## Summary - harden findings and finding-exception Filament surfaces so workflow state, governance validity, overdue urgency, and next action are operator-first - add tenant stats widgets, segmented tabs, richer governance warnings, and baseline/dashboard attention propagation for overdue and lapsed governance states - add Spec 166 artifacts plus regression coverage for findings, badges, baseline summaries, tenantless operation viewer behavior, and critical table standards ## Verification - `vendor/bin/sail bin pint --dirty --format agent` - `vendor/bin/sail artisan test --compact` ## Filament Notes - Livewire v4.0+ compliance: yes, implementation stays on Filament v5 / Livewire v4 APIs only - Provider registration: unchanged, Laravel 12 panel/provider registration remains in `bootstrap/providers.php` - Global search: unchanged in this slice; `FindingExceptionResource` stays not globally searchable, no new globally searchable resource was introduced - Destructive actions: existing revoke/reject/approve/renew/workflow mutations remain capability-gated and confirmation-gated where already defined - Asset strategy: no new assets added; existing deploy process remains unchanged, including `php artisan filament:assets` when registered assets are used - Testing plan delivered: findings list/detail, exception register, dashboard attention, baseline summary, badge semantics, and tenantless operation viewer coverage Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #197
329 lines
10 KiB
YAML
329 lines
10 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: Finding Governance Health Internal Contract
|
|
version: 0.1.0
|
|
description: |
|
|
Internal admin-plane contract for hardened finding governance and resolution semantics.
|
|
These endpoints represent the server-side data contract backing Filament and Livewire surfaces,
|
|
not a new public API.
|
|
servers:
|
|
- url: /api/internal
|
|
paths:
|
|
/tenants/{tenantId}/findings:
|
|
get:
|
|
summary: List findings with workflow, governance, and urgency semantics
|
|
operationId: listTenantFindingsWithGovernanceHealth
|
|
tags: [Findings]
|
|
parameters:
|
|
- $ref: '#/components/parameters/TenantId'
|
|
- name: status
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [new, acknowledged, triaged, in_progress, reopened, resolved, closed, risk_accepted]
|
|
- name: governanceValidity
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [valid, expiring, expired, revoked, rejected, missing_support]
|
|
- name: overdue
|
|
in: query
|
|
schema:
|
|
type: boolean
|
|
responses:
|
|
'200':
|
|
description: Findings list rows with operator-facing lifecycle and governance semantics
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/FindingListItem'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
/tenants/{tenantId}/findings/{findingId}:
|
|
get:
|
|
summary: View finding detail with leading status and governance zone
|
|
operationId: showFindingWithGovernanceHealth
|
|
tags: [Findings]
|
|
parameters:
|
|
- $ref: '#/components/parameters/TenantId'
|
|
- $ref: '#/components/parameters/FindingId'
|
|
responses:
|
|
'200':
|
|
description: Finding detail payload with primary operator summary and secondary diagnostics
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/FindingDetail'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
/tenants/{tenantId}/finding-exceptions:
|
|
get:
|
|
summary: List tenant exception records aligned with finding governance semantics
|
|
operationId: listTenantFindingExceptionsForGovernanceHealth
|
|
tags: [Finding Exceptions]
|
|
parameters:
|
|
- $ref: '#/components/parameters/TenantId'
|
|
- name: status
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [pending, active, expiring, expired, rejected, revoked, superseded]
|
|
- name: validity
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [valid, expiring, expired, revoked, rejected, missing_support]
|
|
responses:
|
|
'200':
|
|
description: Tenant exception register rows with governance validity and warnings
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/FindingExceptionSurfaceItem'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
/workspaces/{workspaceId}/finding-exceptions/queue:
|
|
get:
|
|
summary: Canonical exception queue with tenant-safe governance attention signals
|
|
operationId: listCanonicalFindingExceptionQueueForGovernanceHealth
|
|
tags: [Finding Exceptions]
|
|
parameters:
|
|
- $ref: '#/components/parameters/WorkspaceId'
|
|
- name: tenantId
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
- name: validity
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [valid, expiring, expired, revoked, rejected, missing_support]
|
|
responses:
|
|
'200':
|
|
description: Canonical queue rows filtered to entitled tenants only
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/FindingExceptionSurfaceItem'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
/tenants/{tenantId}/dashboard/needs-attention:
|
|
get:
|
|
summary: Tenant dashboard needs-attention summary including overdue and governance attention
|
|
operationId: showTenantNeedsAttentionSummary
|
|
tags: [Dashboard]
|
|
parameters:
|
|
- $ref: '#/components/parameters/TenantId'
|
|
responses:
|
|
'200':
|
|
description: Read-only summary items for tenant dashboard attention state
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/NeedsAttentionSummary'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
/tenants/{tenantId}/baseline-compare/summary:
|
|
get:
|
|
summary: Baseline compare summary with honest findings and governance attention cues
|
|
operationId: showBaselineCompareSummaryWithFindingGovernanceContext
|
|
tags: [Baseline Compare]
|
|
parameters:
|
|
- $ref: '#/components/parameters/TenantId'
|
|
responses:
|
|
'200':
|
|
description: Baseline compare summary payload with findings and governance attention context
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/BaselineCompareFindingSummary'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
components:
|
|
parameters:
|
|
TenantId:
|
|
name: tenantId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
FindingId:
|
|
name: findingId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
WorkspaceId:
|
|
name: workspaceId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
Forbidden:
|
|
description: Member lacks required capability in the current scope
|
|
NotFound:
|
|
description: Workspace or tenant scope is not entitled
|
|
schemas:
|
|
FindingListItem:
|
|
type: object
|
|
required: [id, workflowStatus, workflowFamily, severity, dueAttention, governance]
|
|
properties:
|
|
id:
|
|
type: integer
|
|
workflowStatus:
|
|
type: string
|
|
enum: [new, acknowledged, triaged, in_progress, reopened, resolved, closed, risk_accepted]
|
|
workflowFamily:
|
|
type: string
|
|
enum: [active, accepted_risk, historical]
|
|
severity:
|
|
type: string
|
|
enum: [low, medium, high, critical]
|
|
dueAttention:
|
|
type: string
|
|
enum: [none, due_soon, overdue]
|
|
ownerName:
|
|
type: string
|
|
nullable: true
|
|
assigneeName:
|
|
type: string
|
|
nullable: true
|
|
governance:
|
|
$ref: '#/components/schemas/GovernanceSignal'
|
|
FindingDetail:
|
|
allOf:
|
|
- $ref: '#/components/schemas/FindingListItem'
|
|
- type: object
|
|
properties:
|
|
primaryNextAction:
|
|
type: string
|
|
nullable: true
|
|
governanceWarning:
|
|
type: string
|
|
nullable: true
|
|
resolutionContext:
|
|
type: string
|
|
nullable: true
|
|
diagnostics:
|
|
type: object
|
|
description: Secondary diagnostic context such as run ids, fingerprints, and evidence sections
|
|
FindingExceptionSurfaceItem:
|
|
type: object
|
|
required: [id, status, validityState, findingId]
|
|
properties:
|
|
id:
|
|
type: integer
|
|
findingId:
|
|
type: integer
|
|
tenantId:
|
|
type: integer
|
|
nullable: true
|
|
status:
|
|
type: string
|
|
enum: [pending, active, expiring, expired, rejected, revoked, superseded]
|
|
validityState:
|
|
type: string
|
|
enum: [valid, expiring, expired, revoked, rejected, missing_support]
|
|
governanceWarning:
|
|
type: string
|
|
nullable: true
|
|
reviewDueAt:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
expiresAt:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
GovernanceSignal:
|
|
type: object
|
|
required: [attentionState]
|
|
properties:
|
|
validityState:
|
|
type: string
|
|
enum: [valid, expiring, expired, revoked, rejected, missing_support]
|
|
nullable: true
|
|
exceptionStatus:
|
|
type: string
|
|
enum: [pending, active, expiring, expired, rejected, revoked, superseded]
|
|
nullable: true
|
|
attentionState:
|
|
type: string
|
|
enum: [healthy, attention_needed, not_applicable]
|
|
warning:
|
|
type: string
|
|
nullable: true
|
|
NeedsAttentionSummary:
|
|
type: object
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
type: object
|
|
required: [title, body, badge]
|
|
properties:
|
|
title:
|
|
type: string
|
|
body:
|
|
type: string
|
|
badge:
|
|
type: string
|
|
badgeColor:
|
|
type: string
|
|
nextStep:
|
|
type: string
|
|
nullable: true
|
|
healthyChecks:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
title:
|
|
type: string
|
|
body:
|
|
type: string
|
|
BaselineCompareFindingSummary:
|
|
type: object
|
|
properties:
|
|
findingsCount:
|
|
type: integer
|
|
summaryHeadline:
|
|
type: string
|
|
supportingMessage:
|
|
type: string
|
|
nullable: true
|
|
governanceAttentionPresent:
|
|
type: boolean
|
|
overdueFindingsPresent:
|
|
type: boolean
|
|
nextActionLabel:
|
|
type: string
|
|
nullable: true |