Files

81 lines
4.1 KiB
Markdown
Raw Permalink Normal View 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](./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` (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 `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)
- `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. **EPREL**`capability.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 |