TenantAtlas/specs/231-finding-outcome-taxonomy/contracts/finding-outcome-taxonomy.logical.openapi.yaml
Ahmed Darrazi 807578dd9c
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 4m16s
feat: implement finding outcome taxonomy
2026-04-23 09:24:59 +02:00

397 lines
10 KiB
YAML

openapi: 3.1.0
info:
title: Finding Outcome Taxonomy Logical Contract
version: 0.1.0
description: |
Logical contract for the findings outcome taxonomy feature. This is not a new
public HTTP API commitment. It documents the request and response shapes that
existing Filament and service workflows must converge on.
servers:
- url: https://tenantpilot.local
description: Logical base URL only
tags:
- name: Findings
- name: FindingsInternal
paths:
/tenants/{tenantId}/findings:
get:
tags: [Findings]
summary: List tenant findings with terminal-outcome filters
operationId: listTenantFindings
parameters:
- $ref: '#/components/parameters/TenantId'
- name: status
in: query
schema:
$ref: '#/components/schemas/FindingStatus'
- name: terminal_outcome
in: query
schema:
$ref: '#/components/schemas/TerminalOutcomeKey'
- name: verification_state
in: query
schema:
$ref: '#/components/schemas/VerificationState'
responses:
'200':
description: Tenant findings list
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: array
items:
$ref: '#/components/schemas/FindingSummary'
/tenants/{tenantId}/findings/{findingId}:
get:
tags: [Findings]
summary: Get one finding with current terminal-outcome semantics
operationId: getTenantFinding
parameters:
- $ref: '#/components/parameters/TenantId'
- $ref: '#/components/parameters/FindingId'
responses:
'200':
description: Finding detail
content:
application/json:
schema:
$ref: '#/components/schemas/FindingDetail'
/tenants/{tenantId}/findings/{findingId}/resolve:
post:
tags: [Findings]
summary: Resolve a finding with a bounded operator reason
operationId: resolveTenantFinding
parameters:
- $ref: '#/components/parameters/TenantId'
- $ref: '#/components/parameters/FindingId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ResolveFindingRequest'
responses:
'200':
description: Finding resolved pending verification
content:
application/json:
schema:
$ref: '#/components/schemas/FindingDetail'
/tenants/{tenantId}/findings/{findingId}/close:
post:
tags: [Findings]
summary: Close a finding with a bounded administrative reason
operationId: closeTenantFinding
parameters:
- $ref: '#/components/parameters/TenantId'
- $ref: '#/components/parameters/FindingId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CloseFindingRequest'
responses:
'200':
description: Finding closed with a non-remediation outcome
content:
application/json:
schema:
$ref: '#/components/schemas/FindingDetail'
/tenants/{tenantId}/findings/{findingId}/reopen:
post:
tags: [Findings]
summary: Reopen a terminal finding with a bounded reopen reason
operationId: reopenTenantFinding
parameters:
- $ref: '#/components/parameters/TenantId'
- $ref: '#/components/parameters/FindingId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ReopenFindingRequest'
responses:
'200':
description: Finding reopened
content:
application/json:
schema:
$ref: '#/components/schemas/FindingDetail'
/internal/tenants/{tenantId}/findings/{findingId}/system-clear:
post:
tags: [FindingsInternal]
summary: Apply a trusted system-clear reason
operationId: systemClearFinding
x-internal: true
parameters:
- $ref: '#/components/parameters/TenantId'
- $ref: '#/components/parameters/FindingId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SystemClearFindingRequest'
responses:
'200':
description: Finding moved into a verified-cleared outcome
content:
application/json:
schema:
$ref: '#/components/schemas/FindingDetail'
/internal/tenants/{tenantId}/findings/{findingId}/system-reopen:
post:
tags: [FindingsInternal]
summary: Reopen a terminal finding due to trusted recurrence or verification failure
operationId: systemReopenFinding
x-internal: true
parameters:
- $ref: '#/components/parameters/TenantId'
- $ref: '#/components/parameters/FindingId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SystemReopenFindingRequest'
responses:
'200':
description: Finding reopened by trusted automation
content:
application/json:
schema:
$ref: '#/components/schemas/FindingDetail'
components:
parameters:
TenantId:
name: tenantId
in: path
required: true
schema:
type: integer
FindingId:
name: findingId
in: path
required: true
schema:
type: integer
schemas:
FindingStatus:
type: string
enum:
- new
- acknowledged
- triaged
- in_progress
- reopened
- resolved
- closed
- risk_accepted
VerificationState:
type: string
enum:
- pending_verification
- verified_cleared
- not_applicable
ResolveReasonKey:
type: string
enum:
- remediated
- no_longer_drifting
- permission_granted
- permission_removed_from_registry
- role_assignment_removed
- ga_count_within_threshold
CloseReasonKey:
type: string
enum:
- false_positive
- duplicate
- no_longer_applicable
- accepted_risk
ReopenReasonKey:
type: string
enum:
- recurred_after_resolution
- verification_failed
- manual_reassessment
TerminalOutcomeKey:
type: string
enum:
- resolved_pending_verification
- verified_cleared
- closed_false_positive
- closed_duplicate
- closed_no_longer_applicable
- risk_accepted
TerminalOutcome:
type: object
required:
- key
- label
- verification_state
- report_bucket
properties:
key:
$ref: '#/components/schemas/TerminalOutcomeKey'
label:
type: string
verification_state:
$ref: '#/components/schemas/VerificationState'
report_bucket:
type: string
enum:
- remediation_pending_verification
- remediation_verified
- administrative_closure
- accepted_risk
governance_state:
type: string
nullable: true
description: Present only when the outcome depends on risk-governance validity.
ResolveFindingRequest:
type: object
required: [reason]
properties:
reason:
type: string
enum: [remediated]
note:
type: string
maxLength: 255
nullable: true
CloseFindingRequest:
type: object
required: [reason]
properties:
reason:
type: string
enum:
- false_positive
- duplicate
- no_longer_applicable
note:
type: string
maxLength: 255
nullable: true
ReopenFindingRequest:
type: object
required: [reason]
properties:
reason:
$ref: '#/components/schemas/ReopenReasonKey'
note:
type: string
maxLength: 255
nullable: true
SystemClearFindingRequest:
type: object
required: [reason, observed_at]
properties:
reason:
type: string
enum:
- no_longer_drifting
- permission_granted
- permission_removed_from_registry
- role_assignment_removed
- ga_count_within_threshold
observed_at:
type: string
format: date-time
operation_run_id:
type: integer
nullable: true
SystemReopenFindingRequest:
type: object
required: [reason, observed_at]
properties:
reason:
type: string
enum:
- recurred_after_resolution
- verification_failed
observed_at:
type: string
format: date-time
operation_run_id:
type: integer
nullable: true
FindingSummary:
type: object
required:
- id
- tenant_id
- status
- severity
- terminal_outcome
properties:
id:
type: integer
tenant_id:
type: integer
status:
$ref: '#/components/schemas/FindingStatus'
severity:
type: string
resolved_reason:
oneOf:
- $ref: '#/components/schemas/ResolveReasonKey'
- type: 'null'
closed_reason:
oneOf:
- $ref: '#/components/schemas/CloseReasonKey'
- type: 'null'
terminal_outcome:
$ref: '#/components/schemas/TerminalOutcome'
FindingDetail:
allOf:
- $ref: '#/components/schemas/FindingSummary'
- type: object
properties:
resolved_at:
type: string
format: date-time
nullable: true
closed_at:
type: string
format: date-time
nullable: true
reopened_at:
type: string
format: date-time
nullable: true
audit_context:
type: object
additionalProperties: true
description: Logical placeholder for the readable audit/history payload.