# Phase 1 Platform Capability Gap Report

Audience: AI coding agents first. Build every `NOT-IMPLEMENTED` or `FAIL` row before claiming its listed MR gate.

Target: `https://press-zone.dry-salad-ffa1.workers.dev`  
Worker version: `32ba9710`  
Run: `BASE_URL=<target> CAPABILITY_BASE_URL=<target> npm run test:capability -- --adapter=platform`  
Observed exit: `1` (expected red gap run)

## Summary

- Outcomes: `PASS=1`, `NOT-IMPLEMENTED=9`, `BLOCKED-ON-INFRA=4`, `FAIL=1`, `DROPPED=3`.
- Route double-prefix: **NOT-REPRODUCED**. Runtime mounts `createPluginRoute()` at `/api`; route declares `/plugin/:plugin`, producing `/api/plugin/:plugin`. Live canonical probe reached auth (`401 UNAUTHORIZED`); obsolete `/api/api/...` suspicion does not match deployed source.
- OAuth seat-cap enforcement: **CONFIRMED**. `/oauth/authorize` delegates directly to provider authorization; token persistence inserts `sites` without counting active sites or reading `subscription_packages.seats_config`.
- Subscribe approval URL omission: **CONFIRMED**. `POST /api/subscribe` returns account/plugin/tier/status/PayPal-subscription/period/wallet identifiers only; no approval URL exists in `SubscribeAccountResult`.
- Credential fixture: **BLOCKED-ON-INFRA**. Public Worker has no account/session bootstrap. `/oauth/token` requires an existing `account_id`; usable entitlement requires session-authenticated `/api/subscribe`, which creates a live PayPal subscription. No platform credential fixture variables were available. Direct DB writes and fake PayPal/Morning data were not used.

## Ordered Spec 2 build backlog

1. **CAP-05:** enforce seat cap atomically during OAuth connect before site/credential persistence.
2. **CAP-01:** implement synchronous single/bulk translation dialects and exact usage response fields.
3. **CAP-03:** implement character estimate for every target language and contract error envelope.
4. **CAP-04:** implement account/site-scoped exception full-replace and paginated fetch.
5. **CAP-02:** implement job submission, durable status/polling, signed callbacks, and idempotent recovery.
6. **CAP-06:** implement site heartbeat and idempotent deactivation.
7. **CAP-07:** expose public purchasable International plans with onboarding-consumed fields.
8. **CAP-12:** implement license lifecycle compatibility or atomically migrate every caller to OAuth/site lifecycle.
9. **CAP-13:** expose signed, versioned plugin update metadata.

## Capability outcomes

| Capability | Outcome | Unearned MR gate(s) | Concrete missing work |
|---|---|---|---|
| CAP-01 | NOT-IMPLEMENTED | MR-04 | Add `/api/translate` and bulk translation handlers with exact character usage; no translation route exists. |
| CAP-02 | NOT-IMPLEMENTED | MR-04, MR-08 | Add job submission, persistence/polling, signed callback delivery, and idempotent recovery. |
| CAP-03 | NOT-IMPLEMENTED | MR-04 | Add `/api/estimate` with multi-target estimates and contract errors. |
| CAP-04 | NOT-IMPLEMENTED | MR-04 | Add exception dictionary push/pull persistence scoped to account/site. |
| CAP-05 | NOT-IMPLEMENTED | MR-04, MR-09 | Add atomic active-site count versus subscribed `seats_config` before OAuth site insert. |
| CAP-06 | NOT-IMPLEMENTED | MR-04, MR-09 | Add credential-authenticated heartbeat plus idempotent disconnect/deactivation route. |
| CAP-07 | NOT-IMPLEMENTED | MR-04 | Add public plan-list endpoint; live `/api/plans?plugin=international` returned `401`, not `200`. |
| CAP-08 | DROPPED | MR-04 | No build: platform session login plus OAuth2 authorization-code/PKCE replaces legacy registration/login. |
| CAP-09 | DROPPED | MR-04 | No build: live PayPal subscription plus OAuth provisioning replaces mock checkout/upgrade. |
| CAP-10 | BLOCKED-ON-INFRA | MR-04, MR-10 | Provide API-obtainable session/account fixture and PayPal approval path; response must include approval URL. |
| CAP-11 | DROPPED | MR-04 | No build: PayPal webhooks replace checkout polling; OAuth exchange provisions credentials. |
| CAP-12 | NOT-IMPLEMENTED | MR-04, MR-09 | Add activate/deactivate/validate/status compatibility or migrate all licensing callers atomically. |
| CAP-13 | NOT-IMPLEMENTED | MR-04 | Add update metadata route; live `/api/updates/check` returned `401`, not `200`. |
| CAP-14 | PASS | — | None; live `/health` returned `200` with `{data:{ok:true}}`. |
| CAP-15 | BLOCKED-ON-INFRA | MR-04, MR-05 | Provide API-only entitled credential fixture to verify accepted credential alongside invalid rejection. |
| CAP-16 | BLOCKED-ON-INFRA | MR-04, MR-05, MR-21 | Provide API-only revoked and wrong-plugin credential fixtures. |
| CAP-17 | BLOCKED-ON-INFRA | MR-04, MR-07, MR-21 | Provide API-only funded and insufficient-credit fixtures for translate/forum wallet assertions. |
| CAP-18 | FAIL | MR-04, MR-06 | Return `Retry-After` on global `429`; then verify per-credential throttling, retry, login throttling, and bulk tolerance. |

## Evidence rules

- Machine output: `docs/contracts/phase1-gap-report.json`.
- Reporter records missing fixture configuration as `FAIL`; this report adjudicates those rows as `BLOCKED-ON-INFRA` because public API cannot create required fixtures without external session/account and live PayPal state.
- Source evidence: `/tmp/press-zone-product/backend/api/src/app.ts`, `routes/oauth.ts`, `routes/plugin.ts`, and `routes/subscribe.ts` from product checkout version stated above.
- No backend feature, harness assertion, database row, PayPal object, or Morning object was created for this measurement.
