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.
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
# 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` (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)
|
||||
- `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 |
|
||||
Reference in New Issue
Block a user