323 lines
44 KiB
Markdown
323 lines
44 KiB
Markdown
# Implementation Plan: Governance-as-a-Service Packaging v1
|
|
|
|
**Branch**: `260-governance-service-packaging` | **Date**: 2026-05-01 | **Spec**: [spec.md](spec.md)
|
|
**Input**: Feature specification from [spec.md](spec.md)
|
|
|
|
## Summary
|
|
|
|
Prepare one bounded, on-demand management-ready governance package inside the existing customer review workspace and released-review detail flow. The narrow implementation path is to reuse current released-review summary and section truth, the shared `control_interpretation` layer from Spec 259, the existing current-review-pack signed-download seam, and the shared artifact-truth presenter for availability or expiry semantics, while keeping package access read-only, tenant-safe, auditable, localization-ready, and derived.
|
|
|
|
Repo truth already supports the key seams this feature needs: [../../apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php](../../apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php) already exposes `control_readiness`, `evidence_basis`, `recommended_next_action`, and `evidence_proof_state` and audits workspace opens; [../../apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php](../../apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php) already has a customer-workspace-specific read-only mode with `downloadCurrentReviewPackAction()` while keeping `exportExecutivePackAction()` operator-only; [../../apps/platform/app/Services/ReviewPackService.php](../../apps/platform/app/Services/ReviewPackService.php) already provides review-derived pack generation and signed download URLs; and [../../apps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php](../../apps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php) already understands `TenantReview`, `EvidenceSnapshot`, and `ReviewPack` truth.
|
|
|
|
V1 therefore stays narrow: no new panel or provider, no new package artifact family, no new report engine, no schedule or batch flow, no campaign system, no AI summary layer, no PSA or CRM workflow, no package-generation run from the management-ready path, and no cross-tenant packaging.
|
|
|
|
## Technical Context
|
|
|
|
**Language/Version**: PHP 8.4, Laravel 12
|
|
**Primary Dependencies**: Filament v5, Livewire v4, Pest v4, existing `TenantReviewComposer`, `TenantReviewSectionFactory`, `ComplianceEvidenceMappingV1`, `ReviewPackService`, `ArtifactTruthPresenter`, capability helpers, localization copy, and shared audit infrastructure
|
|
**Storage**: PostgreSQL via existing `tenant_reviews`, `tenant_review_sections`, `review_packs`, `evidence_snapshots`, `evidence_snapshot_items`, `stored_reports`, `findings`, `finding_exceptions`, `finding_exception_decisions`, memberships, and `audit_logs`; no new persistence planned
|
|
**Testing**: Pest v4 feature and focused unit coverage plus one bounded browser smoke on the existing review flow
|
|
**Validation Lanes**: confidence, browser
|
|
**Target Platform**: Laravel monolith in `apps/platform`, existing admin plane only (`/admin` plus existing tenant-scoped `/admin/t/{tenant}` reuse)
|
|
**Project Type**: Web application (Laravel monolith with Filament pages/resources)
|
|
**Performance Goals**: keep workspace and released-review rendering DB-only and scope-safe, reuse already composed review summary and section payloads plus current review-pack or evidence truth, and avoid new Graph calls, queue starts, or heavy asset work on the read path
|
|
**Constraints**: no new panel/provider, no new `GovernancePackage` persistence family, no new report engine, no scheduling/batching/campaign system, no AI summaries, no PSA/CRM workflow, no package-generation runs from the management-ready path, no cross-tenant packaging, no global-search expansion, and no asset strategy change
|
|
**Scale/Scope**: 1 existing workspace page, 1 existing released-review detail page, 1 existing signed review-pack download route, existing evidence and review-pack truth seams, existing stored-report-backed evidence sources, shared audit infrastructure, and focused reuse of the current `Reviews`, `TenantReview`, `ReviewPack`, `Evidence`, and browser test families
|
|
|
|
## Likely Affected Repo Surfaces
|
|
|
|
- [../../apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php](../../apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php) for package-readiness wording, calm disclosure, and consistency with the current `control_readiness`, `evidence_basis`, `recommended_next_action`, and `evidence_proof_state` columns.
|
|
- [../../apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php](../../apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php) for package framing and management-ready disclosure at the page-intro level.
|
|
- [../../apps/platform/app/Filament/Resources/TenantReviewResource.php](../../apps/platform/app/Filament/Resources/TenantReviewResource.php) and [../../apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php](../../apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php) for the released-review detail contract, customer-workspace read-only mode, one dominant package action, and operator-only export separation.
|
|
- [../../apps/platform/app/Services/TenantReviews/TenantReviewComposer.php](../../apps/platform/app/Services/TenantReviews/TenantReviewComposer.php) and [../../apps/platform/app/Services/TenantReviews/TenantReviewSectionFactory.php](../../apps/platform/app/Services/TenantReviews/TenantReviewSectionFactory.php) for the already composed `summary.control_interpretation`, `summary.highlights`, and current section family (`executive_summary`, `control_interpretation`, `open_risks`, `accepted_risks`, `permission_posture`, `baseline_drift_posture`, `operations_health`).
|
|
- [../../apps/platform/app/Support/Governance/Controls/ComplianceEvidenceMappingV1.php](../../apps/platform/app/Support/Governance/Controls/ComplianceEvidenceMappingV1.php) for the shared interpretation dependency and existing accepted-risk follow-up language.
|
|
- [../../apps/platform/app/Services/ReviewPackService.php](../../apps/platform/app/Services/ReviewPackService.php) and [../../apps/platform/app/Http/Controllers/ReviewPackDownloadController.php](../../apps/platform/app/Http/Controllers/ReviewPackDownloadController.php) for current review-pack truth, signed downloads, and current audit boundaries.
|
|
- [../../apps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php](../../apps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php) and related envelope/compression helpers for `TenantReview`, `EvidenceSnapshot`, and `ReviewPack` availability, freshness, and artifact/result truth separation.
|
|
- [../../apps/platform/app/Services/Evidence/Sources/PermissionPostureSource.php](../../apps/platform/app/Services/Evidence/Sources/PermissionPostureSource.php) and [../../apps/platform/app/Services/Evidence/Sources/EntraAdminRolesSource.php](../../apps/platform/app/Services/Evidence/Sources/EntraAdminRolesSource.php) as the current stored-report-backed evidence seams; planning should avoid inventing a new stored-report viewer when these sources already feed the review and evidence basis.
|
|
- [../../apps/platform/app/Filament/Resources/EvidenceSnapshotResource.php](../../apps/platform/app/Filament/Resources/EvidenceSnapshotResource.php) and existing evidence detail pages for secondary proof routes and explicit unavailable-state behavior.
|
|
- [../../apps/platform/app/Services/Audit/WorkspaceAuditLogger.php](../../apps/platform/app/Services/Audit/WorkspaceAuditLogger.php) and [../../apps/platform/app/Support/Audit/AuditActionId.php](../../apps/platform/app/Support/Audit/AuditActionId.php) for reusable audit events and metadata.
|
|
- [../../apps/platform/app/Services/Auth/RoleCapabilityMap.php](../../apps/platform/app/Services/Auth/RoleCapabilityMap.php) and [../../apps/platform/app/Support/Auth/Capabilities.php](../../apps/platform/app/Support/Auth/Capabilities.php) for capability-first RBAC and deny-as-not-found boundaries.
|
|
- [../../apps/platform/lang/en/localization.php](../../apps/platform/lang/en/localization.php) and [../../apps/platform/lang/de/localization.php](../../apps/platform/lang/de/localization.php) for management-ready and customer-safe wording.
|
|
- [../../apps/platform/tests/Unit/TenantReview/TenantReviewComposerTest.php](../../apps/platform/tests/Unit/TenantReview/TenantReviewComposerTest.php), [../../apps/platform/tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php](../../apps/platform/tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php), [../../apps/platform/tests/Feature/Reviews/CustomerReviewWorkspaceAuthorizationTest.php](../../apps/platform/tests/Feature/Reviews/CustomerReviewWorkspaceAuthorizationTest.php), [../../apps/platform/tests/Feature/Reviews/CustomerReviewWorkspaceNavigationContextTest.php](../../apps/platform/tests/Feature/Reviews/CustomerReviewWorkspaceNavigationContextTest.php), [../../apps/platform/tests/Feature/Reviews/CustomerReviewWorkspaceLaunchLinksTest.php](../../apps/platform/tests/Feature/Reviews/CustomerReviewWorkspaceLaunchLinksTest.php), [../../apps/platform/tests/Feature/Reviews/CustomerReviewWorkspacePackAccessTest.php](../../apps/platform/tests/Feature/Reviews/CustomerReviewWorkspacePackAccessTest.php), [../../apps/platform/tests/Feature/TenantReview/TenantReviewExplanationSurfaceTest.php](../../apps/platform/tests/Feature/TenantReview/TenantReviewExplanationSurfaceTest.php), [../../apps/platform/tests/Feature/TenantReview/TenantReviewUiContractTest.php](../../apps/platform/tests/Feature/TenantReview/TenantReviewUiContractTest.php), [../../apps/platform/tests/Feature/TenantReview/TenantReviewAuditLogTest.php](../../apps/platform/tests/Feature/TenantReview/TenantReviewAuditLogTest.php), [../../apps/platform/tests/Feature/TenantReview/TenantReviewExecutivePackTest.php](../../apps/platform/tests/Feature/TenantReview/TenantReviewExecutivePackTest.php), [../../apps/platform/tests/Feature/ReviewPack/TenantReviewDerivedReviewPackTest.php](../../apps/platform/tests/Feature/ReviewPack/TenantReviewDerivedReviewPackTest.php), [../../apps/platform/tests/Feature/ReviewPack/ReviewPackDownloadTest.php](../../apps/platform/tests/Feature/ReviewPack/ReviewPackDownloadTest.php), [../../apps/platform/tests/Feature/ReviewPack/ReviewPackEntitlementEnforcementTest.php](../../apps/platform/tests/Feature/ReviewPack/ReviewPackEntitlementEnforcementTest.php), [../../apps/platform/tests/Feature/ReviewPack/ReviewPackValidRiskAcceptanceTest.php](../../apps/platform/tests/Feature/ReviewPack/ReviewPackValidRiskAcceptanceTest.php), [../../apps/platform/tests/Feature/Evidence/ExceptionValidityEvidenceIntegrationTest.php](../../apps/platform/tests/Feature/Evidence/ExceptionValidityEvidenceIntegrationTest.php), [../../apps/platform/tests/Feature/Evidence/EvidenceSnapshotResourceTest.php](../../apps/platform/tests/Feature/Evidence/EvidenceSnapshotResourceTest.php), [../../apps/platform/tests/Feature/Evidence/EvidenceSnapshotAuditLogTest.php](../../apps/platform/tests/Feature/Evidence/EvidenceSnapshotAuditLogTest.php), and [../../apps/platform/tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php](../../apps/platform/tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php) for the bounded proving lane already present in the repo.
|
|
|
|
## Packaging / Artifact Reuse Fit
|
|
|
|
- Keep the released review as the only package-owning context. The package summary should be derived from the already composed review summary and section payloads rather than from a new `GovernancePackage` record or a new report namespace.
|
|
- Repo truth already prefers current review-pack reuse over package generation on the customer-safe path. In customer-workspace mode [../../apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php](../../apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php) exposes `downloadCurrentReviewPackAction()` only and routes it through the current signed-download URL, while `exportExecutivePackAction()` remains outside the customer-workspace flow.
|
|
- The management-ready path should therefore begin with current `currentExportReviewPack` availability, signed download reuse, and explicit unavailable or expired states. It must not call [../../apps/platform/app/Services/ReviewPackService.php](../../apps/platform/app/Services/ReviewPackService.php)`::generateFromReview()` from the package path and must not start a new `OperationRun` or report-generation sequence.
|
|
- In v1, `Download governance package` is governance-package framing for downloading the current export review pack for the released review. The summary shown on the page is derived presentation over that artifact and related evidence truth, not a second downloadable export family.
|
|
- [../../apps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php](../../apps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php) already has `forReviewPack()`, `forEvidenceSnapshot()`, and tenant-review seams. Package readiness, expiration, blocked, historical-only, or missing-input states should piggyback on those existing artifact-truth semantics instead of creating a new package state family.
|
|
- Stored reports remain subordinate source truth. The repo currently exposes them mainly through evidence-source and widget seams, not through an obvious shared stored-report viewer resource. V1 should therefore summarize stored-report-backed evidence basis where needed and use explicit unavailable or secondary existing-viewer behavior instead of inventing a new stored-report viewer route.
|
|
- The roadmap phrase `open decisions` must stay narrowed to current accepted-risk and exception decision truth from `FindingException` and `FindingExceptionDecision`. The package does not become a broader governance inbox or approval queue.
|
|
|
|
## UI / Filament & Livewire Fit
|
|
|
|
- Keep [../../apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php](../../apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php) as the primary decision surface. This plan tightens the existing page instead of adding a new page class, Resource, panel, provider, or cluster.
|
|
- Keep [../../apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php](../../apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php) as the only secondary context surface, using the existing customer-workspace read-only mode rather than creating a new package detail shell.
|
|
- Filament remains v5 on Livewire v4. Provider registration remains in [../../apps/platform/bootstrap/providers.php](../../apps/platform/bootstrap/providers.php), and this feature does not plan any panel or provider changes.
|
|
- Global search posture stays unchanged. [../../apps/platform/app/Filament/Resources/TenantReviewResource.php](../../apps/platform/app/Filament/Resources/TenantReviewResource.php), [../../apps/platform/app/Filament/Resources/ReviewPackResource.php](../../apps/platform/app/Filament/Resources/ReviewPackResource.php), and [../../apps/platform/app/Filament/Resources/EvidenceSnapshotResource.php](../../apps/platform/app/Filament/Resources/EvidenceSnapshotResource.php) are already globally disabled, and this plan adds no new globally searchable resource.
|
|
- Keep one dominant next action per surface. On the workspace page that remains `Open released review`; package readiness stays informational and should not become a competing row action. On released-review detail the dominant action remains a safe package download path rooted in the current review-pack seam.
|
|
- No destructive actions are introduced for the management-ready package path. Existing destructive or mutating review lifecycle actions on the normal operator detail page remain outside this slice and continue to rely on existing authorization and confirmation behavior.
|
|
- Asset strategy remains unchanged. No new Filament asset registration is planned. If a later implementation unexpectedly registers assets, deployment still uses the existing `cd apps/platform && php artisan filament:assets` step, but no such change is expected here.
|
|
|
|
## RBAC / Policy Fit
|
|
|
|
- Workspace membership remains the first isolation boundary via the current workspace context and [../../apps/platform/app/Services/TenantReviews/TenantReviewRegisterService.php](../../apps/platform/app/Services/TenantReviews/TenantReviewRegisterService.php). Non-members and actors without any entitled tenant in the current workspace remain `404`.
|
|
- Tenant scope remains the second isolation boundary. Released-review detail, review-pack download, evidence proof, and any secondary drilldown must stay tied to the selected tenant and deny cross-tenant access as not found.
|
|
- Capability reuse remains mandatory. Package access should ride current review visibility plus current `REVIEW_PACK_VIEW` and `EVIDENCE_VIEW` capability checks rather than introducing raw strings or role-name branches.
|
|
- Inside an established scope, the reused released-review detail route or secondary artifact access may still fail as capability denial when inherited capability checks deny access. The page-level contract should prefer calm unavailable messaging where the summary remains readable, while inherited detail-route and direct execution endpoints keep current `403` or signed-route enforcement semantics.
|
|
- Cross-tenant packaging is explicitly out of scope. The workspace may only show package readiness for entitled tenants and their eligible released reviews.
|
|
|
|
## Audit / Logging Fit
|
|
|
|
- Reuse [../../apps/platform/app/Services/Audit/WorkspaceAuditLogger.php](../../apps/platform/app/Services/Audit/WorkspaceAuditLogger.php) and [../../apps/platform/app/Support/Audit/AuditActionId.php](../../apps/platform/app/Support/Audit/AuditActionId.php) as the only audit path.
|
|
- [../../apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php](../../apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php) already logs `CustomerReviewWorkspaceOpened` with `source_surface`, tenant-filter metadata, and interpretation-version context.
|
|
- [../../apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php](../../apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php) already logs `TenantReviewOpened` with the customer-workspace source and interpretation version when entered from the workspace.
|
|
- Current review-pack downloads already flow through `ReviewPackDownloaded` on the signed route. Planning should prefer reusing that event plus metadata over creating a new package-download audit family.
|
|
- Secondary proof access should remain on existing evidence-open audit paths. If a distinct management-ready package open event is ever proposed beyond current review open and pack download, that should first be justified as additive metadata on the existing audit path before a new event family is considered.
|
|
|
|
## Data & Query Fit
|
|
|
|
- Package summary should start from existing released-review truth already composed in [../../apps/platform/app/Services/TenantReviews/TenantReviewComposer.php](../../apps/platform/app/Services/TenantReviews/TenantReviewComposer.php): `summary.control_interpretation`, `summary.highlights`, `summary.recommended_next_actions`, and the current evidence-basis block.
|
|
- Detailed package sections should reuse the current section family from [../../apps/platform/app/Services/TenantReviews/TenantReviewSectionFactory.php](../../apps/platform/app/Services/TenantReviews/TenantReviewSectionFactory.php): `executive_summary`, `control_interpretation`, `open_risks`, `accepted_risks`, `permission_posture`, `baseline_drift_posture`, and `operations_health`.
|
|
- Governance-decision follow-up must stay rooted in accepted-risk and exception truth. That means the package should summarize `accepted_risks` section output and underlying `FindingException` or `FindingExceptionDecision` validity, owner, approval, expiry, and follow-up semantics without broadening into a new decision framework.
|
|
- Review-pack availability should be derived from current review-pack truth, signed-download readiness, expiry, and artifact-truth state. It should not become a new persisted package lifecycle.
|
|
- Evidence and stored-report basis should remain distinct from the package summary. Stored reports can remain subordinate evidence carriers behind existing evidence-source seams; the package may summarize their role, but it should not surface raw report payloads or invent a new viewer if one is not already present.
|
|
- The default plan is render-time composition over released-review summary, sections, and current artifact truth. If implementation later proves that one tiny helper accessor is needed, it should stay inside existing review/resource helpers and must not become new persistence or a parallel package service framework.
|
|
|
|
## UI / Surface Guardrail Plan
|
|
|
|
- **Guardrail scope**: changed surfaces
|
|
- **Native vs custom classification summary**: native Filament
|
|
- **Shared-family relevance**: status messaging, management summary sections, action links, evidence and review-pack viewers, package-availability states, and audit labels
|
|
- **State layers in scope**: page, detail, URL-query, table/session restore
|
|
- **Audience modes in scope**: customer/read-only, customer-admin, auditor-read-only, operator-MSP
|
|
- **Decision/diagnostic/raw hierarchy plan**: decision-first, diagnostics-second, support-raw-third
|
|
- **Raw/support gating plan**: collapsed and capability-gated on reused evidence or review-pack paths; stored-report detail remains secondary and only where an existing viewer seam already exists
|
|
- **One-primary-action / duplicate-truth control**: the workspace keeps `Open released review` as the sole dominant row action; released-review detail keeps one dominant package action; the workspace states readiness while detail owns the package summary so equal-priority duplicate truth is avoided
|
|
- **Handling modes by drift class or surface**: review-mandatory
|
|
- **Repository-signal treatment**: review-mandatory
|
|
- **Special surface test profiles**: standard-native-filament, shared-detail-family
|
|
- **Required tests or manual smoke**: functional-core, state-contract, bounded-browser-smoke
|
|
- **Exception path and spread control**: none planned; any proposal for a new package artifact, new report viewer, new branding or profile engine, or package-generation workflow becomes exception-required drift
|
|
- **Active feature PR close-out entry**: Guardrail / Smoke Coverage
|
|
|
|
## Shared Pattern & System Fit
|
|
|
|
- **Cross-cutting feature marker**: yes
|
|
- **Systems touched**: `CustomerReviewWorkspace`, `TenantReviewResource`, `ViewTenantReview`, `TenantReviewComposer`, `TenantReviewSectionFactory`, `ComplianceEvidenceMappingV1`, `ReviewPackService`, `ReviewPackDownloadController`, `ArtifactTruthPresenter`, existing evidence-source seams, localization copy, `WorkspaceAuditLogger`, and `AuditActionId`
|
|
- **Shared abstractions reused**: existing review summary and section payloads, the shared `control_interpretation` contract, `ArtifactTruthPresenter` plus envelope/compression seams, current signed review-pack download generation, capability helpers, and the shared audit logger
|
|
- **New abstraction introduced? why?**: none planned. If implementation needs a tiny package-view accessor, it should stay inside the existing tenant-review or review-pack family instead of becoming a new packaging framework
|
|
- **Why the existing abstraction was sufficient or insufficient**: existing review, interpretation, review-pack, evidence, and artifact-truth seams already describe what the package should say and whether its supporting artifacts are usable. What is missing is the bounded product contract over those seams, not a new domain model or engine
|
|
- **Bounded deviation / spread control**: none planned. If a real stored-report viewer gap or profile-variant need appears, record it as a follow-up instead of adding a local workaround that becomes permanent architecture
|
|
|
|
## OperationRun UX Impact
|
|
|
|
- **Touches OperationRun start/completion/link UX?**: no
|
|
- **Central contract reused**: `N/A`
|
|
- **Delegated UX behaviors**: `N/A`
|
|
- **Surface-owned behavior kept local**: read-only workspace and released-review detail rendering only; the management-ready path must not enqueue review-pack, stored-report, or evidence generation
|
|
- **Queued DB-notification policy**: `N/A`
|
|
- **Terminal notification path**: `N/A`
|
|
- **Exception path**: none
|
|
|
|
## Provider Boundary & Portability Fit
|
|
|
|
- **Shared provider/platform boundary touched?**: yes
|
|
- **Provider-owned seams**: stored-report types, evidence dimension keys, and Microsoft-shaped source detail remain provider-owned inputs inside the existing evidence-source and report layers
|
|
- **Platform-core seams**: `governance package`, `released review`, `accepted risk`, `governance decision`, `evidence basis`, management-ready summary wording, and package-availability meaning
|
|
- **Neutral platform terms / contracts preserved**: `governance package`, `released review`, `review pack`, `evidence basis`, `accepted risk`, `governance decision`, and `review context`
|
|
- **Retained provider-specific semantics and why**: provider-specific labels may remain visible only in entitled secondary detail where an existing viewer already exposes them. They must not become default package vocabulary
|
|
- **Bounded extraction or follow-up path**: `document-in-feature` for bounded wording and truth-separation notes; `follow-up-spec` only if later work demands framework-specific package profiles or a real stored-report viewer surface
|
|
|
|
## Constitution Check
|
|
|
|
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
|
|
|
- Inventory-first / snapshot truth: PASS. The slice consumes existing released reviews, evidence snapshots, stored-report-backed evidence, and review-pack artifacts as read-only truth.
|
|
- Read/write separation: PASS. No new mutation, publication, regeneration, schedule, batch, or destructive path is introduced.
|
|
- Graph contract path: PASS. No new Graph call or provider contract work is part of this feature.
|
|
- Deterministic capabilities: PASS. Existing capability registries and role maps remain canonical.
|
|
- Workspace and tenant isolation: PASS. Workspace membership and tenant entitlement remain `404` boundaries.
|
|
- RBAC-UX plane separation: PASS. Everything stays inside the existing `/admin` plane and current tenant-scoped detail/proof reuse.
|
|
- Destructive confirmation standard: PASS by non-use. The package path introduces no destructive action, and existing operator-only destructive lifecycle actions remain unchanged outside this slice.
|
|
- Global search safety: PASS. `TenantReviewResource`, `ReviewPackResource`, and `EvidenceSnapshotResource` are already globally disabled, and no new searchable surface is introduced.
|
|
- OperationRun / Ops-UX: PASS by non-use. The management-ready path must not call `generateFromReview()` or start any report/evidence generation workflow.
|
|
- Data minimization: PASS. Default-visible content stays management-ready and customer-safe; raw reports, provider detail, and support diagnostics remain secondary.
|
|
- Test governance (TEST-GOV-001): PASS. Planned proof stays inside focused unit/feature coverage plus one bounded browser smoke.
|
|
- Proportionality / no premature abstraction: PASS. The package stays a derived contract over existing review, interpretation, pack, and artifact truth instead of introducing new persistence, engines, or registries.
|
|
- Persisted truth (PERSIST-001): PASS. No new table, entity, or artifact family is planned.
|
|
- Behavioral state (STATE-001): PASS. `available`, `partial`, `unavailable`, `expired`, and `blocked` conditions remain derived from existing review-pack and artifact truth, while stale or entitlement-restricted situations remain encoded as reasons within those states rather than as a new package lifecycle.
|
|
- Canonical package-state mapping: current repo truth `publishable` maps to `available`; `internal_only` or `stale` with still-readable basis maps to `partial`; `blocked`, `missing_input`, or source-not-publishable cases map to `unavailable`; `historical_only` maps to `expired`; package-level entitlement restriction maps to `blocked`. Secondary proof restrictions stay on `SupportingArtifactLink` disclosure and do not force the package summary itself into `blocked` when the review remains readable. Repo directions like `usable` or `follow_up_needed` stay inside supporting-artifact or governance-follow-up disclosure rather than creating extra package states.
|
|
- UI semantics / shared pattern first / Filament-native UI: PASS. Native Filament surfaces and existing shared review/artifact seams remain the default path.
|
|
- Provider boundary (PROV-001): PASS. Provider-specific semantics stay inside current source artifacts and do not become platform-core package truth.
|
|
- Filament / Laravel planning contract: PASS. Filament remains v5 on Livewire v4, provider registration remains in [../../apps/platform/bootstrap/providers.php](../../apps/platform/bootstrap/providers.php), no panel change is planned, no global-search change is planned, and no new assets are expected.
|
|
|
|
**Gate evaluation**: PASS.
|
|
|
|
- The narrow path is defensible if the implementation keeps package delivery anchored to the current released review and current review-pack download seam.
|
|
- The plan fails the gate if it drifts into new package persistence, scheduled generation, a new report engine, or a new stored-report viewer shell.
|
|
|
|
**Post-design re-check**: PASS once [research.md](research.md), [data-model.md](data-model.md), [quickstart.md](quickstart.md), and [contracts/governance-service-packaging.openapi.yaml](contracts/governance-service-packaging.openapi.yaml) are present and the agent-context refresh step is executed.
|
|
|
|
## Test Governance Check
|
|
|
|
- **Test purpose / classification by changed surface**: Unit for any review-summary composition adjustments in the existing tenant-review composer seam; Feature for workspace readiness, released-review detail package summary, package/download availability, audit metadata, truth separation, and deny-as-not-found or in-scope capability boundaries; Browser for one bounded workspace-to-detail-to-package smoke path
|
|
- **Affected validation lanes**: confidence, browser
|
|
- **Why this lane mix is the narrowest sufficient proof**: the repo already has focused unit and feature files covering the exact review, pack, evidence, and audit seams this feature will reuse, and one existing browser smoke is enough to catch rendered disclosure and action-hierarchy regressions without creating a new heavy family
|
|
- **Narrowest proving command(s)**:
|
|
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/TenantReview/TenantReviewComposerTest.php tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php tests/Feature/Reviews/CustomerReviewWorkspacePackAccessTest.php tests/Feature/Reviews/CustomerReviewWorkspaceLaunchLinksTest.php`
|
|
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Reviews/CustomerReviewWorkspaceAuthorizationTest.php tests/Feature/Reviews/CustomerReviewWorkspaceNavigationContextTest.php tests/Feature/TenantReview/TenantReviewExplanationSurfaceTest.php tests/Feature/TenantReview/TenantReviewUiContractTest.php tests/Feature/TenantReview/TenantReviewAuditLogTest.php tests/Feature/TenantReview/TenantReviewExecutivePackTest.php tests/Feature/ReviewPack/TenantReviewDerivedReviewPackTest.php tests/Feature/ReviewPack/ReviewPackDownloadTest.php tests/Feature/ReviewPack/ReviewPackEntitlementEnforcementTest.php tests/Feature/ReviewPack/ReviewPackValidRiskAcceptanceTest.php tests/Feature/Evidence/ExceptionValidityEvidenceIntegrationTest.php tests/Feature/Evidence/EvidenceSnapshotResourceTest.php tests/Feature/Evidence/EvidenceSnapshotAuditLogTest.php`
|
|
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php`
|
|
- **Fixture / helper / factory / seed / context cost risks**: moderate but contained; reuse existing workspace membership, released review, current export review pack, evidence snapshot, stored-report-backed evidence items, finding exception decision, and audit fixtures
|
|
- **Expensive defaults or shared helper growth introduced?**: no; any new helper should stay explicit and local to the review/review-pack family
|
|
- **Heavy-family additions, promotions, or visibility changes**: none beyond the already-existing single browser smoke
|
|
- **Surface-class relief / special coverage rule**: standard-native-filament relief on the workspace page, shared-detail-family coverage on released-review detail and package reuse
|
|
- **Closing validation and reviewer handoff**: rerun the commands above, verify the package path never starts export generation, verify current review-pack reuse and signed download behavior, verify accepted-risk or exception truth stays narrowed to current governance decisions, verify missing supporting access resolves as calm unavailable state or direct-route denial, and verify out-of-scope targets stay `404`
|
|
- **Budget / baseline / trend follow-up**: none expected beyond small feature-local additions in the existing suites
|
|
- **Review-stop questions**: lane fit, hidden fixture growth, accidental run generation, stored-report viewer drift, packaging abstraction creep
|
|
- **Escalation path**: `document-in-feature` for contained metadata or copy notes; `follow-up-spec` for a real stored-report viewer or broader package-profile need; `reject-or-split` for any drift into new package persistence, report engines, schedules, or campaigns
|
|
- **Active feature PR close-out entry**: Guardrail / Smoke Coverage
|
|
- **Why no dedicated follow-up spec is needed**: this feature is already the bounded packaging follow-up after Specs 258 and 259. Only broader profile automation, stored-report viewer productization, or multi-tenant packaging would justify a separate follow-up
|
|
|
|
## Rollout & Risk Controls
|
|
|
|
- Keep the canonical entry surface on the existing customer review workspace and the canonical secondary surface on the existing released-review detail route.
|
|
- Keep package delivery anchored to current released-review truth and current review-pack reuse. Do not trigger `exportExecutivePackAction()` or `ReviewPackService::generateFromReview()` from the customer-workspace path.
|
|
- Treat `publishable` review-pack truth as `available`, stale or internal-only but still-readable truth as `partial`, missing or blocked source truth as `unavailable`, historical-only truth as `expired`, and package-level entitlement restriction as `blocked`. If only supporting proof is restricted, keep the package summary readable and mark the affected supporting link unavailable or forbidden instead. Do not generate missing truth and do not imply calmness where the source basis is incomplete.
|
|
- Keep branding and profile variants deferred from v1. Neutral governance-package framing must not introduce a new presentation-truth source, layout system, or profile configuration seam.
|
|
- Keep stored-report detail subordinate. If implementation cannot point to an existing entitled viewer seam, the package should stop at calm evidence-basis disclosure rather than inventing a new route.
|
|
- Keep global search posture, provider registration, and asset strategy unchanged.
|
|
|
|
## Project Structure
|
|
|
|
### Documentation (this feature)
|
|
|
|
```text
|
|
specs/260-governance-service-packaging/
|
|
├── checklists/
|
|
│ └── requirements.md
|
|
├── plan.md
|
|
├── research.md
|
|
├── data-model.md
|
|
├── quickstart.md
|
|
├── contracts/
|
|
│ └── governance-service-packaging.openapi.yaml
|
|
└── tasks.md # Created later by /speckit.tasks, not by this plan step
|
|
```
|
|
|
|
### Source Code (repository root)
|
|
|
|
```text
|
|
apps/platform/
|
|
├── app/
|
|
│ ├── Filament/
|
|
│ │ ├── Pages/Reviews/
|
|
│ │ │ └── CustomerReviewWorkspace.php
|
|
│ │ └── Resources/
|
|
│ │ ├── TenantReviewResource.php
|
|
│ │ ├── TenantReviewResource/Pages/ViewTenantReview.php
|
|
│ │ └── EvidenceSnapshotResource.php
|
|
│ ├── Http/Controllers/
|
|
│ │ └── ReviewPackDownloadController.php
|
|
│ ├── Models/
|
|
│ │ ├── TenantReview.php
|
|
│ │ ├── ReviewPack.php
|
|
│ │ ├── EvidenceSnapshot.php
|
|
│ │ ├── StoredReport.php
|
|
│ │ └── FindingException.php
|
|
│ ├── Services/
|
|
│ │ ├── Audit/WorkspaceAuditLogger.php
|
|
│ │ ├── Evidence/Sources/
|
|
│ │ │ ├── EntraAdminRolesSource.php
|
|
│ │ │ └── PermissionPostureSource.php
|
|
│ │ ├── ReviewPackService.php
|
|
│ │ └── TenantReviews/
|
|
│ │ ├── TenantReviewComposer.php
|
|
│ │ └── TenantReviewSectionFactory.php
|
|
│ ├── Support/
|
|
│ │ ├── Audit/AuditActionId.php
|
|
│ │ ├── Auth/Capabilities.php
|
|
│ │ ├── Governance/Controls/ComplianceEvidenceMappingV1.php
|
|
│ │ └── Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php
|
|
├── bootstrap/providers.php
|
|
├── lang/
|
|
│ ├── de/localization.php
|
|
│ └── en/localization.php
|
|
├── resources/views/filament/pages/reviews/customer-review-workspace.blade.php
|
|
└── tests/
|
|
├── Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php
|
|
├── Feature/Evidence/
|
|
├── Feature/ReviewPack/
|
|
├── Feature/Reviews/
|
|
├── Feature/TenantReview/
|
|
└── Unit/TenantReview/TenantReviewComposerTest.php
|
|
```
|
|
|
|
**Structure Decision**: Laravel monolith. The implementation should stay inside the existing `apps/platform` review, review-pack, evidence, audit, localization, and shared-truth seams, with no new panel/provider location and no new persistence layer.
|
|
|
|
## Complexity Tracking
|
|
|
|
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
|
|-----------|------------|-------------------------------------|
|
|
| None expected at planning time | The intended implementation is a bounded product contract over existing review, pack, evidence, and audit seams | Adding a `GovernancePackage` model, report engine, schedule, campaign flow, or new viewer shell would import unnecessary permanent complexity |
|
|
|
|
## Proportionality Review
|
|
|
|
- **Current operator problem**: operators still have to assemble stakeholder-ready governance packages manually outside the product, which risks drift from shared interpretation and artifact truth.
|
|
- **Existing structure is insufficient because**: current review workspace and released-review detail surfaces explain one released review, but they do not yet present one explicit management-ready package contract over the same truth and current package-download seam.
|
|
- **Narrowest correct implementation**: tighten the existing workspace and released-review detail flow so package readiness, summary, and current review-pack download reuse are explicit and consistent, while leaving generation, scheduling, and broader export orchestration out of scope.
|
|
- **Ownership cost created**: bounded copy and disclosure maintenance on existing surfaces, focused audit-metadata reuse, and small expansions in existing test files.
|
|
- **Alternative intentionally rejected**: a standalone `GovernancePackage` model, a package-specific report engine, a customer portal, a stored-report viewer shell, or scheduled campaign packaging were rejected because the repo already has the required review, interpretation, review-pack, evidence, and audit seams for a smaller v1.
|
|
- **Release truth**: current-release commercial packaging follow-through after Specs 258 and 259, not speculative future infrastructure.
|
|
|
|
## Phase 0 — Research (output: research.md)
|
|
|
|
Research resolves the remaining implementation-shaping decisions:
|
|
|
|
- keep the existing customer review workspace and released-review detail route as the only primary and secondary surfaces
|
|
- prefer current review-pack reuse and signed download over creating a new exported artifact or starting generation from the management-ready path
|
|
- derive package summary from existing review summary and section truth rather than a parallel package record or report engine
|
|
- keep `open decisions` narrowed to accepted-risk and exception decision truth only
|
|
- reuse artifact-truth seams for availability, expiry, and artifact/result truth separation
|
|
- treat stored reports as subordinate source truth and explicitly defer inventing a new viewer where the repo does not already expose one
|
|
- reuse existing audit events and metadata rather than introducing a new audit family
|
|
- keep validation inside existing unit/feature families plus the single existing browser smoke
|
|
|
|
**Output**: [research.md](research.md)
|
|
|
|
## Phase 1 — Design (outputs: data-model.md, contracts/, quickstart.md)
|
|
|
|
Design artifacts capture the narrow packaging shape:
|
|
|
|
- no new table, package artifact family, or report namespace; package truth remains derived from existing reviews, sections, packs, evidence snapshots, stored reports, and governance decisions
|
|
- one conceptual package-summary contract documents the derived management-ready payload without prescribing new persistence
|
|
- the conceptual contract documents the existing workspace, released-review detail, review-pack download, and evidence routes reused by this feature
|
|
- quickstart records the intended implementation order, targeted tests, Filament v5 plus Livewire v4 posture, unchanged provider-registration location, unchanged global-search posture, unchanged destructive-action posture for the package path, and unchanged asset strategy
|
|
- `.specify/scripts/bash/update-agent-context.sh copilot` must run after the design artifacts are generated, even if it results in no technology additions
|
|
|
|
**Artifacts**:
|
|
|
|
- [data-model.md](data-model.md)
|
|
- [contracts/governance-service-packaging.openapi.yaml](contracts/governance-service-packaging.openapi.yaml)
|
|
- [quickstart.md](quickstart.md)
|
|
|
|
## Phase 2 — Planning (for tasks.md)
|
|
|
|
Dependency-ordered outline for the later `tasks.md` step:
|
|
|
|
1. Tighten the workspace page and intro copy so package readiness and management value are visible without adding a competing package row action.
|
|
2. Tighten the released-review detail flow in customer-workspace mode so it owns the management-ready package summary and keeps only one dominant package action.
|
|
3. Reuse the current review summary, interpretation, risk, and section seams to keep package wording aligned across workspace, detail, and supporting artifact access.
|
|
4. Reuse current review-pack truth, signed download generation, and artifact-truth presenter output for availability, expired, blocked, and partial states.
|
|
5. Keep stored-report-backed evidence subordinate to the package summary, surfacing explicit unavailable or secondary access states rather than inventing a new viewer.
|
|
6. Reuse the shared audit path and current capabilities, adding only bounded metadata or assertions if the current events do not already cover the required moments.
|
|
7. Expand the focused review, review-pack, evidence, and audit suites plus the single browser smoke, without introducing a new heavy family.
|
|
|
|
## Planning Guardrail Notes
|
|
|
|
- Planning guardrail result: PASS. Filament remains v5 on Livewire v4, provider registration remains in [../../apps/platform/bootstrap/providers.php](../../apps/platform/bootstrap/providers.php), no new panel/provider is expected, no global-search expansion is planned, no new destructive action is introduced on the package path, and no new asset bundle is planned.
|
|
- Shared-path result: the plan keeps package meaning and availability on existing review, interpretation, review-pack, evidence, and artifact-truth seams rather than a new package engine.
|
|
- Stored-report tension result: the repo clearly has stored-report-backed evidence inputs but no obvious shared stored-report viewer resource in the current operator plane. The plan therefore keeps stored reports as subordinate source truth and defers any new viewer shell unless implementation proves an existing viewer seam already exists.
|
|
- Preparation workflow result: the existing [checklists/requirements.md](checklists/requirements.md) already carries the required review outcome and workflow outcome conventions, so no new checklist was needed during this plan pass.
|