TenantAtlas/specs/175-workspace-governance-attention/data-model.md
ahmido 98be510362 feat: harden workspace governance attention foundation (#206)
## Summary
- harden the workspace overview into a governance-aware attention surface that separates governance risk from activity and keeps calm states honest
- add tenant-bound attention, workspace-wide operations continuity, and low-permission fallback behavior for workspace-originated operations drill-through
- add the full Spec 175 artifact set and focused workspace overview regression coverage, plus align remaining operation-viewer wording and guard expectations so the suite stays green

## Testing
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/WorkspaceOverviewAccessTest.php tests/Feature/Filament/WorkspaceOverviewAuthorizationTest.php tests/Feature/Filament/WorkspaceOverviewLandingTest.php tests/Feature/Filament/WorkspaceOverviewNavigationTest.php tests/Feature/Filament/WorkspaceOverviewContentTest.php tests/Feature/Filament/WorkspaceOverviewEmptyStatesTest.php tests/Feature/Filament/WorkspaceOverviewPermissionVisibilityTest.php tests/Feature/Filament/WorkspaceOverviewOperationsTest.php tests/Feature/Filament/WorkspaceOverviewDbOnlyTest.php tests/Feature/Filament/WorkspaceOverviewGovernanceAttentionTest.php tests/Feature/Filament/WorkspaceOverviewSummaryMetricsTest.php tests/Feature/Filament/WorkspaceOverviewDrilldownContinuityTest.php`
- `vendor/bin/sail artisan test --compact tests/Unit/Support/RelatedActionLabelCatalogTest.php tests/Feature/078/VerificationReportTenantlessTest.php tests/Feature/144/CanonicalOperationViewerContextMismatchTest.php tests/Feature/Baselines/BaselineCompareSummaryAssessmentTest.php tests/Feature/Baselines/TenantGovernanceAggregateResolverTest.php tests/Feature/Filament/ReferencedTenantLifecyclePresentationTest.php tests/Feature/Guards/NoAdHocFilamentAuthPatternsTest.php tests/Feature/Monitoring/AuditLogInspectFlowTest.php tests/Feature/Monitoring/HeaderContextBarTest.php tests/Feature/Monitoring/OperationLifecycleFreshnessPresentationTest.php tests/Feature/Monitoring/OperationRunResolvedReferencePresentationTest.php tests/Feature/Notifications/OperationRunNotificationTest.php tests/Feature/OpsUx/QueuedToastCopyTest.php tests/Feature/OpsUx/TerminalNotificationFailureMessageTest.php tests/Feature/System/OpsRunbooks/OpsUxStartSurfaceContractTest.php tests/Feature/Verification/VerificationReportRedactionTest.php`
- `vendor/bin/sail bin pint --dirty --format agent`
- `vendor/bin/sail artisan test --compact`

## Notes
- branch pushed as `175-workspace-governance-attention`
- full suite result: `3235 passed, 8 skipped`

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #206
2026-04-04 21:14:43 +00:00

314 lines
14 KiB
Markdown

# Phase 1 Data Model: Workspace Governance Attention Foundation
## Overview
This feature does not add a table, persisted workspace summary, or new cross-domain runtime subsystem. It aligns the existing workspace overview surface with already-available tenant truth so the workspace home can answer which visible tenants need governance attention, why they need it, and where the operator should jump next.
## Persistent Source Truths
### Workspace
**Purpose**: Scope boundary for the workspace home and all workspace-safe aggregates.
**Key fields**:
- `id`
- `name`
- `slug`
**Validation rules**:
- Workspace overview aggregation must always resolve for one explicit workspace.
- Non-members must receive deny-as-not-found behavior before any workspace truth is rendered.
### Tenant
**Purpose**: Scope boundary and identity anchor for every governance-aware workspace attention item.
**Key fields**:
- `id`
- `workspace_id`
- `external_id`
- `name`
- `status`
**Validation rules**:
- Only active tenants inside the current workspace and inside the current user's entitled tenant slice may contribute to workspace attention or governance-risk metrics.
- Every workspace attention item must identify one visible tenant explicitly.
### Finding
**Purpose**: Source of overdue findings, high-severity active findings, and other governance workflow pressure promoted into workspace attention.
**Key fields**:
- `tenant_id`
- `workspace_id`
- `finding_type`
- `status`
- `severity`
- `due_at`
- `scope_key`
**Validation rules**:
- Canonical open and active semantics remain sourced from existing finding query helpers.
- Workspace promotion must not invent a second finding status universe.
### FindingException / Governance Validity
**Purpose**: Source of lapsed governance and expiring governance truth for risk-accepted findings.
**Key fields**:
- `tenant_id`
- `workspace_id`
- `finding_id`
- `status`
- `current_validity_state`
- `review_due_at`
- `expires_at`
**Validation rules**:
- Lapsed and expiring governance remain derived from existing validity-state rules.
- Workspace promotion must not replace existing governance-validity semantics with a new workspace-specific status family.
### OperationRun
**Purpose**: Source of workspace activity, operation failures, and canonical operation drill-through.
**Key fields**:
- `id`
- `workspace_id`
- `tenant_id`
- `type`
- `status`
- `outcome`
- `created_at`
- `completed_at`
**Validation rules**:
- Active operations and failed or warning operations remain activity truths, not governance truths.
- Workspace attention may still include operations follow-up, but those items must remain semantically distinct from governance items.
### AlertDelivery
**Purpose**: Source of workspace alert-delivery failures that remain supporting attention but no longer define workspace calmness by themselves.
**Key fields**:
- `workspace_id`
- `tenant_id`
- `status`
- `created_at`
**Validation rules**:
- Alert-delivery failures remain lower-priority supporting signals once governance-critical tenant states exist.
### EvidenceSnapshot and TenantReview
**Purpose**: Existing tenant-level evidence and review truth that may serve as a precise workspace drill-through target when already-available truth makes them the best next jump.
**Key fields**:
- `tenant_id`
- `workspace_id`
- `status` or completeness fields on the owning model
- associated detail identifiers needed by tenant evidence or review resources
**Validation rules**:
- This slice does not add a new workspace evidence or review aggregate.
- Evidence or review destinations may only be used when existing tenant truth already makes them the most precise action target.
## Existing Runtime Source Objects
### TenantGovernanceAggregate
**Purpose**: Existing derived tenant summary that already combines compare posture with overdue, expiring, lapsed, and high-severity counts.
**Key consumed fields**:
- `tenantId`
- `workspaceId`
- `compareState`
- `stateFamily`
- `tone`
- `headline`
- `supportingMessage`
- `overdueOpenFindingsCount`
- `expiringGovernanceCount`
- `lapsedGovernanceCount`
- `highSeverityActiveFindingsCount`
- `nextActionLabel`
- `nextActionTarget`
- `positiveClaimAllowed`
- `summaryAssessment`
**Validation rules**:
- Workspace promotion should consume this existing summary contract before considering lower-level recomputation.
- Any workspace calmness or ranking rule based on compare or governance must remain consistent with this aggregate.
### BaselineCompareStats
**Purpose**: Existing compare-backed statistics object underlying the tenant governance aggregate.
**Key consumed fields**:
- `overdueOpenFindingsCount`
- `expiringGovernanceCount`
- `lapsedGovernanceCount`
- `highSeverityActiveFindingsCount`
- compare posture state and evidence-gap fields needed by `summaryAssessment`
**Validation rules**:
- Workspace code should not fork a second compare-summary model while this object already provides the necessary facts.
### BaselineCompareSummaryAssessment
**Purpose**: Existing compare posture contract that maps compare stats into a state family, tone, headline, and next-action intent.
**Key consumed fields**:
- `stateFamily`
- `tone`
- `headline`
- `supportingMessage`
- `reasonCode`
- `nextActionTarget()` semantics as reflected into the aggregate
**Validation rules**:
- Workspace compare attention and calmness suppression should reuse this assessment path rather than inventing a workspace-only tone system.
### WorkspaceOverviewBuilder Payload
**Purpose**: Existing page-level payload that already carries summary metrics, attention items, recent operations, quick actions, and empty states for `/admin`.
**Validation rules**:
- Governance hardening extends this payload shape rather than replacing the page with a new surface framework.
- Existing visible-tenant filtering remains the workspace aggregation guardrail.
## Derived Workspace View Contracts
### Workspace Summary Metric
**Purpose**: Compact workspace stat that answers one scope, governance-risk, or activity question and optionally opens one matching destination.
#### Fields
| Field | Type | Required | Description |
|------|------|----------|-------------|
| `key` | string | yes | Stable metric identity such as `accessible_tenants`, `governance_attention_tenants`, `overdue_findings_tenants`, or `active_operations` |
| `label` | string | yes | Operator-facing label that must accurately describe the counted universe |
| `value` | integer | yes | Metric value |
| `category` | enum | yes | `scope`, `governance_risk`, `activity`, or `alerts` |
| `description` | string | yes | Short explanation of what the metric means |
| `color` | string | yes | Existing tone family used by the widget |
| `destination` | object nullable | no | Shared drill-through contract when the metric is actionable |
#### Validation rules
- Governance-risk metrics count affected visible tenants, not raw issue totals.
- Activity metrics remain activity-only and must not imply governance health.
- The stat strip must make the difference between `governance_risk` and `activity` categories obvious.
### Workspace Attention Item
**Purpose**: One prioritized workspace triage item that names a visible tenant problem and one next jump.
#### Fields
| Field | Type | Required | Description |
|------|------|----------|-------------|
| `key` | string | yes | Stable attention identity such as `tenant_overdue_findings`, `tenant_lapsed_governance`, `tenant_compare_attention`, or `tenant_failed_operation` |
| `tenantId` | integer | yes | Visible tenant identifier |
| `tenantLabel` | string | yes | Tenant name shown to the operator |
| `family` | enum | yes | `governance`, `findings`, `compare`, `evidence`, `review`, `operations`, or `alerts` |
| `urgency` | enum | yes | `critical`, `high`, `medium`, or `supporting` |
| `title` | string | yes | Primary operator-facing summary |
| `body` | string | yes | Short explanation of why this needs attention |
| `badge` | string | yes | Existing family label shown in the UI |
| `badgeColor` | string | yes | Existing tone family used for the item |
| `supportingMessage` | string nullable | no | Secondary explanatory text when needed |
| `destination` | object nullable | no | Shared drill-through contract |
| `actionDisabled` | boolean nullable | no | Whether the visible next step is intentionally disabled |
| `helperText` | string nullable | no | Explanation when the visible next step is disabled |
#### Validation rules
- Every workspace attention item is tenant-bound and must include both `tenantId` and `tenantLabel`.
- Governance, findings, compare, evidence or review, and operations items must remain semantically distinct.
- Compare attention promotes `BaselineCompareSummaryAssessment::STATE_STALE` directly and only treats `BaselineCompareSummaryAssessment::STATE_ACTION_REQUIRED` as materially degraded compare posture when the aggregate's next action remains compare-specific rather than findings-driven.
- `BaselineCompareSummaryAssessment::STATE_CAUTION` stays below the workspace-attention threshold unless another governance signal independently warrants promotion.
- Workspace-wide operations or alert totals remain in summary metrics or recent operations until they can be attributed to one visible tenant.
- Each item may expose one primary destination only.
- Every item must either expose a non-null destination or set `actionDisabled=true` with explanatory `helperText`; null destination without an explicit disabled state is invalid.
- If the most precise destination is not available to the current in-scope user, the item must either use an allowed fallback or expose a disabled explanatory state instead of a clickable dead end.
### Workspace Recent Operation
**Purpose**: One bounded recent-operations entry shown on the workspace overview as diagnostic recency, not governance posture.
#### Fields
| Field | Type | Required | Description |
|------|------|----------|-------------|
| `id` | integer | yes | Operation run identifier |
| `title` | string | yes | Operator-facing operation label |
| `tenantLabel` | string nullable | no | Tenant name when the run is tenant-bound |
| `statusLabel` | string | yes | Human-readable run status |
| `statusColor` | string | yes | Existing tone family for the run status |
| `outcomeLabel` | string | yes | Human-readable run outcome |
| `outcomeColor` | string | yes | Existing tone family for the run outcome |
| `guidance` | string nullable | no | Short follow-up guidance when helpful |
| `startedAt` | string | yes | Render-ready recency label |
| `destination` | object | yes | Canonical operation-detail drill-through target |
#### Validation rules
- The recent-operations collection is bounded to the five most recent visible runs.
- Recent operations remain diagnostic context and do not define calmness on their own.
- `tenantLabel` may be null only when the run is genuinely workspace-wide rather than tenant-bound.
### Workspace Drill-Through Target
**Purpose**: Shared navigation contract used by summary metrics and attention items.
#### Fields
| Field | Type | Required | Description |
|------|------|----------|-------------|
| `kind` | enum | yes | `choose_tenant`, `tenant_dashboard`, `tenant_findings`, `baseline_compare_landing`, `tenant_evidence`, `tenant_reviews`, `operations_index`, `operation_detail`, `alerts_overview`, `switch_workspace`, or `none` |
| `url` | string nullable | no | Destination URL when the target is actionable |
| `tenantRouteKey` | string nullable | no | Tenant route scope when the destination is tenant-bound |
| `filters` | object nullable | no | Query or state needed to reproduce the same subset on the destination |
| `label` | string nullable | no | Primary action label |
| `disabled` | boolean | yes | Whether the target is intentionally non-clickable |
| `helperText` | string nullable | no | Explanation shown when the target is disabled |
#### Validation rules
- `kind=none` may only be used for intentionally passive reassurance states.
- `tenant_findings` must carry the filter state needed to reproduce overdue, high-severity, expiring-governance, or other directly filterable findings subsets when applicable.
- Aggregate lapsed-governance attention uses `tenant_dashboard` when the current tenant findings filters would otherwise narrow the full invalid-governance family to a smaller subset such as `missing_support`.
- `operations_index` may carry tenant and tab filters but must remain the canonical admin operations route and the workspace-member-safe fallback for low-permission workspace states.
- `alerts_overview` targets the existing alerts overview at `/admin/alerts`, which remains the canonical alert-delivery follow-up surface for this slice.
- `switch_workspace` targets `/admin/choose-workspace` and is the default zero-tenant recovery action.
### Workspace Calmness State
**Purpose**: The derived claim that the workspace is currently calm enough for an empty or reassurance state.
#### Fields
| Field | Type | Required | Description |
|------|------|----------|-------------|
| `isCalm` | boolean | yes | Whether the workspace may currently make a calmness claim |
| `checkedDomains` | array<enum> | yes | Domains actually checked before the claim was made: `governance`, `findings`, `compare`, `evidence`, `review`, `operations`, `alerts`, `tenant_access` |
| `title` | string | yes | Empty-state or reassurance title |
| `body` | string | yes | Supporting explanation constrained to the checked domains |
| `nextAction` | object | yes | One bounded next action |
#### Validation rules
- `isCalm=true` is invalid whenever any visible tenant has governance-critical conditions inside the checked domains.
- Zero-tenant states and low-permission states must not masquerade as healthy calmness states.
- Zero-tenant states default `nextAction.kind` to `switch_workspace`, while low-permission states default `nextAction.kind` to `operations_index` unless a more specific allowed in-scope recovery action exists.
- Calm wording must not imply portfolio health beyond the `checkedDomains` list.
## Ranking Rules
1. Governance-critical tenant conditions outrank activity-only and alert-only items.
2. A single tenant may contribute multiple raw issues, but workspace attention should surface a bounded prioritized subset.
3. The stat strip answers portfolio counts by tenant, while the attention list answers which tenant to open next.
4. Recent operations remain supporting recency context and do not participate in calmness unless explicitly modeled as an operations-follow-up issue.