229 lines
13 KiB
YAML
229 lines
13 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: Investigation Queue & Scenario Analytics API
|
|
version: 0.3.0
|
|
description: Analyst-opened agentic investigation cases over deterministic scenario health, trends and recurring failures.
|
|
paths:
|
|
/api/internal/investigation-signals:
|
|
post:
|
|
operationId: investigations.ingestSignal
|
|
summary: Idempotently ingest a deterministic producer signal into the Investigation Queue
|
|
description: Internal producer route. Ingestion creates/updates Queue/Episode only and never starts an agent chat or AgentRun.
|
|
security: [{ serviceAndUser: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/InvestigationSignal" }
|
|
responses:
|
|
"202": { description: Signal accepted; Queue item created or updated deterministically, content: { application/json: { schema: { $ref: "#/components/schemas/InvestigationQueueItem" } } } }
|
|
"409": { description: Signal identity was reused with non-canonical content }
|
|
/api/investigation-queue:
|
|
get:
|
|
operationId: investigations.listQueue
|
|
summary: List deduplicated attention items; listing never starts an agent run
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- { name: state, in: query, schema: { type: string, enum: [new, acknowledged, case_opened, suppressed, resolved] } }
|
|
- { name: scenario_id, in: query, schema: { type: string } }
|
|
- { name: severity, in: query, schema: { type: string, enum: [info, warning, critical] } }
|
|
responses:
|
|
"200":
|
|
description: InvestigationQueueItem[]
|
|
content: { application/json: { schema: { type: array, items: { $ref: "#/components/schemas/InvestigationQueueItem" } } } }
|
|
/api/investigation-queue/{queue_item_id}/open-case:
|
|
post:
|
|
operationId: investigations.openCase
|
|
summary: Explicitly open a persistent InvestigationCase and its agent thread
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: queue_item_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses:
|
|
"201":
|
|
description: Case opened
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/InvestigationCase" } } }
|
|
"200":
|
|
description: Existing case for the active queue item
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/InvestigationCase" } } }
|
|
"403": { description: Requires source-object and evidence access }
|
|
"409": { description: Queue item is suppressed/resolved or has incompatible case state }
|
|
/api/investigation-cases/{case_id}:
|
|
get:
|
|
operationId: investigations.getCase
|
|
summary: Get persistent case, evidence, compact triage and action timeline
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: case_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses:
|
|
"200": { description: InvestigationCase, content: { application/json: { schema: { $ref: "#/components/schemas/InvestigationCase" } } } }
|
|
"403": { description: Requires source-object and evidence access }
|
|
"404": { description: Not found }
|
|
/api/investigation-cases/{case_id}/disposition:
|
|
post:
|
|
operationId: investigations.setDisposition
|
|
summary: Record an analyst-confirmed case disposition and update compact triage projection
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: case_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/CaseDispositionRequest" }
|
|
responses:
|
|
"200": { description: Updated case and audited TriageRecord projection, content: { application/json: { schema: { $ref: "#/components/schemas/InvestigationCase" } } } }
|
|
"403": { description: Requires scenario-result:triage and object access }
|
|
"409": { description: Stale decision_version or terminal-case conflict }
|
|
"422": { description: Invalid state/disposition combination }
|
|
/api/scenarios/{scenario_id}/health:
|
|
get:
|
|
operationId: analytics.health
|
|
summary: Contextual deterministic health feeding 042 badge
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- { name: scenario_id, in: path, required: true, schema: { type: string } }
|
|
- { name: environment_class, in: query, schema: { type: string } }
|
|
- { name: context_key, in: query, schema: { type: string } }
|
|
responses:
|
|
"200": { description: ScenarioHealth, content: { application/json: { schema: { $ref: "#/components/schemas/ScenarioHealth" } } } }
|
|
/api/scenarios/{scenario_id}/trends:
|
|
get:
|
|
operationId: analytics.trends
|
|
summary: Deterministic success and classified/disposition trend series
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: scenario_id, in: path, required: true, schema: { type: string } }]
|
|
responses:
|
|
"200": { description: Trends, content: { application/json: { schema: { $ref: "#/components/schemas/Trends" } } } }
|
|
/api/scenarios/{scenario_id}/recurring-failures:
|
|
get:
|
|
operationId: analytics.recurring
|
|
summary: Compatibility-scoped recurring groups and episodes
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: scenario_id, in: path, required: true, schema: { type: string } }]
|
|
responses:
|
|
"200": { description: "RecurringFailureGroup[]", content: { application/json: { schema: { type: array, items: { $ref: "#/components/schemas/RecurringFailureGroup" } } } } }
|
|
components:
|
|
securitySchemes:
|
|
bearerAuth: { type: http, scheme: bearer }
|
|
serviceAndUser: { type: http, scheme: bearer, description: "Trusted producer service with originating user/provenance context" }
|
|
schemas:
|
|
InvestigationQueueItem:
|
|
type: object
|
|
required: [id, source_type, severity, state, count, first_seen_at, last_seen_at]
|
|
properties:
|
|
id: { type: string, format: uuid }
|
|
source_type: { type: string, enum: [scenario_run, staleness_signal, baseline_immutability, load_finding, automation_failure] }
|
|
scenario_id: { type: [string, 'null'] }
|
|
run_id: { type: [string, 'null'], format: uuid }
|
|
logical_step_id: { type: [string, 'null'], format: uuid }
|
|
severity: { type: string, enum: [info, warning, critical] }
|
|
fingerprint: { type: [string, 'null'] }
|
|
active_episode_id: { type: [string, 'null'], format: uuid }
|
|
evidence_summary: { type: object, additionalProperties: true }
|
|
target_snapshot: { type: object, additionalProperties: true }
|
|
suggested_next_action: { type: [string, 'null'] }
|
|
state: { type: string, enum: [new, acknowledged, case_opened, suppressed, resolved] }
|
|
count: { type: integer, minimum: 1 }
|
|
first_seen_at: { type: string, format: date-time }
|
|
last_seen_at: { type: string, format: date-time }
|
|
case_id: { type: [string, 'null'], format: uuid }
|
|
InvestigationSignal:
|
|
type: object
|
|
required: [source_type, source_id, severity, evidence_refs, occurred_at]
|
|
properties:
|
|
source_type: { type: string, enum: [scenario_run, staleness_signal, baseline_immutability, load_finding, automation_failure] }
|
|
source_id: { type: string }
|
|
scenario_id: { type: [string, 'null'] }
|
|
run_id: { type: [string, 'null'], format: uuid }
|
|
logical_step_id: { type: [string, 'null'], format: uuid }
|
|
severity: { type: string, enum: [info, warning, critical] }
|
|
canonical_fingerprint: { type: [string, 'null'] }
|
|
evidence_refs: { type: array, items: { type: string, format: uuid } }
|
|
target_snapshot: { type: [object, 'null'], additionalProperties: true }
|
|
execution_principal_fingerprint: { type: [string, 'null'] }
|
|
occurred_at: { type: string, format: date-time }
|
|
InvestigationCase:
|
|
type: object
|
|
required: [id, queue_item_id, status, source_snapshot, evidence_snapshot, owner_actor_id, agent_thread_id, opened_at]
|
|
properties:
|
|
id: { type: string, format: uuid }
|
|
queue_item_id: { type: string, format: uuid }
|
|
status: { type: string, enum: [open, investigating, awaiting_approval, awaiting_external_change, verifying, resolved, accepted, reopened] }
|
|
source_snapshot: { type: object, additionalProperties: true }
|
|
evidence_snapshot: { type: object, additionalProperties: true }
|
|
owner_actor_id: { type: string }
|
|
agent_thread_id: { type: string }
|
|
opened_at: { type: string, format: date-time }
|
|
resolved_at: { type: [string, 'null'], format: date-time }
|
|
final_disposition: { type: [string, 'null'], enum: [fixed, accepted_risk, duplicate, wont_fix, false_positive] }
|
|
resolution_summary: { type: [string, 'null'] }
|
|
triage: { $ref: "#/components/schemas/TriageRecord" }
|
|
actions: { type: array, items: { $ref: "#/components/schemas/AgentAction" } }
|
|
CaseDispositionRequest:
|
|
type: object
|
|
required: [decision_version, investigation_status]
|
|
properties:
|
|
decision_version: { type: integer, minimum: 1 }
|
|
investigation_status: { type: string, enum: [new, investigating, resolved] }
|
|
classification: { type: string, enum: [product_regression, data_regression, baseline_stale, scenario_bug, infrastructure_failure, not_confirmed] }
|
|
resolution: { type: string, enum: [fixed, accepted_risk, duplicate, wont_fix, false_positive] }
|
|
comment: { type: string, maxLength: 4000 }
|
|
verification_evidence_refs: { type: array, items: { type: string, format: uuid }, description: "Required to transition a case to resolved" }
|
|
acceptance_rationale: { type: string, maxLength: 4000, description: "Required for accepted-risk/wont-fix terminal acceptance" }
|
|
TriageRecord:
|
|
type: object
|
|
properties:
|
|
investigation_status: { type: string }
|
|
classification: { type: [string, 'null'] }
|
|
resolution: { type: [string, 'null'] }
|
|
comment: { type: [string, 'null'] }
|
|
decision_version: { type: integer }
|
|
actor_id: { type: string }
|
|
AgentAction:
|
|
type: object
|
|
required: [id, intent, risk_class, policy_decision, status]
|
|
properties:
|
|
id: { type: string, format: uuid }
|
|
intent: { type: string }
|
|
risk_class: { type: string, enum: [read, diagnostic_run, controlled_test_data_mutation, draft_write, scenario_revision_write, activate_current_revision, baseline_approval, automation_policy_write, prod_mutation] }
|
|
policy_decision: { type: string, enum: [delegated, approval_required, denied] }
|
|
status: { type: string, enum: [planned, running, completed, failed, awaiting_reconciliation] }
|
|
evidence_refs: { type: array, items: { type: string, format: uuid } }
|
|
approval_gate_id: { type: [string, 'null'], format: uuid }
|
|
ScenarioHealth:
|
|
type: object
|
|
required: [scenario_id, overall_attention, generated_at, confidence]
|
|
properties:
|
|
scenario_id: { type: string }
|
|
environment_class: { type: string }
|
|
context_key: { type: string, description: "044 AnalyticsContextKey" }
|
|
product_health: { type: string, enum: [healthy, attention, unknown] }
|
|
scenario_test_health: { type: string, enum: [healthy, attention, unknown] }
|
|
infrastructure_health: { type: string, enum: [healthy, attention, unknown] }
|
|
agent_evaluation_health: { type: string, enum: [healthy, attention, unknown] }
|
|
overall_attention: { type: string, enum: [healthy, attention, unknown] }
|
|
success_rate: { type: number }
|
|
flaky_ratio: { type: number }
|
|
infra_failure_ratio: { type: number }
|
|
inconclusive_ratio: { type: number }
|
|
agent_disagreement_ratio: { type: number }
|
|
low_confidence_ratio: { type: number }
|
|
model_instability_ratio: { type: number }
|
|
generated_at: { type: string, format: date-time }
|
|
confidence: { type: string, enum: [insufficient_history, low, high] }
|
|
Trends:
|
|
type: object
|
|
required: [generated_at, success_rate_series, disposition_distribution]
|
|
properties:
|
|
generated_at: { type: string, format: date-time }
|
|
success_rate_series: { type: array, items: { type: object } }
|
|
disposition_distribution: { type: object, additionalProperties: { type: integer } }
|
|
RecurringFailureGroup:
|
|
type: object
|
|
required: [id, fingerprint, compatibility_family, count, first_occurred_at, last_occurred_at, episodes]
|
|
properties:
|
|
id: { type: string, format: uuid }
|
|
fingerprint: { type: string, description: "logical_step_id + error_code + normalized_error_signature + assertion_kind + affected_ref" }
|
|
compatibility_family: { type: string }
|
|
count: { type: integer }
|
|
first_occurred_at: { type: string, format: date-time }
|
|
last_occurred_at: { type: string, format: date-time }
|
|
episodes: { type: array, items: { type: object, properties: { id: { type: string, format: uuid }, opened_at: { type: string, format: date-time }, resolved_at: { type: [string, 'null'], format: date-time } } } }
|