```yaml
id: UJ-010
title: Provision a paid subscription
actors: [administrator]
surface: onboarding-wizard
goal: Authenticated Press.Zone account provisions selected subscription for this site and continues to language setup.
trigger: Activate Continue with Card after selecting plan and billing cycle at /wp-admin/admin.php?page=international-press-zone#/onboarding.
fixtures: [authenticated-admin, authenticated-presszone-onboarding-session, purchasable-plan]
success_state:
  visible: "Configure Your Languages" renders with active plan retained.
  durable: License key, API key, active tier, expiry, site limit, and language limit are persisted.
  persistence: Fresh onboarding status returns active subscription for this site.
source_specs: [admin/src/pages/onboarding.js, includes/Translation/OnboardingApi.php]
readiness: draft
canonical: false
blockers: []
```

## Path

| Hop | Evidence |
|---|---|
| UI trigger | `admin/src/pages/onboarding.js:641` |
| Request construction | `admin/src/pages/onboarding.js:662` |
| Endpoint auth and parse | `includes/Translation/OnboardingApi.php:85` |
| Authoritative write | `includes/Translation/OnboardingApi.php:379` |
| Response | `includes/Translation/OnboardingApi.php:400` |
| Terminal render | `admin/src/pages/onboarding.js:812` |

## Happy path

### H1
- Setup: WordPress administrator authenticated; onboarding JWT valid; selected plan is purchasable; site has no active subscription.
- Action: Select plan and billing cycle, then activate `Continue with Card`.
- Request: `POST /wp-json/international-press-zone/v1/onboarding/checkout`.
- Response: `200` with `{success:true,license_key:<key>,tier:<tier>,credits_allocated:<integer>}`.
- Visible: `Configure Your Languages` renders and wizard proceeds to language setup with selected tier retained.
- Durable: License key and API key stores contain returned credentials; license status is `active`; tier, expiry, site limit, and language limit match backend response; onboarding JWT is removed.
- Fresh read: `GET /wp-json/international-press-zone/v1/onboarding/status` returns `200` with active configured entitlement.
- Forbidden: No duplicate subscription, duplicate credential set, or language/content mutation occurs during checkout.
- Evidence:
  - Setup: `includes/Translation/OnboardingApi.php:327`
  - Action: `admin/src/pages/onboarding.js:641`
  - Request: `admin/src/pages/onboarding.js:662`
  - Response: `includes/Translation/OnboardingApi.php:400`
  - Visible: `admin/src/pages/onboarding.js:812`
  - Durable: `includes/Translation/OnboardingApi.php:379`
  - Fresh read: `includes/Translation/OnboardingApi.php:158`
  - Forbidden: `includes/Translation/OnboardingApi.php:396`

## Alternate and failure paths

### A1
- Setup: WordPress administrator authenticated; onboarding JWT missing; selected plan valid.
- Action: Activate `Continue with Card`.
- Request: `POST /wp-json/international-press-zone/v1/onboarding/checkout`.
- Response: `401` with `{error:"SESSION_EXPIRED",message:"Onboarding session expired. Please register or login again."}`.
- Visible: `Onboarding session expired. Please register or login again.` renders; checkout remains recoverable.
- Durable: No license, API key, subscription metadata, or credential state changes.
- Fresh read: `GET /wp-json/international-press-zone/v1/onboarding/status` returns `200` without a newly active subscription.
- Forbidden: No backend checkout call, subscription, charge, credential write, or language mutation occurs.
- Evidence:
  - Setup: `includes/Translation/OnboardingApi.php:328`
  - Action: `admin/src/pages/onboarding.js:641`
  - Request: `admin/src/pages/onboarding.js:662`
  - Response: `includes/Translation/OnboardingApi.php:331`
  - Visible: `admin/src/pages/onboarding.js:671`
  - Durable: `includes/Translation/OnboardingApi.php:328`
  - Fresh read: `includes/Translation/OnboardingApi.php:158`
  - Forbidden: `includes/Translation/OnboardingApi.php:328`

## Permissions and boundaries

### P1
- Setup: Actor lacks `manage_options`; valid onboarding session and plan otherwise exist.
- Action: Submit checkout request.
- Request: `POST /wp-json/international-press-zone/v1/onboarding/checkout`.
- Response: `401` with `{code:"rest_forbidden",message:"Sorry, you are not allowed to do that.",data:{status:401}}`.
- Visible: REST denial exposes no credentials, account, subscription, or pricing secrets.
- Durable: No WordPress option or backend subscription changes.
- Fresh read: Protected onboarding status returns the same permission denial.
- Forbidden: No checkout, charge, credential write, or account disclosure occurs.
- Evidence:
  - Setup: `includes/Translation/OnboardingApi.php:152`
  - Action: `includes/Translation/OnboardingApi.php:87`
  - Request: `includes/Translation/OnboardingApi.php:85`
  - Response: `includes/Translation/OnboardingApi.php:152`
  - Visible: `includes/Translation/OnboardingApi.php:152`
  - Durable: `includes/Translation/OnboardingApi.php:152`
  - Fresh read: `includes/Translation/OnboardingApi.php:35`
  - Forbidden: `includes/Translation/OnboardingApi.php:152`

## Source specs

- `admin/src/pages/onboarding.js`
- `includes/Translation/OnboardingApi.php`
