Some checks failed
Main Confidence / confidence (push) Failing after 53s
## Summary This PR delivers three related improvements: ### 1. Finding Ownership Semantics (Spec 219) - Add responsibility/accountability labels to findings and finding exceptions - `owner_user_id` = accountable party (governance owner) - `assignee_user_id` = responsible party (technical implementer) - Expose Assign/Reassign actions in FindingResource with audit logging - Add ownership columns and filters to finding list - Propagate owner from finding to exception on creation - Tests: ownership semantics, assignment audit, workflow actions ### 2. Constitution v2.7.0 — LEAN-001 Pre-Production Lean Doctrine - New principle forbidding legacy aliases, migration shims, dual-write logic, and compatibility fixtures in a pre-production codebase - AI-agent 4-question verification gate before adding any compatibility path - Review rule: compatibility shims without answering the gate questions = merge blocker - Exit condition: LEAN-001 expires at first production deployment - Spec template: added default "Compatibility posture" block - Agent instructions: added "Pre-production compatibility check" section ### 3. Backup Set Operation Type Unification - Unified `backup_set.add_policies` and `backup_set.remove_policies` into single canonical `backup_set.update` - Removed all legacy aliases, constants, and test fixtures - Added lifecycle coverage for `backup_set.update` in config - Updated all 14+ test files referencing legacy types ### Spec Artifacts - `specs/219-finding-ownership-semantics/` — full spec, plan, tasks, research, data model, contracts, checklist ### Tests - All affected tests pass (OperationCatalog, backup set, finding workflow, ownership semantics) Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #256
248 lines
7.4 KiB
YAML
248 lines
7.4 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: TenantPilot Internal Finding Responsibility Contract
|
|
version: 1.0.0
|
|
description: |
|
|
Internal review contract for Spec 219.
|
|
|
|
These are operator-facing Filament surfaces, not public API endpoints. The document exists so
|
|
the feature has an explicit, reviewable contract under specs/.../contracts/.
|
|
|
|
paths:
|
|
/admin/t/{tenant}/findings:
|
|
get:
|
|
summary: Tenant findings list with explicit responsibility semantics
|
|
parameters:
|
|
- $ref: '#/components/parameters/TenantPathParam'
|
|
responses:
|
|
'200':
|
|
description: Findings list rendered
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/FindingListSurface'
|
|
/admin/t/{tenant}/findings/{finding}:
|
|
get:
|
|
summary: Finding detail with owner, assignee, and optional exception-owner context
|
|
parameters:
|
|
- $ref: '#/components/parameters/TenantPathParam'
|
|
- $ref: '#/components/parameters/FindingPathParam'
|
|
responses:
|
|
'200':
|
|
description: Finding detail rendered
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/FindingDetailSurface'
|
|
/admin/t/{tenant}/findings/{finding}/responsibility:
|
|
post:
|
|
summary: Update finding owner and assignee semantics
|
|
description: Conceptual responsibility-update contract implemented by Filament action endpoints.
|
|
parameters:
|
|
- $ref: '#/components/parameters/TenantPathParam'
|
|
- $ref: '#/components/parameters/FindingPathParam'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponsibilityUpdateRequest'
|
|
responses:
|
|
'200':
|
|
description: Responsibility updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponsibilityUpdateResult'
|
|
'403':
|
|
description: Actor is an in-scope tenant member but lacks assignment capability
|
|
'404':
|
|
description: Tenant or finding is outside the actor scope
|
|
/admin/t/{tenant}/findings/{finding}/exception-request:
|
|
post:
|
|
summary: Request exception with explicitly separate exception owner
|
|
description: Conceptual exception-request contract implemented by Filament action endpoints.
|
|
parameters:
|
|
- $ref: '#/components/parameters/TenantPathParam'
|
|
- $ref: '#/components/parameters/FindingPathParam'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ExceptionRequestInput'
|
|
responses:
|
|
'200':
|
|
description: Exception request accepted
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ExceptionOwnershipBoundaryResult'
|
|
|
|
components:
|
|
parameters:
|
|
TenantPathParam:
|
|
name: tenant
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Tenant route identifier for tenant-scoped findings surfaces.
|
|
FindingPathParam:
|
|
name: finding
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Tenant-owned finding identifier.
|
|
|
|
schemas:
|
|
UserReference:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- id
|
|
- display_name
|
|
properties:
|
|
id:
|
|
type: integer
|
|
display_name:
|
|
type: string
|
|
|
|
ResponsibilityState:
|
|
type: string
|
|
description: Uses internal slugs for API and test contracts. The operator-facing UI label for `orphaned_accountability` is `orphaned accountability`.
|
|
enum:
|
|
- orphaned_accountability
|
|
- owned_unassigned
|
|
- assigned
|
|
|
|
FindingResponsibilitySummary:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- finding_id
|
|
- workflow_status
|
|
- responsibility_state
|
|
properties:
|
|
finding_id:
|
|
type: integer
|
|
workflow_status:
|
|
type: string
|
|
owner:
|
|
allOf:
|
|
- $ref: '#/components/schemas/UserReference'
|
|
nullable: true
|
|
assignee:
|
|
allOf:
|
|
- $ref: '#/components/schemas/UserReference'
|
|
nullable: true
|
|
responsibility_state:
|
|
$ref: '#/components/schemas/ResponsibilityState'
|
|
accountability_gap:
|
|
type: boolean
|
|
exception_owner:
|
|
allOf:
|
|
- $ref: '#/components/schemas/UserReference'
|
|
nullable: true
|
|
description: Present only when a finding exception exists or is shown in current context.
|
|
|
|
FindingListSurface:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- surface
|
|
- collection_route
|
|
- primary_inspect_model
|
|
- items
|
|
properties:
|
|
surface:
|
|
const: tenant_findings_list
|
|
collection_route:
|
|
const: /admin/t/{tenant}/findings
|
|
primary_inspect_model:
|
|
const: finding
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/FindingResponsibilitySummary'
|
|
|
|
FindingDetailSurface:
|
|
allOf:
|
|
- $ref: '#/components/schemas/FindingResponsibilitySummary'
|
|
- type: object
|
|
additionalProperties: false
|
|
required:
|
|
- surface
|
|
- detail_route
|
|
properties:
|
|
surface:
|
|
const: finding_detail
|
|
detail_route:
|
|
const: /admin/t/{tenant}/findings/{finding}
|
|
|
|
ResponsibilityUpdateRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
properties:
|
|
owner_user_id:
|
|
type: integer
|
|
nullable: true
|
|
description: Accountable owner for the finding outcome.
|
|
assignee_user_id:
|
|
type: integer
|
|
nullable: true
|
|
description: Active remediation assignee for the finding.
|
|
|
|
ResponsibilityUpdateResult:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- change_classification
|
|
- responsibility
|
|
properties:
|
|
change_classification:
|
|
type: string
|
|
description: Uses explicit slugs for single-role clears and `owner_and_assignee` whenever both fields change in one update, including mixed set/clear combinations.
|
|
enum:
|
|
- owner_only
|
|
- assignee_only
|
|
- owner_and_assignee
|
|
- clear_owner
|
|
- clear_assignee
|
|
responsibility:
|
|
$ref: '#/components/schemas/FindingResponsibilitySummary'
|
|
|
|
ExceptionRequestInput:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- owner_user_id
|
|
- request_reason
|
|
- review_due_at
|
|
properties:
|
|
owner_user_id:
|
|
type: integer
|
|
description: Owner of the exception artifact, not the finding owner.
|
|
request_reason:
|
|
type: string
|
|
review_due_at:
|
|
type: string
|
|
format: date-time
|
|
expires_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
|
|
ExceptionOwnershipBoundaryResult:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- finding_owner_preserved
|
|
- exception_owner
|
|
properties:
|
|
finding_owner_preserved:
|
|
type: boolean
|
|
const: true
|
|
exception_owner:
|
|
$ref: '#/components/schemas/UserReference' |