# Quickstart: Billing & Subscription Truth Layer v1

**Date**: 2026-05-04  
**Branch**: `274-billing-subscription-truth`

This quickstart is the intended reviewer flow after implementation. It stays bounded to current subscription truth, lifecycle derivation, and the existing onboarding or review-pack gates.

## Prerequisites

1. Start the local platform stack.
   - `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail up -d`
2. Ensure one platform user has directory visibility plus the current dedicated commercial-management capability.
3. Ensure one workspace member can view workspace settings, one operator can complete onboarding, and one reporting operator can manage review-pack generation.
4. Seed or factory-create:
   - one workspace with no subscription record and no explicit manual lifecycle override
   - one workspace with a current subscription record in `trial`
   - one workspace with a current subscription record in `past_due`
   - one onboarding draft in a subscription-backed workspace
   - one tenant with an existing review and generated review pack in a subscription-backed workspace

## Scenario 1: Record or update current subscription truth from the system plane

1. Open `/system/directory/workspaces/{workspace}` as the authorized platform user.
2. Confirm the page shows:
   - current subscription status or an explicit fallback indicator when no subscription record exists
   - derived commercial posture
   - next relevant date
   - reference and last changed attribution
3. Use `Update subscription truth` to save a `trial` record with `trial_ends_at` and status reason.
4. Confirm the page updates immediately and the derived lifecycle resolves to `trial`.
5. Repeat with `active`, `past_due`, `cancel_at_period_end`, and `ended`.
6. Backdate a `trial` or `cancel_at_period_end` date and confirm the system page surfaces that the subscription record needs review without auto-transitioning state.
7. Confirm every explicit update requires status reason, explicit confirmation, and remains auditable.

## Scenario 2: Preserve fallback behavior when no subscription record exists

1. Use a workspace with no current subscription record.
2. Confirm the system detail page marks the commercial posture as fallback-backed.
3. If the workspace has an explicit manual lifecycle state from current repo truth, confirm that state still drives the derived lifecycle.
4. If the workspace has no explicit lifecycle state either, confirm the workspace still resolves to the current default posture of `active_paid`.
5. Confirm the fallback `Change commercial state` action remains available only while no subscription record exists.
6. Confirm no subscription-specific mutation or admin-plane readout leaks outside the current workspace and platform scopes.

## Scenario 3: Keep onboarding activation on the existing lifecycle gate

1. Open `/admin/onboarding/{onboardingDraft}` for a workspace with an `active` subscription and an allowed entitlement substrate.
2. Confirm the completion step allows `Complete onboarding` and that the commercial explanation is subscription-backed.
3. Switch the same workspace to `past_due` from the system plane.
4. Refresh the onboarding draft and confirm:
   - the action remains visible for an otherwise authorized actor
   - the step explains the grace posture as a business-state block
   - no tenant activation occurs
5. Repeat with a workspace that has no subscription record but does have a fallback manual lifecycle block and confirm the step explains the fallback source rather than pretending a subscription exists.

## Scenario 4: Keep review-pack generation on the existing lifecycle gate

1. Use a workspace with an `active` subscription where the underlying review-pack entitlement allows generation.
2. Trigger the current start family from:
   - the tenant dashboard review-pack card
   - the review register export action
   - the tenant review detail export action
   - the review-pack detail regenerate action
3. Confirm the existing queued-start UX remains unchanged when allowed.
4. Change the same workspace to `ended` from the system plane.
5. Repeat the same start actions and confirm:
   - each surface shows the same lifecycle-based reason
   - no new `ReviewPack` row is created
   - no new `OperationRun` row is created
   - no queued or terminal review-pack notification is emitted for the blocked attempt
6. Confirm a workspace without a subscription record still follows its fallback lifecycle state exactly as before.

## Scenario 5: Preserve current review-pack and customer-workspace access

1. Keep a workspace in a state where review-pack generation is blocked.
2. Open an already-generated review pack through the current detail or download path.
3. Confirm the artifact is still viewable or downloadable under current RBAC.
4. Open the current customer-workspace pack access path for the same workspace.
5. Confirm current read-only pack access remains unchanged by the new subscription truth layer.

## Scenario 6: Show a read-only commercial summary on workspace settings

1. Open `/admin/settings/workspace` as an authorized workspace manager.
2. Confirm the page shows:
   - the current commercial posture
   - whether the posture is subscription-backed or fallback-backed
   - the next relevant date when present
   - a concise explanation without mutation controls
3. Switch the current subscription state from the system plane and refresh the settings page.
4. Confirm the read-only summary updates accordingly.

## RBAC and Plane Semantics Checks

1. Access subscription mutation from `/admin` and confirm there is no self-service control surface.
2. Access `/system/directory/workspaces/{workspace}` as a platform user lacking the dedicated capability and confirm authorization is enforced without leaking admin-plane truth.
3. Access onboarding or review-pack surfaces as a non-member or wrong-plane actor and confirm 404.
4. Access the same surfaces as an established-scope actor lacking the relevant capability and confirm 403.
5. Access the action as an otherwise authorized actor whose workspace is blocked by the derived lifecycle and confirm a truthful business-state block instead of 403 or 404.

## Targeted Validation Commands

```bash
export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Entitlements/WorkspaceSubscriptionResolverTest.php tests/Unit/Entitlements/WorkspaceCommercialLifecycleResolverTest.php

export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/System/ViewWorkspaceEntitlementsTest.php tests/Feature/System/Spec113/AuthorizationSemanticsTest.php tests/Feature/Filament/Settings/WorkspaceEntitlementsSettingsPageTest.php

export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Onboarding/ManagedTenantOnboardingEntitlementTest.php tests/Feature/ReviewPack/ReviewPackEntitlementEnforcementTest.php tests/Feature/ReviewPack/ReviewPackGenerationTest.php tests/Feature/ReviewPack/ReviewPackDownloadTest.php tests/Feature/Reviews/CustomerReviewWorkspacePackAccessTest.php

export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent
```

## Out of Scope Confirmations

While validating this slice, confirm that the implementation does not add or imply:

- payment-provider credentials, invoices, checkout, taxes, or public pricing UI
- customer-account, contract, or CRM models
- webhook or schedule-driven state transitions
- a second admin-plane commercial management surface
- a second runtime gate outside `WorkspaceCommercialLifecycleResolver`
- a multi-row subscription ledger or history browser
