Automated PR: commit all local changes and add feature 274-billing-subscription-truth. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #326
121 lines
7.7 KiB
Markdown
121 lines
7.7 KiB
Markdown
# 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
|