## Summary - add the bounded workspace commercial lifecycle overlay from spec 251 on top of the existing entitlement substrate - expose audited commercial state inspection and mutation on the system workspace detail surface - gate onboarding activation and review-pack start actions through the shared lifecycle decision while preserving suspended read-only access to existing review, evidence, and generated-pack history - add focused Pest coverage plus the spec/plan/tasks/data-model/contract artifacts for the feature ## Validation - targeted Pest unit and feature lanes for lifecycle resolution, system-plane mutation, onboarding gating, review-pack enforcement, download preservation, customer review workspace access, and evidence snapshot access - `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` - integrated browser smoke on the system workspace detail and the preserved read-only review/evidence/review-pack surfaces ## Notes - branch: `251-commercial-entitlements-billing-state` - base: `dev` - commit: `606e9760` Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #292
33 KiB
Implementation Plan: Commercial Entitlements and Billing-State Maturity
Branch: 251-commercial-entitlements-billing-state | Date: 2026-04-28 | Spec: /Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/251-commercial-entitlements-billing-state/spec.md
Input: Feature specification from /Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/251-commercial-entitlements-billing-state/spec.md
Note: This template is filled in by the /speckit.plan command. See .specify/scripts/ for helper scripts.
Summary
- Layer one bounded workspace commercial lifecycle overlay on top of the already-real Spec 247 entitlement substrate, not beside it. The existing
WorkspaceEntitlementResolverremains canonical for plan/default/override truth, and the new slice adds one explicit lifecycle state plus action-family outcomes for onboarding activation, review-pack start, and preserved read-only history access. - Keep mutation narrow and platform-owned: persist lifecycle state through the existing workspace settings infrastructure, expose inspection plus state change from the existing system workspace detail surface, and keep
/adminlimited to contextual allow, warn, or block messaging on onboarding and review-pack surfaces. - Preserve current review/evidence/download truth while suspended. New lifecycle blocking must stop future onboarding activation and future review-pack starts before any tenant mutation,
ReviewPack, orOperationRuncreation, while leaving already-generated history and evidence consumption under current RBAC intact.
Technical Context
Language/Version: PHP 8.4 (Laravel 12)
Primary Dependencies: Filament v5 + Livewire v4, existing workspace settings stack (SettingsRegistry, SettingsResolver, SettingsWriter), WorkspaceEntitlementResolver, ReviewPackService, system directory detail page
Storage: PostgreSQL via existing workspace_settings rows plus existing audit log records; no new table or billing/account model
Testing: Pest unit and feature tests via Laravel Sail
Validation Lanes: fast-feedback, confidence
Target Platform: Monorepo Laravel web application in apps/platform, using existing Filament admin and system panels
Project Type: web
Performance Goals: Reuse existing settings reads and current workspace aggregates only, add no new external calls during render, keep review-pack dedupe and shared run UX unchanged when allowed, and short-circuit blocked review-pack starts before any ReviewPack or OperationRun write
Constraints: One commercial lifecycle overlay only, four bounded states, two real gated behavior families, preserved authorized read-only history/evidence/download access while suspended, explicit /admin vs /system separation, no payment provider/invoice/checkout/website/broad billing-engine scope
Scale/Scope: One bounded lifecycle resolver, one system-plane mutation surface, one platform capability addition, one onboarding gate, one review-pack action-family gate, and focused lifecycle/read-only test coverage
Filament v5 / Panel Notes
- Livewire v4.0+ compliance: The slice stays inside existing Filament v5 pages, widgets, resources, and Livewire-backed actions. No Livewire v3 assumptions or compatibility work are introduced.
- Provider registration location: No panel/provider registration changes are planned. Existing Laravel 12 + Filament provider registration remains in
bootstrap/providers.php. - Global search: No new globally searchable resource is introduced. Current global-search behavior remains unchanged.
- Destructive and high-impact actions: The future
Change commercial stateaction on the system workspace detail page must use->requiresConfirmation(), require platform authorization, and write audit history. TheSuspended / read-onlytransition is the only high-risk path in scope. Review-pack and onboarding blocks remain non-destructive business-state responses, not hidden authorization failures. - Asset strategy: No new panel or shared assets are planned. Deployment remains unchanged, including
cd apps/platform && php artisan filament:assetswhen registered Filament assets are deployed elsewhere in the product.
UI / Surface Guardrail Plan
- Guardrail scope: changed surfaces
- Native vs custom classification summary: mixed
- Shared-family relevance: system detail controls, status messaging, onboarding helper text, review-pack action gating, review/evidence viewer messaging
- State layers in scope: page, detail
- Audience modes in scope: operator-MSP, support-platform, customer/read-only
- Decision/diagnostic/raw hierarchy plan: decision-first on the system workspace detail surface and on the immediate onboarding/review-pack action context; diagnostics-second via the existing entitlement substrate and review/run/history context; no new raw/support payload surface is planned
- Raw/support gating plan: capability-gated system-plane inspection only; customer/read-only surfaces remain calm and evidence-first
- One-primary-action / duplicate-truth control:
/system/directory/workspaces/{workspace}remains the only mutation surface; onboarding and review-pack surfaces show only the local lifecycle consequence required for the immediate action; suspended read-only history pages do not restate the whole commercial profile - Handling modes by drift class or surface: review-mandatory because one lifecycle vocabulary must stay consistent across system, onboarding, review-pack, and read-only history surfaces
- Repository-signal treatment: review-mandatory
- Special surface test profiles: standard-native-filament, shared-detail-family, monitoring-state-page
- Required tests or manual smoke: functional-core, state-contract
- Exception path and spread control: no second admin-plane commercial mutation surface, no page-local lifecycle labels, and no broad suspension sweep across unrelated mutable surfaces
- Active feature PR close-out entry: Guardrail
Shared Pattern & System Fit
- Cross-cutting feature marker: yes
- Systems touched:
SettingsRegistry,SettingsResolver,SettingsWriter, existing workspace-setting audit path,WorkspaceEntitlementResolver,WorkspaceSettingsas the current entitlement substrate reference,App\Filament\System\Pages\Directory\ViewWorkspace,ManagedTenantOnboardingWizard,ReviewPackService,TenantReviewPackCard,ReviewRegister,TenantReviewResource,ReviewPackResource,CustomerReviewWorkspace,EvidenceSnapshotResource, andWorkspaceEntitlementBlockedException - Shared abstractions reused:
WorkspaceEntitlementResolver,WorkspacePlanProfileCatalog,SettingsResolver,SettingsWriter, current workspace audit logging,ReviewPackService,OperationUxPresenter,OperationRunLinks,Capabilities,PlatformCapabilities, and existing Filament action/resource surfaces - New abstraction introduced? why?: one bounded
WorkspaceCommercialLifecycleResolveris justified because the existing entitlement resolver answers per-key entitlement truth but does not express one workspace-wide lifecycle posture with action-family outcomes, preserved read-only semantics, or system/admin messaging - Why the existing abstraction was sufficient or insufficient: Spec 247 already provides canonical entitlement substrate truth and must remain the foundation. It is insufficient for
trial,grace,active_paid, andsuspended_read_onlybecause those states cut across more than one entitlement key and need one central business-state explanation - Bounded deviation / spread control: no page-local lifecycle conditionals and no second exception taxonomy by default; prefer reusing the existing blocked decision payload/catch path for review-pack actions unless implementation proves that the current class name or payload cannot carry lifecycle metadata cleanly
OperationRun UX Impact
- Touches OperationRun start/completion/link UX?: yes
- Central contract reused: existing shared review-pack OperationRun start UX through
ReviewPackService,OperationUxPresenter, andOperationRunLinks - Delegated UX behaviors: queued toast, run link, run-enqueued browser event, dedupe messaging, and existing terminal notifications remain unchanged when review-pack generation is allowed; lifecycle-blocked starts create no
OperationRun, no queued DB notification, and no terminal notification - Surface-owned behavior kept local: onboarding completion helper text, review-pack tooltips/disabled state, and suspended read-only explanation on history surfaces remain local projections of the central lifecycle decision
- Queued DB-notification policy: unchanged explicit opt-in only
- Terminal notification path: unchanged central lifecycle mechanism for existing review-pack runs only
- Exception path: none planned; lifecycle blocking must happen before
ReviewPackServicecreates or reuses aReviewPackorOperationRun, and the preferred later implementation is to extend the current blocked-decision payload rather than invent a second parallel business-state exception family
Provider Boundary & Portability Fit
- Shared provider/platform boundary touched?: no
- Provider-owned seams: N/A
- Platform-core seams: workspace commercial lifecycle vocabulary, lifecycle rationale, action-family outcomes, system/admin messaging, and audit semantics
- Neutral platform terms / contracts preserved:
workspace,trial,grace,active paid,suspended / read-only,commercial state,review pack,managed tenant activation - Retained provider-specific semantics and why: none; review-pack generation stays provider-backed operationally, but the new lifecycle vocabulary remains platform-core and provider-neutral
- Bounded extraction or follow-up path: none
Constitution Check
GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.
- Inventory-first: PASS - the slice adds workspace-owned business state, not new inventory or backup truth.
- Read/write separation: PASS - the only new write is a confirmation-protected, audited system-plane lifecycle mutation using existing workspace settings persistence.
- Graph contract path: PASS - no new Microsoft Graph path is introduced.
- Deterministic capabilities: PASS - admin-plane capabilities remain unchanged, and any new platform capability stays registry-backed.
- RBAC-UX: PASS -
/adminand/systemremain separated; wrong-plane and non-member access stay 404; member-without-capability stays 403; otherwise-authorized actors get a business-state block or warning instead of authorization failure. - Workspace isolation: PASS - admin-plane contextual behavior still requires established workspace context.
- RBAC-UX destructive confirmation: PASS - the future system-plane state-change action must require confirmation and rationale.
- RBAC-UX global search: PASS - no new searchable resource or search scope is introduced.
- Tenant isolation: PASS - onboarding, review-pack, review history, evidence, and download surfaces remain tenant-safe.
- Run observability: PASS - review-pack generation keeps the existing
OperationRunpath when allowed, and blocked starts stop before run creation. - OperationRun start UX: PASS - the plan preserves shared review-pack start UX and inserts lifecycle blocking before run creation.
- Ops-UX 3-surface feedback: PASS - existing feedback stays toast + progress surfaces + terminal notification only when a run exists.
- Ops-UX lifecycle: PASS - no new
OperationRunlifecycle contract is introduced. - Ops-UX summary counts: N/A - no
summary_countsshape change is planned. - Ops-UX guards: N/A - no new run guard family is planned in the planning slice.
- Ops-UX system runs: N/A - initiator-null behavior is unchanged.
- Automation: N/A - no new queued or scheduled workflow family is introduced.
- Data minimization: PASS - no payment payloads, account records, or provider secrets are introduced.
- Test governance (TEST-GOV-001): PASS - the plan stays in focused unit + feature lanes with explicit proof commands and limited fixture growth.
- Proportionality (PROP-001): PASS - persistence stays in existing settings rows, and the only new structural element is one bounded lifecycle overlay.
- No premature abstraction (ABSTR-001): PASS - no interface, registry, strategy system, or framework is planned; only one local resolver is added because multiple real surfaces already need the same lifecycle decision.
- Persisted truth (PERSIST-001): PASS - no new table or durable artifact is introduced.
- Behavioral state (STATE-001): PASS -
graceandsuspended_read_onlycreate distinct action-family consequences immediately, andtrialremains justified because it is part of the explicit platform-managed commercial posture and audit workflow even though its two in-scope gated families currently matchactive_paid. - UI semantics (UI-SEM-001): PASS - the plan prefers direct mapping from lifecycle truth to helper text and badges instead of a new presentation framework.
- Shared pattern first (XCUT-001): PASS - system detail, onboarding, review-pack, and read-only history surfaces all reuse the existing substrate and shared run path first.
- Provider boundary (PROV-001): PASS - the new vocabulary is platform-core, not Microsoft-shaped.
- V1 explicitness / few layers (V1-EXP-001, LAYER-001): PASS - one explicit state family plus one thin overlay resolver is the narrowest viable shape.
- Spec discipline / bloat check (SPEC-DISC-001, BLOAT-001): PASS - the plan keeps the whole lifecycle overlay in one coherent spec and includes proportionality review below.
- Badge semantics (BADGE-001): PASS - any future lifecycle badge must reuse shared badge semantics or stay plain text; no page-local color taxonomy is planned.
- Filament-native UI (UI-FIL-001): PASS - the slice extends existing Filament pages, resources, widgets, and the current system Blade page.
- Filament-native UI local Blade/Tailwind: PASS - the existing system Blade view remains the only custom-rendered surface in scope and must preserve current Filament visual language.
- UI/UX surface taxonomy (UI-CONST-001 / UI-SURF-001): PASS - existing system detail, guided onboarding, action family, and read-only viewer surface types remain intact.
- Decision-first operating model (DECIDE-001): PASS - system workspace detail is primary, onboarding/review-pack surfaces stay contextual, and read-only history/evidence pages remain tertiary evidence/diagnostics.
- Audience-aware disclosure (DECIDE-AUD-001 / OPSURF-001): PASS - system detail stays platform/support-facing, admin action gates stay operator-first, and suspended read-only pages keep customer-safe history access without raw platform diagnostics.
- UI/UX inspect model (UI-HARD-001): PASS - no duplicate inspect affordances are added.
- UI/UX action hierarchy (UI-HARD-001 / UI-EX-001): PASS - the plan keeps one system mutation action and existing onboarding/review-pack primary actions in place.
- UI/UX scope, truth, and naming (UI-HARD-001 / UI-NAMING-001 / OPSURF-001): PASS - labels remain narrow and billing-provider-free.
- UI/UX placeholder ban (UI-HARD-001): PASS - no empty action groups are planned.
- UI naming (UI-NAMING-001): PASS - primary labels stay
Change commercial state,Complete onboarding,Generate pack,Regenerate, andExport executive pack. - Operator surfaces (OPSURF-001): PASS - mutation scope remains explicit, and
/adminsurfaces only show contextual lifecycle truth. - Operator surface page contract: PASS - the spec already defines the required surface contracts.
- Filament UI Action Surface Contract: PASS - touched surfaces already have contracts or exemptions; the plan preserves them while adding lifecycle truth.
- Filament UI UX-001 (Layout & IA): PASS - no new page shell or panel is introduced.
- Action-surface discipline (ACTSURF-001 / HDR-001): PASS - one system primary action and existing onboarding/review-pack action families remain the only primary mutations in scope.
- UI review workflow: PASS - guardrail, shared-family, and exception posture remain explicit in this plan.
Test Governance Check
- Test purpose / classification by changed surface:
Unitfor the bounded lifecycle overlay and behavior matrix;Featurefor system-plane mutation, onboarding activation gating, review-pack start blocking, and preserved suspended read-only consumption - Affected validation lanes:
fast-feedback,confidence - Why this lane mix is the narrowest sufficient proof: the business risk is deterministic decision ordering plus existing Filament/Livewire and service entry points. Browser or heavy-governance coverage would add cost without proving additional current-release risk for this bounded overlay.
- Narrowest proving command(s):
export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Entitlements/WorkspaceCommercialLifecycleResolverTest.phpexport 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/Onboarding/ManagedTenantOnboardingEntitlementTest.php tests/Feature/Onboarding/OnboardingRbacSemanticsTest.phpexport PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ReviewPack/ReviewPackEntitlementEnforcementTest.php tests/Feature/ReviewPack/ReviewPackGenerationTest.php tests/Feature/ReviewPack/ReviewPackDownloadTest.php tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php tests/Feature/Reviews/CustomerReviewWorkspacePackAccessTest.php tests/Feature/Evidence/EvidenceSnapshotResourceTest.php
- Fixture / helper / factory / seed / context cost risks: limited to workspace, platform user, workspace member, onboarding draft, tenant, existing review pack, tenant review, and evidence snapshot fixtures
- Expensive defaults or shared helper growth introduced?: no - implementation should reuse existing factories and opt-in tenant/review/evidence helpers only
- Heavy-family additions, promotions, or visibility changes: none
- Surface-class relief / special coverage rule: standard-native relief for system detail and onboarding; monitoring-state-page proof for no new run creation; shared-detail-family proof for preserved view/download access while suspended
- Closing validation and reviewer handoff: rerun the exact targeted commands above, verify 404 vs 403 vs business-state outcomes separately, verify system detail source labels remain consistent, verify blocked review-pack starts create no new
ReviewPackorOperationRunand emit no queued or terminal notification, verify already queued or running review-pack runs continue unaffected after later suspension, and verify suspended workspaces still allow authorized review/evidence/download access - Budget / baseline / trend follow-up: none expected beyond ordinary feature-local growth
- Review-stop questions: does the state vocabulary stay narrow enough, does the system/admin split remain intact, does suspended read-only coverage avoid broad mutation-sweep scope, and does the blocked-decision transport avoid a second exception framework
- Escalation path: document-in-feature if only payload wording or helper reuse needs adjustment; follow-up-spec only if the overlay starts pulling unrelated mutable surfaces into suspension logic
- Active feature PR close-out entry: Guardrail
- Why no dedicated follow-up spec is needed: the testing cost stays local to one overlay resolver and a small set of existing pages/services/resources; no new browser or heavy-governance harness is justified
Project Structure
Documentation (this feature)
specs/251-commercial-entitlements-billing-state/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│ └── workspace-commercial-lifecycle-overlay.logical.openapi.yaml
├── checklists/
│ └── requirements.md
└── tasks.md # Created later by /speckit.tasks, not by this plan step
Source Code (repository root)
apps/platform/
├── app/
│ ├── Exceptions/Entitlements/WorkspaceEntitlementBlockedException.php
│ ├── Filament/
│ │ ├── Pages/
│ │ │ ├── Reviews/CustomerReviewWorkspace.php
│ │ │ ├── Reviews/ReviewRegister.php
│ │ │ ├── Settings/WorkspaceSettings.php
│ │ │ └── Workspaces/ManagedTenantOnboardingWizard.php
│ │ ├── Resources/
│ │ │ ├── EvidenceSnapshotResource.php
│ │ │ ├── EvidenceSnapshotResource/Pages/ViewEvidenceSnapshot.php
│ │ │ ├── ReviewPackResource.php
│ │ │ ├── ReviewPackResource/Pages/ViewReviewPack.php
│ │ │ ├── TenantReviewResource.php
│ │ │ └── TenantReviewResource/Pages/ViewTenantReview.php
│ │ ├── System/Pages/Directory/ViewWorkspace.php
│ │ └── Widgets/Tenant/TenantReviewPackCard.php
│ ├── Models/WorkspaceSetting.php
│ ├── Services/
│ │ ├── Entitlements/WorkspaceCommercialLifecycleResolver.php # likely new bounded overlay service
│ │ ├── Entitlements/WorkspaceEntitlementResolver.php
│ │ ├── ReviewPackService.php
│ │ └── Settings/
│ │ ├── SettingsResolver.php
│ │ └── SettingsWriter.php
│ ├── Support/
│ │ ├── Auth/Capabilities.php
│ │ ├── Auth/PlatformCapabilities.php
│ │ └── Settings/SettingsRegistry.php
├── resources/views/filament/system/pages/directory/view-workspace.blade.php
└── tests/
├── Feature/
└── Unit/
Structure Decision: Single Laravel/Filament application inside apps/platform, with one new bounded lifecycle overlay service and changes limited to existing settings persistence, system detail, onboarding, review-pack, and read-only review/evidence/download surfaces plus focused Pest coverage.
Likely Implementation Surfaces
app/Support/Settings/SettingsRegistry.phpto register lifecycle-setting definitions and validation using the existing workspace settings infrastructureapp/Services/Entitlements/WorkspaceCommercialLifecycleResolver.phpas the new bounded overlay, withWorkspaceEntitlementResolver.phpremaining the canonical substrate providerapp/Support/Auth/PlatformCapabilities.phpand related platform authorization helpers for one dedicated commercial-lifecycle management capabilityapp/Filament/System/Pages/Directory/ViewWorkspace.phpandresources/views/filament/system/pages/directory/view-workspace.blade.phpfor read-only summary plus the confirmation-protected state-change actionapp/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.phpfor contextual lifecycle messaging and activation blocking before tenant mutationapp/Services/ReviewPackService.php,app/Filament/Widgets/Tenant/TenantReviewPackCard.php,app/Filament/Pages/Reviews/ReviewRegister.php,app/Filament/Resources/TenantReviewResource.php,app/Filament/Resources/ReviewPackResource.php,app/Filament/Resources/ReviewPackResource/Pages/ViewReviewPack.php, andapp/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.phpfor shared start gating and tooltip/disabled-state reuse- Existing read-only consumption surfaces
CustomerReviewWorkspace.php,ViewTenantReview.php,ViewReviewPack.php,ViewEvidenceSnapshot.php, and the current review-pack download path to prove suspended history/evidence access remains available under existing RBAC - Focused unit and feature tests under
tests/Unit/Entitlements,tests/Feature/System/Directory,tests/Feature/Onboarding,tests/Feature/ReviewPack,tests/Feature/Reviews, andtests/Feature/Evidence
Complexity Tracking
| Violation | Why Needed | Simpler Alternative Rejected Because |
|---|---|---|
One bounded WorkspaceCommercialLifecycleResolver |
Two real gated behavior families plus preserved read-only consumption need one shared workspace-wide decision layered above existing entitlements | Page-local conditionals in onboarding, review-pack resources/widgets, and system detail would drift immediately and undermine business-state consistency |
| Four-state commercial lifecycle vocabulary | Platform operators need one auditable commercial posture that distinguishes trial, grace, active paid, and suspended/read-only on the single system decision surface | Three unlabeled booleans or ad hoc flags would either collapse grace into suspension or lose the explicit platform-side lifecycle state needed for support and audit |
Proportionality Review
- Current operator problem: The repo can already answer per-key entitlement questions, but it cannot say in one place whether a workspace is currently trialing, in grace, fully active paid, or suspended/read-only, nor can it explain why onboarding and review-pack starts are blocked while history remains readable.
- Existing structure is insufficient because:
WorkspaceEntitlementResolverand current workspace settings expose substrate truth only. They do not provide one workspace-wide lifecycle posture, one system-owned mutation path, or one action-family outcome that distinguishes lifecycle blocks from entitlement blocks and authorization failures. - Narrowest correct implementation: Keep persistence inside existing
workspace_settings, add only one four-state lifecycle family plus rationale, derive action-family outcomes in one bounded overlay service, mutate it from one system detail page, and apply it only to onboarding activation, review-pack starts, and preserved read-only history/evidence/download semantics. - Ownership cost created: One new state vocabulary, one overlay service, one platform capability, cross-surface copy discipline, and focused lifecycle/read-only tests.
- Alternative intentionally rejected: A billing/subscription engine, customer-account model, payment-provider seam, or many local page booleans was rejected because the current release only needs a single workspace commercial overlay on top of the already-real entitlement substrate.
- Release truth: current-release truth. The four-state vocabulary is justified now because platform operators already need to set and audit those named postures, even though only
graceandsuspended_read_onlyintroduce new blocked outcomes for the two in-scope action families in this slice.
Phase 0 — Research (output: research.md)
See: /Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/251-commercial-entitlements-billing-state/research.md
Goals:
- Confirm the narrowest reuse of the existing
entitlementssettings domain and audit path for lifecycle state and rationale. - Confirm that one bounded overlay service can compose
WorkspaceEntitlementResolverwithout creating a second commercial framework. - Confirm that lifecycle mutation remains platform-only on the existing system workspace detail page and does not leak into
/adminself-service. - Confirm that review-pack start blocking happens before
ReviewPackorOperationRuncreation and can reuse the current blocked-decision transport. - Confirm that suspended read-only preservation remains bounded to existing review, evidence, and generated-pack consumption surfaces instead of becoming a broad product-wide suspension sweep.
Phase 1 — Design & Contracts (outputs: data-model.md, contracts/, quickstart.md)
See:
/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/251-commercial-entitlements-billing-state/data-model.md/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/251-commercial-entitlements-billing-state/contracts/workspace-commercial-lifecycle-overlay.logical.openapi.yaml/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/251-commercial-entitlements-billing-state/quickstart.md
Design focus:
- Persist
commercial_lifecycle_stateplus rationale through the existingentitlementssettings domain instead of adding a new table or billing domain. - Keep the overlay inside
App\Services\Entitlementsand let it composeWorkspaceEntitlementResolverrather than replacing it. - Extend the existing system workspace detail page with a read-only lifecycle summary and one confirmation-protected
Change commercial stateaction, while leavingWorkspaceSettingsas substrate truth rather than a second mutation plane. - Gate
ManagedTenantOnboardingWizardcompletion from the central lifecycle decision after underlying entitlement truth is known. - Gate review-pack
Generate pack,Regenerate, andExport executive packstarts throughReviewPackServiceand current action surfaces, stopping before anyReviewPackorOperationRunwrite when the lifecycle blocks the action. - Preserve
CustomerReviewWorkspace, review detail, evidence detail, review-pack detail, and pack download access under current RBAC while suspended, and keep any broader mutable-surface suspension work explicitly out of scope.
Phase 1 — Agent Context Update
After Phase 1 artifacts are generated, update Copilot context from the completed plan:
/Users/ahmeddarrazi/Documents/projects/wt-plattform/.specify/scripts/bash/update-agent-context.sh copilot
Phase 2 — Implementation Outline (tasks created later by /speckit.tasks)
- Register lifecycle state and rationale setting definitions under the existing
entitlementssettings domain and wire them into the current workspace-setting audit path. - Add one bounded
WorkspaceCommercialLifecycleResolverthat composes underlying entitlement decisions and yields action-family outcomes plus suspended read-only allowances. - Add one dedicated platform capability for commercial lifecycle management and enforce it on the system detail mutation action only.
- Extend
ViewWorkspaceplus its Blade view with current lifecycle state, affected behavior summary, and a confirmation-protectedChange commercial stateaction. - Gate onboarding completion in
ManagedTenantOnboardingWizardusing the shared lifecycle decision while preserving existing tenant operability checks and 404/403 semantics. - Gate review-pack start surfaces and
ReviewPackServiceusing the shared lifecycle decision, preserving current queued-start UX when allowed and reusing the existing blocked-decision transport when blocked. - Prove suspended read-only continuation by asserting existing review/evidence/download surfaces remain available under current RBAC while no new onboarding activation or review-pack run can start.
- Add focused Sail/Pest unit and feature coverage only.
Constitution Check (Post-Design)
Re-check result: PASS. The design keeps Filament v5 + Livewire v4 compliance intact, leaves provider registration unchanged in bootstrap/providers.php, introduces no new globally searchable resource, keeps asset strategy unchanged, preserves strict /admin vs /system separation, layers one bounded lifecycle resolver above the existing entitlement substrate, and blocks review-pack starts before OperationRun creation rather than forking shared run UX.
Planning Readiness
- Outcome: keep
- No unresolved clarification markers remain in the plan-phase artifacts.
- No application implementation is included in this planning step.
- The next repo-native step is
/speckit.tasksfor an implementation task breakdown, not code changes.
Implementation Close-Out
- Workflow outcome: keep.
- Implementation result: one bounded commercial lifecycle overlay was implemented through existing workspace settings, one system-plane
Change commercial stateaction, onboarding activation gating, review-pack start allow/warn/block semantics, and preserved suspended read-only review/evidence/download access. - Blocked-decision transport: document-in-feature. The existing
WorkspaceEntitlementBlockedExceptiontransport remains sufficient for review-pack blocked starts; no second business-state exception family was introduced. - Preserved read-only scope: document-in-feature. Suspension stays bounded to onboarding activation and new review-pack starts in this spec; broader mutable-surface suspension remains out of scope.
- Browser smoke path:
/system/loginasoperator@tenantpilot.io,/system/directory/workspaces/1, openChange commercial state, setTrialwith rationale, confirm, observe updated lifecycle summary and notification follow-up, then restoreActive paid. - Browser smoke result: pass after fixing
WorkspaceResolverto accept Livewire serialized workspace route parameters; the follow-up notification update no longer emits console errors or 404/419 markers. - Lane results: targeted unit/support/system/onboarding/review-pack/read-only Pest lanes passed; dirty-only Pint passed;
git diff --checkpassed.