Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
4.1 KiB
4.1 KiB
10 — Backend enforcement + integration (agent 10/10)
Status
Enforcement wired for the highest-risk mutating surfaces. Focused resolve/default/custom/global tests added. Docs index: README.md.
Claim gate: run verify / finish_check after tests in this session.
What was enforced
| Surface | Keys checked | Where |
|---|---|---|
Processing StartJob |
FeatureKeysForProcessingType (AI / EPREL / normalize / campaign AI) |
processing/pipeline.go → AssertProcessingFeatures |
| Campaign AI generate | capability.campaign_ai, marketing.campaigns.generate_ai |
campaigns/generate_send.go |
| Campaign live send | capability.email_live_send, marketing.campaigns.send |
campaigns/generate_send.go (non–dry-run) |
| SEO AI apply | capability.seo_ai_rewrite, marketing.seo.ai_rewrite |
seo/service.go |
| API key create | settings.api_keys, capability.api_access |
httpapi/apikey_handlers.go |
| Email blast send | capability.email_live_send, integrations.email.blast |
httpapi/email_handlers.go |
| Brand AI inject | capability.brand_ai_apply, marketing.brand_ai_apply |
AIBrandApplyAllowed |
HTTP: writePlanGate + RequireFeature middleware (httpapi/plan_gate.go). Processing / SEO / campaigns / v1 process map ErrFeatureDisabled → 402 with code=plan_gate, error=feature_disabled, optional feature.
Helpers: FeatureKeyFromError, AssertFeatures, FeatureKeysForProcessingType in billing/feature_enforcement.go.
Tests added
apps/api/internal/billing/feature_enforcement_test.go:
- Free defaults deny AI / API keys
- Custom / Enterprise enable-all
- Global section disable-all (marketing off)
- Custom override false wins
- Capability resolution Starter vs Growth BYOK
- Feature key extraction + processing-type map
Existing: features_api_test.go, custom_package_features_test.go, plan_features_handlers_test.go.
Glue confirmed from siblings
- Migration
026_plan_features.sql - Routes mounted in
server.go(capabilities, plan features, feature-gates, enable/disable-all) EnsureDefaultFeatureSeedscalled fromEnsureDefaultPlans- CreditsOverview /auth/me embed effective features
- Admin Permissions UI + dashboard gating docs present
Remaining blockers
- Migrate required — writes to
plans.features/platform_feature_gatesneed026applied (.\scripts\migrate.ps1). Resolve falls back without column but admin PUT fails closed with a clear error. - Not every route is AssertFeature'd — list/read endpoints and many store/feed mutations are still UI-gated only. Extend using
RequireFeatureorAssertFeaturewhen a section is product-critical. - OpenAPI — session fragment lives in
05-openapi-fragment.yaml; public/api/v1/openapi.yamlintentionally unchanged. Optional: merge fragment into internal docs. - Numeric marketing limits (feed source count, export count, storage GB) remain documentation-only — not feature keys with counters.
- Agent 9 UI — confirm live that nav hides after capabilities load; stub mode in admin UI should clear once APIs return 200.
- EPREL —
capability.eprelis ON for Free in the matrix; product docs historically disagreed with code (CanUseEPRELalways true). Align product copy separately.
Files touched (agent 10)
| File | Intent |
|---|---|
billing/feature_enforcement.go |
Assert helpers + processing key map |
billing/feature_enforcement_test.go |
Defaults / custom / global / resolve tests |
billing/service.go |
Brand AI feature check |
processing/pipeline.go |
Assert before meter gate |
campaigns/generate_send.go |
Generate AI + live send |
seo/service.go |
SEO AI apply |
httpapi/plan_gate.go |
402 writer + RequireFeature |
httpapi/processing_handlers.go / v1_process_handlers.go |
Feature 402 |
httpapi/seo_handlers.go / campaigns_handlers.go |
Feature 402 |
httpapi/apikey_handlers.go / email_handlers.go |
Create/send gates |
docs/plan-permissions/README.md |
System index |
docs/plan-permissions/10-enforcement.md |
This note |