## Summary - amend the operator UI constitution and related SpecKit templates for the new UI/UX governance rules - add Spec 168 artifacts plus the tenant governance aggregate implementation used by the tenant dashboard, banner, and baseline compare landing surfaces - normalize Filament action surfaces around clickable-row inspection, grouped secondary actions, and explicit action-surface declarations across enrolled resources and pages - fix post-suite regressions in membership cache priming, finding workflow state refresh, tenant review derived-state invalidation, and tenant-bound backup-set related navigation ## Commit Series - `docs: amend operator UI constitution` - `spec: add tenant governance aggregate contract` - `feat: add tenant governance aggregate contract` - `refactor: normalize filament action surfaces` - `fix: resolve post-suite state regressions` ## Testing - `vendor/bin/sail artisan test --compact` - Result: `3176 passed, 8 skipped (17384 assertions)` ## Notes - Livewire v4 / Filament v5 stack remains unchanged - no provider registration changes; `bootstrap/providers.php` remains the relevant location - no new global-search resources or asset-registration changes in this branch Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #199
335 lines
9.6 KiB
YAML
335 lines
9.6 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: Tenant Governance Aggregate Internal Surface Contract
|
|
version: 0.1.0
|
|
summary: Internal logical contract for the shared tenant-governance summary aggregate
|
|
description: |
|
|
This contract is an internal planning artifact for Spec 168. It documents the
|
|
derived tenant-governance aggregate and the way tenant dashboard, banner, and
|
|
Baseline Compare landing surfaces consume it. The rendered routes still return
|
|
HTML. The structured schemas below describe the internal page and widget models
|
|
that must be derivable before rendering. This does not add a public HTTP API.
|
|
servers:
|
|
- url: /internal
|
|
x-governance-consumers:
|
|
- surface: tenant.dashboard.needs_attention
|
|
summarySource: tenant_governance_aggregate
|
|
accessPattern: widget_safe
|
|
guardScope:
|
|
- app/Filament/Widgets/Dashboard/NeedsAttention.php
|
|
requiredMarkers:
|
|
- 'TenantGovernanceAggregate'
|
|
- 'Needs Attention'
|
|
maxOccurrences:
|
|
- needle: 'Finding::query()'
|
|
max: 0
|
|
- surface: tenant.dashboard.baseline_governance
|
|
summarySource: tenant_governance_aggregate
|
|
accessPattern: widget_safe
|
|
guardScope:
|
|
- app/Filament/Widgets/Dashboard/BaselineCompareNow.php
|
|
requiredMarkers:
|
|
- 'TenantGovernanceAggregate'
|
|
- 'Baseline Governance'
|
|
- surface: tenant.banner.baseline_compare_coverage
|
|
summarySource: tenant_governance_aggregate
|
|
accessPattern: widget_safe
|
|
guardScope:
|
|
- app/Filament/Widgets/Tenant/BaselineCompareCoverageBanner.php
|
|
requiredMarkers:
|
|
- 'TenantGovernanceAggregate'
|
|
- 'nextActionUrl'
|
|
- surface: tenant.page.baseline_compare_landing
|
|
summarySource: tenant_governance_aggregate
|
|
accessPattern: page_safe
|
|
guardScope:
|
|
- app/Filament/Pages/BaselineCompareLanding.php
|
|
requiredMarkers:
|
|
- 'TenantGovernanceAggregate'
|
|
- 'Compare now'
|
|
paths:
|
|
/tenants/{tenant}/governance-aggregate:
|
|
get:
|
|
summary: Resolve the derived tenant-governance aggregate for one tenant
|
|
operationId: resolveTenantGovernanceAggregate
|
|
parameters:
|
|
- name: tenant
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Tenant route key or canonical tenant identifier for the current tenant scope.
|
|
- name: surface
|
|
in: query
|
|
required: false
|
|
schema:
|
|
$ref: '#/components/schemas/GovernanceSurface'
|
|
responses:
|
|
'200':
|
|
description: Aggregate resolved for the current tenant scope
|
|
content:
|
|
application/vnd.tenantpilot.tenant-governance-aggregate+json:
|
|
schema:
|
|
$ref: '#/components/schemas/TenantGovernanceAggregate'
|
|
'403':
|
|
description: Actor is in scope but lacks the capability required to view the target surface
|
|
'404':
|
|
description: Tenant is outside workspace or tenant entitlement scope
|
|
/admin/t/{tenant}:
|
|
get:
|
|
summary: Tenant dashboard governance summary surfaces
|
|
operationId: viewTenantDashboardGovernance
|
|
parameters:
|
|
- name: tenant
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Rendered tenant dashboard with shared governance summary surfaces
|
|
content:
|
|
text/html:
|
|
schema:
|
|
type: string
|
|
application/vnd.tenantpilot.tenant-dashboard-governance+json:
|
|
schema:
|
|
$ref: '#/components/schemas/TenantDashboardGovernanceBundle'
|
|
'403':
|
|
description: Actor is in scope but lacks the required tenant capability
|
|
'404':
|
|
description: Tenant is not visible in the current workspace or membership scope
|
|
/admin/t/{tenant}/baseline-compare-landing:
|
|
get:
|
|
summary: Baseline Compare landing governance summary and diagnostics split
|
|
operationId: viewBaselineCompareLandingGovernance
|
|
parameters:
|
|
- name: tenant
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Rendered Baseline Compare landing page
|
|
content:
|
|
text/html:
|
|
schema:
|
|
type: string
|
|
application/vnd.tenantpilot.baseline-compare-landing-governance+json:
|
|
schema:
|
|
$ref: '#/components/schemas/BaselineCompareLandingGovernanceView'
|
|
'403':
|
|
description: Actor is in scope but lacks the required tenant capability
|
|
'404':
|
|
description: Tenant is not visible in the current workspace or membership scope
|
|
components:
|
|
schemas:
|
|
GovernanceSurface:
|
|
type: string
|
|
enum:
|
|
- dashboard_needs_attention
|
|
- dashboard_baseline_governance
|
|
- baseline_compare_landing
|
|
- coverage_banner
|
|
NextActionTarget:
|
|
type: string
|
|
enum:
|
|
- findings
|
|
- run
|
|
- landing
|
|
- none
|
|
GovernanceCounts:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- visibleDriftFindingsCount
|
|
- overdueOpenFindingsCount
|
|
- expiringGovernanceCount
|
|
- lapsedGovernanceCount
|
|
- activeNonNewFindingsCount
|
|
- highSeverityActiveFindingsCount
|
|
properties:
|
|
visibleDriftFindingsCount:
|
|
type: integer
|
|
minimum: 0
|
|
overdueOpenFindingsCount:
|
|
type: integer
|
|
minimum: 0
|
|
expiringGovernanceCount:
|
|
type: integer
|
|
minimum: 0
|
|
lapsedGovernanceCount:
|
|
type: integer
|
|
minimum: 0
|
|
activeNonNewFindingsCount:
|
|
type: integer
|
|
minimum: 0
|
|
highSeverityActiveFindingsCount:
|
|
type: integer
|
|
minimum: 0
|
|
NextActionIntent:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- label
|
|
- target
|
|
properties:
|
|
label:
|
|
type: string
|
|
target:
|
|
$ref: '#/components/schemas/NextActionTarget'
|
|
ComparePosture:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- compareState
|
|
- stateFamily
|
|
- tone
|
|
- headline
|
|
- positiveClaimAllowed
|
|
properties:
|
|
compareState:
|
|
type: string
|
|
enum:
|
|
- no_tenant
|
|
- no_assignment
|
|
- no_snapshot
|
|
- idle
|
|
- comparing
|
|
- failed
|
|
- ready
|
|
stateFamily:
|
|
type: string
|
|
enum:
|
|
- positive
|
|
- caution
|
|
- stale
|
|
- action_required
|
|
- in_progress
|
|
- unavailable
|
|
tone:
|
|
type: string
|
|
enum:
|
|
- success
|
|
- warning
|
|
- danger
|
|
- info
|
|
- gray
|
|
headline:
|
|
type: string
|
|
supportingMessage:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
reasonCode:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
lastComparedLabel:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
positiveClaimAllowed:
|
|
type: boolean
|
|
TenantGovernanceAggregate:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- tenantId
|
|
- workspaceId
|
|
- posture
|
|
- counts
|
|
- nextAction
|
|
properties:
|
|
tenantId:
|
|
type: integer
|
|
workspaceId:
|
|
type: integer
|
|
profileName:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
posture:
|
|
$ref: '#/components/schemas/ComparePosture'
|
|
counts:
|
|
$ref: '#/components/schemas/GovernanceCounts'
|
|
nextAction:
|
|
$ref: '#/components/schemas/NextActionIntent'
|
|
operationRunId:
|
|
type:
|
|
- integer
|
|
- 'null'
|
|
diagnosticsOwner:
|
|
type: string
|
|
enum:
|
|
- baseline_compare_stats
|
|
NeedsAttentionItem:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- title
|
|
- badge
|
|
- badgeColor
|
|
properties:
|
|
title:
|
|
type: string
|
|
body:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
supportingMessage:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
badge:
|
|
type: string
|
|
badgeColor:
|
|
type: string
|
|
nextStep:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
TenantDashboardGovernanceBundle:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- aggregate
|
|
properties:
|
|
aggregate:
|
|
$ref: '#/components/schemas/TenantGovernanceAggregate'
|
|
needsAttentionItems:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/NeedsAttentionItem'
|
|
baselineGovernanceCard:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- aggregate
|
|
properties:
|
|
aggregate:
|
|
$ref: '#/components/schemas/TenantGovernanceAggregate'
|
|
BaselineCompareLandingGovernanceView:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- aggregate
|
|
- diagnosticsPolicy
|
|
properties:
|
|
aggregate:
|
|
$ref: '#/components/schemas/TenantGovernanceAggregate'
|
|
diagnosticsPolicy:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- compareDiagnosticsRemainLocal
|
|
- evidenceGapDetailsRemainLocal
|
|
- compareActionUnchanged
|
|
properties:
|
|
compareDiagnosticsRemainLocal:
|
|
type: boolean
|
|
evidenceGapDetailsRemainLocal:
|
|
type: boolean
|
|
compareActionUnchanged:
|
|
type: boolean |