553 lines
16 KiB
YAML
553 lines
16 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: Tenant Dashboard Truth Alignment Internal Surface Contract
|
|
version: 0.1.0
|
|
summary: Internal logical contract for aligned tenant dashboard KPI, attention, compare, and recency surfaces
|
|
description: |
|
|
This contract is an internal planning artifact for Spec 173. It documents how
|
|
the tenant dashboard's summary and recency surfaces must derive their meaning
|
|
from existing tenant truth and how drill-through destinations must preserve
|
|
that meaning. 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-dashboard-consumers:
|
|
- surface: tenant.dashboard.kpis
|
|
summarySource:
|
|
- finding_status_helpers
|
|
- finding_destination_filters
|
|
- canonical_operations_links
|
|
guardScope:
|
|
- app/Filament/Widgets/Dashboard/DashboardKpis.php
|
|
expectedContract:
|
|
- each_kpi_label_matches_its_count_universe
|
|
- each_kpi_destination_reproduces_or_explicitly_broadens_the_named_subset
|
|
- surface: tenant.dashboard.needs_attention
|
|
summarySource:
|
|
- tenant_governance_aggregate
|
|
- operation_run_activity
|
|
guardScope:
|
|
- app/Filament/Widgets/Dashboard/NeedsAttention.php
|
|
expectedContract:
|
|
- each_primary_item_has_one_tenant_safe_destination
|
|
- healthy_fallback_is_hidden_when_any_attention_condition_exists
|
|
- surface: tenant.dashboard.baseline_compare_now
|
|
summarySource:
|
|
- tenant_governance_aggregate
|
|
- baseline_compare_summary_assessment
|
|
guardScope:
|
|
- app/Filament/Widgets/Dashboard/BaselineCompareNow.php
|
|
expectedContract:
|
|
- positive_compare_claims_do_not_outvote_stronger_attention_conditions
|
|
- primary_compare_destination_uses_existing_baseline_compare_landing
|
|
- surface: tenant.dashboard.recent_drift_findings
|
|
summarySource:
|
|
- recent_drift_query
|
|
guardScope:
|
|
- app/Filament/Widgets/Dashboard/RecentDriftFindings.php
|
|
expectedContract:
|
|
- surface_role_is_diagnostic_recency_not_primary_queue
|
|
- row_click_uses_canonical_finding_detail
|
|
- surface: tenant.dashboard.recent_operations
|
|
summarySource:
|
|
- recent_operations_query
|
|
- canonical_operations_links
|
|
guardScope:
|
|
- app/Filament/Widgets/Dashboard/RecentOperations.php
|
|
expectedContract:
|
|
- surface_role_is_diagnostic_recency_not_primary_queue
|
|
- row_click_uses_canonical_operation_detail
|
|
paths:
|
|
/admin/t/{tenant}:
|
|
get:
|
|
summary: Render the aligned tenant dashboard summary bundle
|
|
operationId: viewTenantDashboardAlignedTruth
|
|
parameters:
|
|
- name: tenant
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Tenant dashboard rendered with aligned KPI, attention, compare, and recency semantics
|
|
content:
|
|
text/html:
|
|
schema:
|
|
type: string
|
|
application/vnd.tenantpilot.tenant-dashboard-truth+json:
|
|
schema:
|
|
$ref: '#/components/schemas/TenantDashboardTruthBundle'
|
|
'404':
|
|
description: Tenant is outside workspace or tenant entitlement scope
|
|
/admin/t/{tenant}/findings:
|
|
get:
|
|
summary: Tenant findings destination used by KPI and attention drill-throughs
|
|
operationId: openTenantFindingsFromDashboard
|
|
parameters:
|
|
- name: tenant
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- name: tab
|
|
in: query
|
|
required: false
|
|
schema:
|
|
$ref: '#/components/schemas/FindingsTab'
|
|
- name: high_severity
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type: boolean
|
|
- name: status
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type: string
|
|
- name: finding_type
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Tenant findings list opened with tenant-safe dashboard continuity filters
|
|
'403':
|
|
description: Actor is in scope but lacks findings inspection capability
|
|
'404':
|
|
description: Tenant is outside workspace or tenant entitlement scope
|
|
/admin/t/{tenant}/baseline-compare-landing:
|
|
get:
|
|
summary: Tenant baseline compare landing used by compare and attention drill-throughs
|
|
operationId: openTenantBaselineCompareLandingFromDashboard
|
|
parameters:
|
|
- name: tenant
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Tenant baseline compare landing opened with the same tenant-context compare posture the dashboard summarized
|
|
'403':
|
|
description: Actor is in scope but lacks baseline compare inspection capability
|
|
'404':
|
|
description: Tenant is outside workspace or tenant entitlement scope
|
|
/admin/t/{tenant}/findings/{record}:
|
|
get:
|
|
summary: Tenant finding detail opened from recent drift row-click inspection
|
|
operationId: openTenantFindingDetailFromDashboardRecency
|
|
parameters:
|
|
- name: tenant
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- name: record
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Tenant finding detail opened from the recent drift diagnostic surface
|
|
'403':
|
|
description: Actor is in scope but lacks finding detail inspection capability
|
|
'404':
|
|
description: Tenant or finding is outside entitlement scope
|
|
/admin/operations:
|
|
get:
|
|
summary: Canonical operations destination with tenant-prefilter continuity from the tenant dashboard
|
|
operationId: openCanonicalOperationsFromDashboard
|
|
parameters:
|
|
- name: tenant_id
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type:
|
|
- integer
|
|
- string
|
|
description: Tenant filter carried forward from tenant-context dashboard navigation.
|
|
- name: activeTab
|
|
in: query
|
|
required: false
|
|
description: Uses `active` for healthy queued or running activity, `blocked` for warning, stalled, or unusually long-running follow-up needing review, and `failed` for terminal failure follow-up.
|
|
schema:
|
|
$ref: '#/components/schemas/OperationsTab'
|
|
- name: navigationContext
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type: string
|
|
description: Optional serialized canonical navigation context carried from tenant dashboard drill-throughs.
|
|
responses:
|
|
'200':
|
|
description: Canonical admin operations list filtered to the originating tenant when opened from the dashboard
|
|
'403':
|
|
description: Actor is in scope but lacks operations inspection capability
|
|
'404':
|
|
description: Tenant context is outside entitlement scope
|
|
/admin/operations/{run}:
|
|
get:
|
|
summary: Canonical operation detail opened from recent operations row-click inspection
|
|
operationId: openOperationDetailFromDashboardRecency
|
|
parameters:
|
|
- name: run
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type:
|
|
- integer
|
|
- string
|
|
responses:
|
|
'200':
|
|
description: Canonical operation detail opened from the recent operations diagnostic surface
|
|
'403':
|
|
description: Actor is in scope but lacks operation detail inspection capability
|
|
'404':
|
|
description: Operation run is outside entitlement scope
|
|
components:
|
|
schemas:
|
|
FindingsTab:
|
|
type: string
|
|
enum:
|
|
- all
|
|
- needs_action
|
|
- overdue
|
|
- risk_accepted
|
|
- resolved
|
|
OperationsTab:
|
|
type: string
|
|
description: Shared canonical operations tab semantics where `active` represents healthy queued or running work, `blocked` reproduces warning, stalled, or unusually long-running follow-up, and `failed` reproduces terminal failure follow-up.
|
|
enum:
|
|
- all
|
|
- active
|
|
- blocked
|
|
- succeeded
|
|
- partial
|
|
- failed
|
|
ProblemFamily:
|
|
type: string
|
|
enum:
|
|
- findings
|
|
- governance
|
|
- compare
|
|
- operations
|
|
FindingUniverse:
|
|
type: string
|
|
enum:
|
|
- new_drift_only
|
|
- open_drift
|
|
- active_findings
|
|
SeverityUniverse:
|
|
type: string
|
|
enum:
|
|
- high_only
|
|
- high_and_critical
|
|
FindingsDestinationFilterState:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- tenant
|
|
properties:
|
|
tenant:
|
|
type: string
|
|
tab:
|
|
oneOf:
|
|
- $ref: '#/components/schemas/FindingsTab'
|
|
- type: 'null'
|
|
status:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
high_severity:
|
|
type:
|
|
- boolean
|
|
- 'null'
|
|
finding_type:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
OperationsDestinationFilterState:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- workspace_id
|
|
- tenant_id
|
|
properties:
|
|
workspace_id:
|
|
type: integer
|
|
tenant_id:
|
|
type:
|
|
- integer
|
|
- string
|
|
activeTab:
|
|
oneOf:
|
|
- $ref: '#/components/schemas/OperationsTab'
|
|
- type: 'null'
|
|
navigationContext:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
DestinationKind:
|
|
type: string
|
|
enum:
|
|
- tenant_findings
|
|
- baseline_compare_landing
|
|
- canonical_operations
|
|
- operation_detail
|
|
- finding_detail
|
|
- none
|
|
SurfaceDestination:
|
|
type: object
|
|
additionalProperties: false
|
|
allOf:
|
|
- if:
|
|
properties:
|
|
actionDisabled:
|
|
const: true
|
|
then:
|
|
required:
|
|
- helperText
|
|
required:
|
|
- kind
|
|
- tenantScoped
|
|
- semanticsLabel
|
|
properties:
|
|
kind:
|
|
$ref: '#/components/schemas/DestinationKind'
|
|
tenantScoped:
|
|
type: boolean
|
|
semanticsLabel:
|
|
type: string
|
|
filterState:
|
|
oneOf:
|
|
- $ref: '#/components/schemas/FindingsDestinationFilterState'
|
|
- $ref: '#/components/schemas/OperationsDestinationFilterState'
|
|
- type: 'null'
|
|
actionDisabled:
|
|
type:
|
|
- boolean
|
|
- 'null'
|
|
helperText:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
ActionableDestinationKind:
|
|
type: string
|
|
enum:
|
|
- tenant_findings
|
|
- baseline_compare_landing
|
|
- canonical_operations
|
|
KpiDestinationKind:
|
|
type: string
|
|
enum:
|
|
- tenant_findings
|
|
- canonical_operations
|
|
- none
|
|
ActionableSurfaceDestination:
|
|
allOf:
|
|
- $ref: '#/components/schemas/SurfaceDestination'
|
|
- type: object
|
|
properties:
|
|
kind:
|
|
$ref: '#/components/schemas/ActionableDestinationKind'
|
|
KpiSurfaceDestination:
|
|
allOf:
|
|
- $ref: '#/components/schemas/SurfaceDestination'
|
|
- type: object
|
|
properties:
|
|
kind:
|
|
$ref: '#/components/schemas/KpiDestinationKind'
|
|
KpiMetric:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- key
|
|
- label
|
|
- count
|
|
- problemFamily
|
|
- destination
|
|
properties:
|
|
key:
|
|
type: string
|
|
label:
|
|
type: string
|
|
count:
|
|
type: integer
|
|
minimum: 0
|
|
problemFamily:
|
|
type: string
|
|
enum:
|
|
- findings
|
|
- operations
|
|
findingUniverse:
|
|
oneOf:
|
|
- $ref: '#/components/schemas/FindingUniverse'
|
|
- type: 'null'
|
|
severityUniverse:
|
|
oneOf:
|
|
- type: string
|
|
enum:
|
|
- high_only
|
|
- high_and_critical
|
|
- type: 'null'
|
|
destination:
|
|
$ref: '#/components/schemas/KpiSurfaceDestination'
|
|
AttentionItem:
|
|
type: object
|
|
additionalProperties: false
|
|
anyOf:
|
|
- required:
|
|
- actionLabel
|
|
- required:
|
|
- nextStepLabel
|
|
- properties:
|
|
actionDisabled:
|
|
const: true
|
|
required:
|
|
- actionDisabled
|
|
- helperText
|
|
required:
|
|
- key
|
|
- title
|
|
- body
|
|
- badge
|
|
- tone
|
|
- problemFamily
|
|
- destination
|
|
properties:
|
|
key:
|
|
type: string
|
|
title:
|
|
type: string
|
|
body:
|
|
type: string
|
|
supportingMessage:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
badge:
|
|
type: string
|
|
tone:
|
|
type: string
|
|
enum:
|
|
- success
|
|
- warning
|
|
- danger
|
|
- info
|
|
- gray
|
|
problemFamily:
|
|
$ref: '#/components/schemas/ProblemFamily'
|
|
actionLabel:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
actionDisabled:
|
|
type:
|
|
- boolean
|
|
- 'null'
|
|
helperText:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
nextStepLabel:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
destination:
|
|
$ref: '#/components/schemas/ActionableSurfaceDestination'
|
|
CompareSummary:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- stateFamily
|
|
- tone
|
|
- headline
|
|
- positiveClaimAllowed
|
|
- nextAction
|
|
properties:
|
|
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'
|
|
positiveClaimAllowed:
|
|
type: boolean
|
|
nextAction:
|
|
$ref: '#/components/schemas/SurfaceDestination'
|
|
DiagnosticSurfaceSummary:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- heading
|
|
- role
|
|
- doesNotDefinePosture
|
|
- fullRowClick
|
|
- detailDestinationKind
|
|
properties:
|
|
heading:
|
|
type: string
|
|
role:
|
|
type: string
|
|
enum:
|
|
- diagnostic_recency
|
|
doesNotDefinePosture:
|
|
type: boolean
|
|
fullRowClick:
|
|
type: boolean
|
|
detailDestinationKind:
|
|
type: string
|
|
enum:
|
|
- finding_detail
|
|
- operation_detail
|
|
TenantDashboardTruthBundle:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- tenantId
|
|
- workspaceId
|
|
- kpis
|
|
- attentionItems
|
|
- compareSummary
|
|
- recentFindings
|
|
- recentOperations
|
|
properties:
|
|
tenantId:
|
|
type: integer
|
|
workspaceId:
|
|
type: integer
|
|
kpis:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/KpiMetric'
|
|
attentionItems:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/AttentionItem'
|
|
compareSummary:
|
|
$ref: '#/components/schemas/CompareSummary'
|
|
recentFindings:
|
|
$ref: '#/components/schemas/DiagnosticSurfaceSummary'
|
|
recentOperations:
|
|
$ref: '#/components/schemas/DiagnosticSurfaceSummary' |