317 lines
22 KiB
Markdown
317 lines
22 KiB
Markdown
# Implementation Plan: Governance Friction Hardening and Operator Vocabulary
|
|
|
|
**Branch**: `194-governance-friction-hardening` | **Date**: 2026-04-12 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/194-governance-friction-hardening/spec.md`
|
|
**Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/194-governance-friction-hardening/spec.md`
|
|
|
|
**Note**: This plan keeps the work inside the existing Filament v5 / Livewire v4 surface layer, existing mutation services, existing audit loggers, and the current RBAC helpers. It explicitly avoids introducing a new workflow engine, new persistence, or a broad UI meta-framework.
|
|
|
|
## Summary
|
|
|
|
Codify one narrow governance-action semantics contract across tenant, workspace, and system surfaces. Introduce a derived governance action catalog that classifies in-scope actions into explicit friction classes, reason rules, danger semantics, and canonical vocabulary; then align the affected Filament pages and existing mutation services so exception, review, evidence, run-triage, finding-lifecycle, and tenant-lifecycle actions behave consistently. Protect the result with a spec-scoped guard, focused feature tests, RBAC regression coverage, and one browser smoke suite.
|
|
|
|
## Technical Context
|
|
|
|
**Language/Version**: PHP 8.4.15
|
|
**Primary Dependencies**: Laravel 12, Filament v5, Livewire v4, Pest v4, Tailwind CSS v4, existing `UiEnforcement`, existing audit loggers (`AuditLogger`, `WorkspaceAuditLogger`, `SystemConsoleAuditLogger`), existing mutation services (`FindingExceptionService`, `FindingWorkflowService`, `TenantReviewLifecycleService`, `EvidenceSnapshotService`, `OperationRunTriageService`)
|
|
**Storage**: PostgreSQL through existing workspace-owned and tenant-owned models; no schema change planned
|
|
**Testing**: Pest unit, feature, and browser tests run through Laravel Sail
|
|
**Target Platform**: Laravel monolith web application under `apps/platform`, with tenant routes under `/admin/t/{tenant}/...`, workspace routes under `/admin/...`, and platform routes under `/system/...`
|
|
**Project Type**: web application
|
|
**Performance Goals**: Preserve current operator interaction speed, keep render-time governance semantics DB-only with no outbound HTTP, avoid adding polling or additional round trips for confirmation flows, and keep any catalog lookups constant-time and local
|
|
**Constraints**: No new persistence, no new workflow states, no panel/provider changes, no raw capability strings, no cross-plane authorization drift, destructive-like actions keep `->requiresConfirmation()`, and no new generic execution framework
|
|
**Scale/Scope**: 8 primary operator surfaces across 3 authorization planes, 6 high-priority governance families, 4 medium or low-priority supporting families, focused changes to existing page classes, services, and tests only
|
|
|
|
## Constitution Check
|
|
|
|
*GATE: Passed before Phase 0 research. Re-check after Phase 1 design and still passing.*
|
|
|
|
| Principle | Pre-Research | Post-Design | Notes |
|
|
|-----------|--------------|-------------|-------|
|
|
| Inventory-first / snapshots-second | PASS | PASS | The feature does not alter inventory or snapshot truth. It governs action semantics only. |
|
|
| Read/write separation | PASS | PASS | Existing mutations keep confirmation, audit, and tests. No new write domain is introduced. |
|
|
| Graph contract path | N/A | N/A | No new Microsoft Graph endpoints or contract-registry changes are planned. |
|
|
| Deterministic capabilities | PASS | PASS | Existing capability registries and `UiEnforcement` remain authoritative. |
|
|
| Workspace + tenant isolation | PASS | PASS | Existing scope boundaries remain authoritative on `/admin`, `/admin/t/{tenant}`, and `/system`. |
|
|
| RBAC-UX authorization semantics | PASS | PASS | Non-member remains `404`, member-without-capability remains `403`, and server-side checks remain unchanged. |
|
|
| Run observability / Ops-UX | PASS | PASS | Existing `OperationRun` flows keep their current lifecycle and feedback contract; this feature changes only semantics. |
|
|
| Data minimization | PASS | PASS | No new persistence, caches, or semantic mirrors are introduced. |
|
|
| Proportionality / anti-bloat | PASS | PASS | The plan adds one narrow derived catalog and guard instead of a new framework or persistence layer. |
|
|
| UI semantics / few layers | PASS | PASS | The feature uses direct action semantics and targeted builders instead of a new presenter stack. |
|
|
| Filament-native UI | PASS | PASS | Native Filament actions, action groups, and current shared helpers remain the implementation path. |
|
|
| Surface taxonomy / decision-first roles | PASS | PASS | Surface roles and action semantics remain aligned with Spec 192 and Spec 193 without reclassifying the affected surfaces. |
|
|
| Filament v5 / Livewire v4 compliance | PASS | PASS | All touched surfaces remain inside the existing Filament v5 + Livewire v4 stack. |
|
|
| Provider registration location | PASS | PASS | No provider change is needed; Laravel 11+ registration remains in `bootstrap/providers.php`. |
|
|
| Global search hard rule | PASS | PASS | No new globally searchable resource is introduced and search settings are not altered. |
|
|
| Destructive action safety | PASS | PASS | Strong actions continue to execute via confirmed Filament actions plus current authorization. |
|
|
| Asset strategy | PASS | PASS | No new assets are planned. Existing deployment handling of `cd apps/platform && php artisan filament:assets` remains sufficient. |
|
|
|
|
## Filament-Specific Compliance Notes
|
|
|
|
- **Livewire v4.0+ compliance**: The plan remains on Filament v5 + Livewire v4 and introduces no legacy APIs.
|
|
- **Provider registration location**: No panel or provider changes are required; registration remains in `bootstrap/providers.php`.
|
|
- **Global search**: This feature does not add new globally searchable resources and does not change current resource search behavior.
|
|
- **Destructive actions**: `Revoke exception`, `Archive review`, `Cancel`, and `Archive` remain execution actions with confirmation and server-side authorization.
|
|
- **Asset strategy**: No new global or lazy-loaded assets are planned. Existing `filament:assets` deployment behavior remains unchanged.
|
|
- **Testing plan**: Add one spec-scoped guard layer, focused action and authorization tests, and one browser smoke suite across the highest-risk surfaces.
|
|
|
|
## Phase 0 Research
|
|
|
|
Research outcomes are captured in `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/194-governance-friction-hardening/research.md`.
|
|
|
|
Key decisions:
|
|
|
|
- Reuse existing mutation services and audit loggers; do not add a new governance workflow engine.
|
|
- Introduce one narrow derived governance-action catalog instead of page-local constants or a broad action meta-framework.
|
|
- Keep action semantics family-first: exception, review, evidence, run-triage, finding-lifecycle, and tenant-lifecycle.
|
|
- Treat reason capture as a family contract and extend current services or audit metadata only where the spec requires stronger propagation.
|
|
- Use the existing three testing layers already proven in this repo: spec guard, focused feature/RBAC tests, and one browser smoke suite.
|
|
|
|
## Phase 1 Design
|
|
|
|
Design artifacts are created under `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/194-governance-friction-hardening/`:
|
|
|
|
- `research.md`: implementation-shape, reason-propagation, and vocabulary decisions
|
|
- `data-model.md`: derived governance family, rule, binding, deviation, and regression models
|
|
- `contracts/governance-action-semantics.logical.openapi.yaml`: internal logical contract for governance-action family rules and surface bindings
|
|
- `quickstart.md`: implementation and verification sequence for the feature
|
|
|
|
Design highlights:
|
|
|
|
- Keep all new semantics derived, not persisted.
|
|
- Model governance rules by action family first, then bind them to concrete page actions.
|
|
- Reuse existing services as owners of state change, audit logging, and operation behavior.
|
|
- Centralize only the shared semantics that already have multiple real concrete cases.
|
|
- Keep surface placement aligned with Spec 192 and Spec 193; Spec 194 governs semantic hardness, not where actions live.
|
|
|
|
## Phase 1 - Agent Context Update
|
|
|
|
Planned command:
|
|
|
|
- `.specify/scripts/bash/update-agent-context.sh copilot`
|
|
|
|
This feature does not introduce a new technology stack, but the required context refresh still runs after the technical context and design artifacts are complete.
|
|
|
|
## Project Structure
|
|
|
|
### Documentation (this feature)
|
|
|
|
```text
|
|
specs/194-governance-friction-hardening/
|
|
├── plan.md
|
|
├── research.md
|
|
├── data-model.md
|
|
├── quickstart.md
|
|
├── spec.md
|
|
├── contracts/
|
|
│ └── governance-action-semantics.logical.openapi.yaml
|
|
└── checklists/
|
|
└── requirements.md
|
|
```
|
|
|
|
### Source Code (repository root)
|
|
|
|
```text
|
|
apps/platform/
|
|
├── app/
|
|
│ ├── Filament/
|
|
│ │ ├── Pages/
|
|
│ │ │ ├── Monitoring/
|
|
│ │ │ │ └── FindingExceptionsQueue.php # MODIFY
|
|
│ │ │ └── Operations/
|
|
│ │ │ └── TenantlessOperationRunViewer.php # REVIEW / possible minor alignment only
|
|
│ │ ├── Resources/
|
|
│ │ │ ├── FindingResource.php # MODIFY
|
|
│ │ │ ├── FindingResource/
|
|
│ │ │ │ └── Pages/
|
|
│ │ │ │ └── ViewFinding.php # MODIFY
|
|
│ │ │ ├── FindingExceptionResource/
|
|
│ │ │ │ └── Pages/
|
|
│ │ │ │ └── ViewFindingException.php # MODIFY
|
|
│ │ │ ├── EvidenceSnapshotResource.php # MODIFY
|
|
│ │ │ ├── EvidenceSnapshotResource/
|
|
│ │ │ │ └── Pages/
|
|
│ │ │ │ └── ViewEvidenceSnapshot.php # MODIFY
|
|
│ │ │ ├── TenantReviewResource/
|
|
│ │ │ │ └── Pages/
|
|
│ │ │ │ └── ViewTenantReview.php # MODIFY
|
|
│ │ │ ├── TenantResource.php # MODIFY
|
|
│ │ │ └── TenantResource/
|
|
│ │ │ └── Pages/
|
|
│ │ │ ├── ViewTenant.php # MODIFY
|
|
│ │ │ └── EditTenant.php # MODIFY
|
|
│ │ └── System/
|
|
│ │ └── Pages/
|
|
│ │ └── Ops/
|
|
│ │ └── ViewRun.php # MODIFY
|
|
│ ├── Services/
|
|
│ │ ├── Findings/
|
|
│ │ │ ├── FindingExceptionService.php # MODIFY
|
|
│ │ │ └── FindingWorkflowService.php # MODIFY
|
|
│ │ ├── Evidence/
|
|
│ │ │ └── EvidenceSnapshotService.php # MODIFY
|
|
│ │ ├── TenantReviews/
|
|
│ │ │ └── TenantReviewLifecycleService.php # MODIFY
|
|
│ │ └── SystemConsole/
|
|
│ │ └── OperationRunTriageService.php # MODIFY
|
|
│ ├── Support/
|
|
│ │ └── Ui/
|
|
│ │ └── GovernanceActions/
|
|
│ │ ├── GovernanceActionCatalog.php # NEW
|
|
│ │ ├── GovernanceActionRule.php # NEW
|
|
│ │ └── Enums/
|
|
│ │ ├── GovernanceFrictionClass.php # NEW
|
|
│ │ └── GovernanceReasonPolicy.php # NEW
|
|
└── tests/
|
|
├── Feature/
|
|
│ ├── Guards/
|
|
│ │ └── Spec194GovernanceActionSemanticsGuardTest.php # NEW
|
|
│ ├── Monitoring/
|
|
│ │ ├── FindingExceptionsQueueHierarchyTest.php # MODIFY
|
|
│ │ └── FindingExceptionsQueueTest.php # MODIFY
|
|
│ ├── Findings/
|
|
│ │ ├── FindingExceptionWorkflowTest.php # MODIFY
|
|
│ │ ├── FindingExceptionRenewalTest.php # MODIFY
|
|
│ │ ├── FindingExceptionRevocationTest.php # MODIFY
|
|
│ │ ├── FindingWorkflowViewActionsTest.php # MODIFY
|
|
│ │ └── FindingAuditLogTest.php # MODIFY
|
|
│ ├── Evidence/
|
|
│ │ └── EvidenceSnapshotResourceTest.php # MODIFY
|
|
│ ├── TenantReview/
|
|
│ │ ├── TenantReviewUiContractTest.php # MODIFY
|
|
│ │ └── TenantReviewLifecycleTest.php # MODIFY
|
|
│ ├── Operations/
|
|
│ │ ├── TenantlessOperationRunViewerTest.php # REVIEW / possible extend
|
|
│ │ └── SystemRunBlockedExecutionNotificationTest.php # REVIEW / possible extend
|
|
│ ├── Rbac/
|
|
│ │ ├── TenantLifecycleActionVisibilityTest.php # MODIFY
|
|
│ │ ├── EditTenantArchiveUiEnforcementTest.php # MODIFY
|
|
│ │ └── TenantResourceAuthorizationTest.php # MODIFY
|
|
│ └── Audit/
|
|
│ └── TenantLifecycleAuditLogTest.php # MODIFY
|
|
├── Unit/
|
|
│ └── Ui/
|
|
│ └── GovernanceActions/
|
|
│ └── GovernanceActionCatalogTest.php # NEW
|
|
└── Browser/
|
|
│ └── Spec194GovernanceFrictionSmokeTest.php # NEW
|
|
```
|
|
|
|
**Structure Decision**: Keep the work entirely inside the existing Laravel or Filament monolith under `apps/platform`. Add one narrow support namespace for shared governance semantics, then modify the affected page classes, mutation services, and focused tests. Do not introduce new persistence or a second runtime orchestration layer.
|
|
|
|
## Complexity Tracking
|
|
|
|
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
|
|-----------|------------|-------------------------------------|
|
|
| New derived friction and reason taxonomy | The feature needs one shared project-wide rule for actions that already exist across multiple surfaces and panels. | Local constants and per-page copy edits would not prevent drift or make regression guardable. |
|
|
| New shared governance-action catalog | Multiple concrete families already exist and need one canonical source for friction, reason, vocabulary, and approved deviations. | Keeping all semantics inside individual page classes would duplicate logic, produce inconsistent naming, and make CI enforcement weak. |
|
|
|
|
## Proportionality Review
|
|
|
|
- **Current operator problem**: Similar governance actions currently carry different semantic weight, reason burden, and vocabulary depending on the surface.
|
|
- **Existing structure is insufficient because**: Current page-local action definitions and service calls do not provide one guardable source for friction class, reason requirement, or canonical wording across families.
|
|
- **Narrowest correct implementation**: Add a small derived catalog and enums for friction and reason policy, bind existing actions to those rules, and keep all state change in the current services.
|
|
- **Ownership cost created**: One small shared support namespace, one spec-scoped guard test, targeted page and service test updates, and one browser smoke suite.
|
|
- **Alternative intentionally rejected**: A generic governance workflow framework or persisted action matrix was rejected because the repo only needs explicit cross-surface semantics, not a new runtime engine.
|
|
- **Release truth**: current-release operator safety, auditability, and semantic consistency
|
|
|
|
## Implementation Strategy
|
|
|
|
### Phase A - Codify the shared governance semantics contract
|
|
|
|
Goal: create one derived, testable source for action families without introducing a new workflow engine.
|
|
|
|
Changes:
|
|
|
|
- Add `GovernanceFrictionClass` and `GovernanceReasonPolicy` enums.
|
|
- Add `GovernanceActionRule` plus `GovernanceActionCatalog` as the canonical mapping of action family, friction, reason policy, danger expectation, and canonical copy.
|
|
- Declare the current-release indirect risk-acceptance continuity rule so finding exception semantics remain the canonical carrier until a direct risk-acceptance surface exists.
|
|
- Add `Spec194GovernanceActionSemanticsGuardTest.php` to ensure every in-scope action family and documented deviation is declared.
|
|
- Keep the catalog derived only. Do not create DB tables or stored mirrors.
|
|
|
|
Tests:
|
|
|
|
- Add `GovernanceActionCatalogTest.php` for catalog completeness and invariants.
|
|
- Add `Spec194GovernanceActionSemanticsGuardTest.php` for project-level inventory and exception coverage.
|
|
|
|
### Phase B - Align the highest-risk governance families
|
|
|
|
Goal: normalize the surfaces where semantic inconsistency carries the highest operator risk.
|
|
|
|
Changes:
|
|
|
|
- Align exception decision and lifecycle actions on `FindingExceptionsQueue` and `ViewFindingException`.
|
|
- Align review publication and archival semantics on `ViewTenantReview`.
|
|
- Align evidence refresh versus expiry on `EvidenceSnapshotResource` and `ViewEvidenceSnapshot`, keeping `Refresh evidence` as confirmed F1 with no operator-entered reason.
|
|
- Align run triage semantics on `System ViewRun`, keeping `Retry` as confirmed F1 with no operator-entered reason while `Mark investigated` and `Cancel` keep stronger rationale rules.
|
|
- Extend or standardize reason propagation in the owning services and audit loggers where F2 or F3 requires it.
|
|
|
|
Tests:
|
|
|
|
- Extend exception workflow and queue tests.
|
|
- Extend tenant review lifecycle and UI-contract tests.
|
|
- Extend evidence snapshot resource tests.
|
|
- Add or extend run-triage tests around `ViewRun`-owned actions and audit behavior.
|
|
|
|
### Phase C - Align supporting lifecycle families and preserve calm surfaces
|
|
|
|
Goal: finish cross-surface consistency without overcorrecting lower-risk actions.
|
|
|
|
Changes:
|
|
|
|
- Align finding close and reopen semantics across header, row, and bulk actions in `FindingResource`, `ViewFinding`, and `FindingWorkflowService`.
|
|
- Align tenant archive and restore semantics across `ViewTenant`, `EditTenant`, `TenantResource`, and current audit logging, keeping `Restore` as confirmed F1 with no operator-entered reason.
|
|
- Keep indirect risk-acceptance wording aligned with the exception family and document any allowed alias only in the shared catalog.
|
|
- Review `TenantlessOperationRunViewer` to ensure it stays context-first and does not drift into a triage surface unless justified.
|
|
- Keep navigation, export, and related-context actions explicitly outside governance friction.
|
|
|
|
Tests:
|
|
|
|
- Extend finding workflow header-, row-, and bulk-action tests, finding audit tests, and finding view-action tests.
|
|
- Extend tenant lifecycle RBAC, naming, and audit tests.
|
|
- Extend any affected operation viewer tests only if the viewer surface changes semantics.
|
|
|
|
### Phase D - Browser verification and final regression protection
|
|
|
|
Goal: prove the new semantics in a real browser and prevent new local exceptions from returning.
|
|
|
|
Changes:
|
|
|
|
- Add `Spec194GovernanceFrictionSmokeTest.php` covering exception queue/detail, review detail, evidence detail, system run detail, and tenant lifecycle surfaces.
|
|
- Ensure the guard layer fails when a new governance action lacks a declared family, friction class, reason rule, or documented deviation.
|
|
- Re-run formatting and the focused Sail verification pack.
|
|
|
|
Tests:
|
|
|
|
- Browser smoke coverage for visible friction, copy, and danger separation.
|
|
- Focused guard, feature, and authorization tests for all changed families.
|
|
|
|
## Risk Assessment
|
|
|
|
| Risk | Impact | Likelihood | Mitigation |
|
|
|------|--------|------------|------------|
|
|
| The catalog grows into a general workflow framework | Medium | Low | Keep only friction, reason, vocabulary, and deviation metadata; leave execution in existing services. |
|
|
| Reason capture is added inconsistently across services | High | Medium | Make reason policy family-owned and test propagation at service and audit levels. |
|
|
| Low-risk actions accidentally inherit F3 semantics | Medium | Medium | Keep explicit F0 and F1 boundaries in the catalog and browser smoke coverage. |
|
|
| Surface-specific copy diverges from the family canon | Medium | Medium | Use one catalog source for labels and heading copy where practical and guard with tests. |
|
|
| Authorization semantics drift while actions are reworked | High | Low | Reuse existing Policies and `UiEnforcement`, and extend positive plus negative RBAC tests. |
|
|
|
|
## Test Strategy
|
|
|
|
- Add `GovernanceActionCatalogTest.php` so friction, reason, and deviation rules remain internally consistent.
|
|
- Add `Spec194GovernanceActionSemanticsGuardTest.php` to validate that every in-scope family, indirect risk-acceptance alias, and documented exception is declared.
|
|
- Extend exception queue/detail tests to assert family-consistent reason prompts and semantic separation.
|
|
- Extend review, evidence, finding, run, tenant lifecycle, and audit tests where the plan changes semantics or reason propagation, including explicit header-, row-, and bulk-finding lifecycle coverage.
|
|
- Reuse existing RBAC feature tests to prove non-member `404`, member-without-capability `403`, and correct disabled-state behavior where UI enforcement remains visible.
|
|
- Add `Spec194GovernanceFrictionSmokeTest.php` using the existing spec-based browser smoke pattern already present in the repo.
|
|
- Run the focused Sail verification commands from `quickstart.md`, then run `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`.
|
|
|
|
## Constitution Check (Post-Design)
|
|
|
|
Re-check result: PASS.
|
|
|
|
- Livewire v4.0+ compliance remains intact because all touched surfaces stay inside the existing Filament v5 + Livewire v4 stack.
|
|
- Provider registration remains unchanged in `bootstrap/providers.php`.
|
|
- The plan changes no global-search semantics; affected surfaces are existing resource pages or standalone pages whose search behavior is unchanged.
|
|
- Destructive and governance-changing actions keep `->requiresConfirmation()` plus existing authorization.
|
|
- No new assets are introduced; existing `filament:assets` deployment behavior remains sufficient.
|