# 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.
