Files
greeneclipse 8580c996c3 Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
2026-08-09 22:47:43 +02:00

4.1 KiB
Raw Permalink Blame History

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.goAssertProcessingFeatures
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 (nondry-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 ErrFeatureDisabled402 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)
  • EnsureDefaultFeatureSeeds called from EnsureDefaultPlans
  • CreditsOverview /auth/me embed effective features
  • Admin Permissions UI + dashboard gating docs present

Remaining blockers

  1. Migrate required — writes to plans.features / platform_feature_gates need 026 applied (.\scripts\migrate.ps1). Resolve falls back without column but admin PUT fails closed with a clear error.
  2. Not every route is AssertFeature'd — list/read endpoints and many store/feed mutations are still UI-gated only. Extend using RequireFeature or AssertFeature when a section is product-critical.
  3. OpenAPI — session fragment lives in 05-openapi-fragment.yaml; public /api/v1/openapi.yaml intentionally unchanged. Optional: merge fragment into internal docs.
  4. Numeric marketing limits (feed source count, export count, storage GB) remain documentation-only — not feature keys with counters.
  5. Agent 9 UI — confirm live that nav hides after capabilities load; stub mode in admin UI should clear once APIs return 200.
  6. EPRELcapability.eprel is ON for Free in the matrix; product docs historically disagreed with code (CanUseEPREL always 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