7.7 KiB
7.7 KiB
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
- Start the local platform stack.
export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail up -d
- Ensure one platform user has directory visibility plus the current dedicated commercial-management capability.
- Ensure one workspace member can view workspace settings, one operator can complete onboarding, and one reporting operator can manage review-pack generation.
- 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
- Open
/system/directory/workspaces/{workspace}as the authorized platform user. - 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
- Use
Update subscription truthto save atrialrecord withtrial_ends_atand status reason. - Confirm the page updates immediately and the derived lifecycle resolves to
trial. - Repeat with
active,past_due,cancel_at_period_end, andended. - Backdate a
trialorcancel_at_period_enddate and confirm the system page surfaces that the subscription record needs review without auto-transitioning state. - Confirm every explicit update requires status reason, explicit confirmation, and remains auditable.
Scenario 2: Preserve fallback behavior when no subscription record exists
- Use a workspace with no current subscription record.
- Confirm the system detail page marks the commercial posture as fallback-backed.
- If the workspace has an explicit manual lifecycle state from current repo truth, confirm that state still drives the derived lifecycle.
- If the workspace has no explicit lifecycle state either, confirm the workspace still resolves to the current default posture of
active_paid. - Confirm the fallback
Change commercial stateaction remains available only while no subscription record exists. - 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
- Open
/admin/onboarding/{onboardingDraft}for a workspace with anactivesubscription and an allowed entitlement substrate. - Confirm the completion step allows
Complete onboardingand that the commercial explanation is subscription-backed. - Switch the same workspace to
past_duefrom the system plane. - 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
- 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
- Use a workspace with an
activesubscription where the underlying review-pack entitlement allows generation. - 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
- Confirm the existing queued-start UX remains unchanged when allowed.
- Change the same workspace to
endedfrom the system plane. - Repeat the same start actions and confirm:
- each surface shows the same lifecycle-based reason
- no new
ReviewPackrow is created - no new
OperationRunrow is created - no queued or terminal review-pack notification is emitted for the blocked attempt
- 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
- Keep a workspace in a state where review-pack generation is blocked.
- Open an already-generated review pack through the current detail or download path.
- Confirm the artifact is still viewable or downloadable under current RBAC.
- Open the current customer-workspace pack access path for the same workspace.
- 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
- Open
/admin/settings/workspaceas an authorized workspace manager. - 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
- Switch the current subscription state from the system plane and refresh the settings page.
- Confirm the read-only summary updates accordingly.
RBAC and Plane Semantics Checks
- Access subscription mutation from
/adminand confirm there is no self-service control surface. - Access
/system/directory/workspaces/{workspace}as a platform user lacking the dedicated capability and confirm authorization is enforced without leaking admin-plane truth. - Access onboarding or review-pack surfaces as a non-member or wrong-plane actor and confirm 404.
- Access the same surfaces as an established-scope actor lacking the relevant capability and confirm 403.
- 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
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