Some checks failed
Main Confidence / confidence (push) Failing after 1m20s
## Summary - add the workspace-scoped findings hygiene report, overview signal, and supporting classification service for broken assignments and stale in-progress work - add Spec 225 artifacts and focused findings hygiene test coverage alongside the new Filament page and workspace overview wiring - align product roadmap and spec candidates around the layered canonical control catalog, CIS library, and readiness model - extend SpecKit constitution and templates with the XCUT-001 shared-pattern reuse guidance ## Notes - validation commands and implementation close-out notes are documented in `specs/225-assignment-hygiene/plan.md` and `specs/225-assignment-hygiene/quickstart.md` - this PR targets `dev` from `225-assignment-hygiene` Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #264
276 lines
8.0 KiB
YAML
276 lines
8.0 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: Assignment Hygiene Surface Contract
|
|
version: 1.0.0
|
|
summary: Logical internal contract for Spec 225 report rendering, overview discoverability, and finding drilldown.
|
|
description: |
|
|
This contract documents the structured payloads and UI-facing surfaces that Spec 225 must satisfy.
|
|
It is intentionally logical rather than public-API only: the feature reuses existing Filament pages,
|
|
workspace overview builders, and finding detail routes instead of introducing a new public controller namespace.
|
|
servers:
|
|
- url: https://logical.internal
|
|
description: Non-routable placeholder used to describe internal repository contracts.
|
|
paths:
|
|
/internal/findings/hygiene-issues:
|
|
get:
|
|
summary: Evaluate derived findings hygiene issues for the current visible workspace scope.
|
|
description: |
|
|
Logical internal contract implemented by the narrow findings hygiene service.
|
|
It derives `broken_assignment` and `stale_in_progress` from current finding, audit,
|
|
tenant-entitlement, and user lifecycle truth without persisting a second workflow state.
|
|
operationId: listFindingHygieneIssues
|
|
x-not-public-http: true
|
|
parameters:
|
|
- name: workspaceId
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
- name: tenantId
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type:
|
|
- integer
|
|
- 'null'
|
|
- name: reason
|
|
in: query
|
|
required: false
|
|
schema:
|
|
$ref: '#/components/schemas/HygieneReasonFilter'
|
|
responses:
|
|
'200':
|
|
description: Derived findings hygiene issues and visible-scope summary counts.
|
|
content:
|
|
application/vnd.tenantpilot.findings-hygiene-report+json:
|
|
schema:
|
|
$ref: '#/components/schemas/FindingsHygieneReportSurface'
|
|
/admin/findings/hygiene:
|
|
get:
|
|
summary: Canonical workspace-context findings hygiene report.
|
|
operationId: viewFindingsHygieneReport
|
|
parameters:
|
|
- name: tenant
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
- name: reason
|
|
in: query
|
|
required: false
|
|
schema:
|
|
$ref: '#/components/schemas/HygieneReasonFilter'
|
|
responses:
|
|
'200':
|
|
description: Existing Filament page renders the read-first findings hygiene report.
|
|
content:
|
|
text/html:
|
|
schema:
|
|
type: string
|
|
application/vnd.tenantpilot.findings-hygiene-report+json:
|
|
schema:
|
|
$ref: '#/components/schemas/FindingsHygieneReportSurface'
|
|
'404':
|
|
description: Non-member or out-of-scope workspace remains deny-as-not-found; hidden tenants inside an entitled workspace are suppressed from rows, counts, filters, and hints rather than causing a route-level `404`.
|
|
/admin:
|
|
get:
|
|
summary: Workspace overview includes one findings hygiene signal.
|
|
operationId: viewWorkspaceOverviewWithFindingsHygieneSignal
|
|
responses:
|
|
'200':
|
|
description: Existing workspace overview renders the hygiene summary signal in attention or calm state for the current visible scope.
|
|
content:
|
|
text/html:
|
|
schema:
|
|
type: string
|
|
application/vnd.tenantpilot.findings-hygiene-overview-signal+json:
|
|
schema:
|
|
$ref: '#/components/schemas/FindingsHygieneOverviewSignal'
|
|
/admin/t/{tenant}/findings/{finding}:
|
|
get:
|
|
summary: Report drilldown opens the existing tenant finding detail route.
|
|
operationId: openFindingFromHygieneReport
|
|
parameters:
|
|
- name: tenant
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
- name: finding
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Existing finding detail renders for an entitled tenant operator.
|
|
content:
|
|
text/html:
|
|
schema:
|
|
type: string
|
|
'403':
|
|
description: In-scope member lacks the current capability to inspect the finding.
|
|
'404':
|
|
description: Recipient no longer has tenant or record visibility.
|
|
components:
|
|
schemas:
|
|
HygieneReason:
|
|
type: string
|
|
enum:
|
|
- broken_assignment
|
|
- stale_in_progress
|
|
HygieneReasonFilter:
|
|
type: string
|
|
enum:
|
|
- all
|
|
- broken_assignment
|
|
- stale_in_progress
|
|
FindingsHygieneIssue:
|
|
type: object
|
|
required:
|
|
- findingId
|
|
- tenantId
|
|
- tenantName
|
|
- findingSummary
|
|
- status
|
|
- lastWorkflowActivityAt
|
|
- reasons
|
|
- detailUrl
|
|
properties:
|
|
findingId:
|
|
type: integer
|
|
workspaceId:
|
|
type: integer
|
|
tenantId:
|
|
type: integer
|
|
tenantName:
|
|
type: string
|
|
findingSummary:
|
|
type: string
|
|
status:
|
|
type: string
|
|
ownerUserId:
|
|
type:
|
|
- integer
|
|
- 'null'
|
|
ownerName:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
assigneeUserId:
|
|
type:
|
|
- integer
|
|
- 'null'
|
|
assigneeName:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
dueAt:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
format: date-time
|
|
overdue:
|
|
type: boolean
|
|
lastWorkflowActivityAt:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
format: date-time
|
|
reasons:
|
|
type: array
|
|
minItems: 1
|
|
items:
|
|
$ref: '#/components/schemas/HygieneReason'
|
|
detailUrl:
|
|
type: string
|
|
FindingsHygieneSummary:
|
|
type: object
|
|
required:
|
|
- uniqueIssueCount
|
|
- brokenAssignmentCount
|
|
- staleInProgressCount
|
|
- isCalm
|
|
properties:
|
|
uniqueIssueCount:
|
|
type: integer
|
|
minimum: 0
|
|
brokenAssignmentCount:
|
|
type: integer
|
|
minimum: 0
|
|
staleInProgressCount:
|
|
type: integer
|
|
minimum: 0
|
|
isCalm:
|
|
type: boolean
|
|
FindingsHygieneReportSurface:
|
|
type: object
|
|
required:
|
|
- appliedReasonFilter
|
|
- appliedTenantFilter
|
|
- issues
|
|
- summary
|
|
properties:
|
|
appliedReasonFilter:
|
|
$ref: '#/components/schemas/HygieneReasonFilter'
|
|
appliedTenantFilter:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
issues:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/FindingsHygieneIssue'
|
|
summary:
|
|
$ref: '#/components/schemas/FindingsHygieneSummary'
|
|
emptyState:
|
|
type:
|
|
- object
|
|
- 'null'
|
|
properties:
|
|
title:
|
|
type: string
|
|
description:
|
|
type: string
|
|
ctaLabel:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
ctaUrl:
|
|
type:
|
|
- string
|
|
- 'null'
|
|
FindingsHygieneOverviewSignal:
|
|
type: object
|
|
required:
|
|
- headline
|
|
- description
|
|
- uniqueIssueCount
|
|
- brokenAssignmentCount
|
|
- staleInProgressCount
|
|
- isCalm
|
|
- ctaLabel
|
|
- ctaUrl
|
|
properties:
|
|
headline:
|
|
type: string
|
|
description:
|
|
type: string
|
|
description: Short operator-facing summary derived from broken-assignment and stale-in-progress counts.
|
|
uniqueIssueCount:
|
|
type: integer
|
|
minimum: 0
|
|
brokenAssignmentCount:
|
|
type: integer
|
|
minimum: 0
|
|
staleInProgressCount:
|
|
type: integer
|
|
minimum: 0
|
|
isCalm:
|
|
type: boolean
|
|
ctaLabel:
|
|
type: string
|
|
ctaUrl:
|
|
type: string |