The window rendered the same 13 collapsible sections for every entity, sorted
only by "does it have content". Audit trail carried the same visual weight as
Health, and the window answered "what data do we hold about X?" rather than
"what do I need to know, and what should I do?".
Measured against prod: host:hubris has 223 relations, 1,601 events, 2.7M metric
samples and 148 executions; an ingress route has three facts. Both got 13
identical headers. Expanding a host put ~540 interactive elements on screen.
- **A verdict header that never collapses.** Not just "down" but *why*:
"ping failing · 5 of 6 checks passing". That line did not previously exist
and could not have — checks rendered as configuration, never as results.
- **Sections composed per type.** A document has no checks, metrics or blast
radius; a signal or execution is a record, not a thing. Infrastructure gets
Status/Impact/Activity/Metrics/Reference, knowledge types lead with Content,
records get a minimal view. Unknown types fall back to infrastructure so a
new entity type is never a blank window.
- **Status replaces Monitoring**, showing each check's own verdict and when it
last ran — the section that answers the header's "why".
- **Impact** finally calls /entities/{id}/blast-radius. The endpoint has existed
since the first API and had no frontend caller anywhere, despite
.agents/OIKOS.md naming blast radius as the reason the ontology exists. Its
outgoing-edges-only limitation is stated in the UI rather than hidden.
- **Activity merges four lists** (executions, signals, events, agent activity)
that were telling one story in four places.
- **Relations cap at 8 with a drill-in** — 540 interactive elements down to 126.
- **Ask Nomos** opens a task pre-scoped to what you are looking at, seeded with
the verdict just computed, via an optional draft threaded through
openNewTaskWindow -> NewTaskChat -> ChatThread.
Requires exposing check_defs.last_health/last_run_at through the API (the
columns landed with the health-aggregation work but were never surfaced).
Adding a fourth enum containing "unknown" made oapi-codegen disambiguate all
enum constants by type prefix, so metrics.go moves to gen.TrendDirection*.
Verdict derivation and type->section composition live in $lib/entityView.ts as
pure functions with 15 unit tests, including the host:strong case that
motivated this.
Co-Authored-By: Claude <noreply@anthropic.com>
3321 lines
82 KiB
YAML
3321 lines
82 KiB
YAML
openapi: 3.0.3
|
|
info:
|
|
title: Oikos API
|
|
version: 1.0.0
|
|
contact:
|
|
name: dtoro
|
|
license:
|
|
name: Private
|
|
url: https://example.invalid/private
|
|
description: 'Control-plane API for the Oikos homelab OS. This file is the **source of
|
|
|
|
truth** (contract-first): Go server stubs are generated with oapi-codegen,
|
|
|
|
clients (homelab CLI, future UIs) from the same spec.
|
|
|
|
|
|
Conventions (plan R3-3):
|
|
|
|
- Errors are RFC 9457 `application/problem+json`.
|
|
|
|
- Lists use `{items, next_cursor}` with cursor pagination (default limit 50, max 200).
|
|
|
|
- Unsafe POSTs accept `Idempotency-Key` (24h replay window).
|
|
|
|
- Mutable resources carry `version`; GET returns `ETag`, PATCH requires `If-Match` (412 on mismatch).
|
|
|
|
- Timestamps are RFC 3339 UTC.
|
|
|
|
- Entities are addressable by UUID or slug (`host:hubris`).
|
|
|
|
|
|
The MCP interface (streamable HTTP, official Go SDK) is mounted at `/mcp`
|
|
|
|
on the same binary and is out of scope for this document; its tools wrap
|
|
|
|
the same service layer as these endpoints.
|
|
|
|
'
|
|
servers:
|
|
- url: /api/v1
|
|
tags:
|
|
- name: entities
|
|
description: Inventory graph — entities and relationships
|
|
- name: clients
|
|
description: Client enrollment, context distribution, secrets
|
|
- name: ontology
|
|
description: Entity types, relationship types, lifecycles
|
|
- name: signals
|
|
description: Signals and checks (observe)
|
|
- name: executions
|
|
description: Executions, classifications, approvals (decide/act)
|
|
- name: learning
|
|
description: Patterns and skills (learn)
|
|
- name: policy
|
|
description: Risk classes, approval rules, autonomy
|
|
- name: knowledge
|
|
description: Knowledge graph search
|
|
- name: observability
|
|
description: Metrics, trends, audit, events, health
|
|
- name: system
|
|
description: Export, health
|
|
security:
|
|
- bearerAuth: []
|
|
paths:
|
|
/entities:
|
|
get:
|
|
tags:
|
|
- entities
|
|
operationId: listEntities
|
|
summary: List entities
|
|
x-required-scope: viewer
|
|
parameters:
|
|
- name: type
|
|
in: query
|
|
schema:
|
|
type: string
|
|
description: Filter by entity type (includes descendants)
|
|
- name: state
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: domain
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: layer
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: q
|
|
in: query
|
|
schema:
|
|
type: string
|
|
description: Substring match on slug/name
|
|
- $ref: '#/components/parameters/Cursor'
|
|
- $ref: '#/components/parameters/Limit'
|
|
responses:
|
|
'200':
|
|
description: Entity list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Entity'
|
|
next_cursor:
|
|
type: string
|
|
nullable: true
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
post:
|
|
tags:
|
|
- entities
|
|
operationId: createEntity
|
|
summary: Create an entity
|
|
x-required-scope: operator
|
|
parameters:
|
|
- $ref: '#/components/parameters/IdempotencyKey'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EntityCreate'
|
|
responses:
|
|
'201':
|
|
description: Created
|
|
headers:
|
|
ETag:
|
|
$ref: '#/components/headers/ETag'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Entity'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/entities/{id}:
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntityId'
|
|
get:
|
|
tags:
|
|
- entities
|
|
operationId: getEntity
|
|
summary: Get entity by UUID or slug
|
|
x-required-scope: viewer
|
|
responses:
|
|
'200':
|
|
description: Entity detail
|
|
headers:
|
|
ETag:
|
|
$ref: '#/components/headers/ETag'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Entity'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
patch:
|
|
tags:
|
|
- entities
|
|
operationId: patchEntity
|
|
summary: Update attributes or transition lifecycle state
|
|
description: 'Lifecycle transitions are validated against the type''s lifecycle_def;
|
|
|
|
illegal transitions return 409 (invalid-transition). Policy-gated
|
|
|
|
actions may return 403 (approval-required).
|
|
|
|
'
|
|
x-required-scope: operator
|
|
parameters:
|
|
- $ref: '#/components/parameters/IfMatch'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EntityPatch'
|
|
responses:
|
|
'200':
|
|
description: Updated entity
|
|
headers:
|
|
ETag:
|
|
$ref: '#/components/headers/ETag'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Entity'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/entities/{id}/relations:
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntityId'
|
|
get:
|
|
tags:
|
|
- entities
|
|
operationId: getEntityRelations
|
|
summary: Direct relationships of an entity (both directions)
|
|
x-required-scope: viewer
|
|
parameters:
|
|
- name: rel_type
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: direction
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum:
|
|
- out
|
|
- in
|
|
- both
|
|
default: both
|
|
responses:
|
|
'200':
|
|
description: Relationships
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Relationship'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/relationships:
|
|
post:
|
|
tags:
|
|
- entities
|
|
operationId: createRelationship
|
|
summary: Create a relationship edge
|
|
description: Endpoint types validated against relationship_types (hierarchy-aware); cardinality
|
|
enforced.
|
|
x-required-scope: operator
|
|
parameters:
|
|
- $ref: '#/components/parameters/IdempotencyKey'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RelationshipCreate'
|
|
responses:
|
|
'201':
|
|
description: Created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Relationship'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
delete:
|
|
tags:
|
|
- entities
|
|
operationId: endRelationship
|
|
summary: End a relationship (sets valid_to; the edge is kept for history)
|
|
x-required-scope: operator
|
|
parameters:
|
|
- name: source
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- name: target
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- name: rel_type
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'204':
|
|
description: Relationship ended
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/graph:
|
|
get:
|
|
tags:
|
|
- entities
|
|
operationId: getGraph
|
|
summary: Subgraph for visualization (nodes + edges)
|
|
x-required-scope: viewer
|
|
parameters:
|
|
- name: root
|
|
in: query
|
|
schema:
|
|
type: string
|
|
description: Start entity (UUID or slug); omit for whole graph (capped)
|
|
- name: depth
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 2
|
|
maximum: 5
|
|
- name: rel_type
|
|
in: query
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: string
|
|
style: form
|
|
explode: true
|
|
- name: include
|
|
in: query
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: string
|
|
enum:
|
|
- status
|
|
style: form
|
|
explode: true
|
|
description: include=status joins entity_status and populates GraphView.health
|
|
responses:
|
|
'200':
|
|
description: Graph view
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/GraphView'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/entities/{id}/blast-radius:
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntityId'
|
|
get:
|
|
tags:
|
|
- entities
|
|
operationId: getBlastRadius
|
|
summary: Entities affected if this entity fails
|
|
x-required-scope: viewer
|
|
parameters:
|
|
- name: depth
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 3
|
|
maximum: 5
|
|
responses:
|
|
'200':
|
|
description: Affected entities with graph distance
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
type: object
|
|
required:
|
|
- entity
|
|
- depth
|
|
properties:
|
|
entity:
|
|
$ref: '#/components/schemas/Entity'
|
|
depth:
|
|
type: integer
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/clients/enroll:
|
|
post:
|
|
tags:
|
|
- clients
|
|
operationId: enrollClient
|
|
summary: Enroll a new client — issue age key, create Infisical identity
|
|
description: >
|
|
Validates mesh IP, generates an age keypair, creates an Infisical
|
|
machine identity, and transitions the entity to provisioning.
|
|
Caller must already have an entity in planned or provisioning state.
|
|
x-required-scope: agent
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EnrollRequest'
|
|
responses:
|
|
'200':
|
|
description: Enrollment response with keys and identity
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EnrollResponse'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/clients/{slug}/context:
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntitySlug'
|
|
get:
|
|
tags:
|
|
- clients
|
|
operationId: getClientContext
|
|
summary: Get agent context delta since a timestamp
|
|
description: >
|
|
Returns which agent files, tools, and SOPS config changed since the
|
|
given timestamp. Thin clients poll this instead of git pull.
|
|
x-required-scope: agent
|
|
parameters:
|
|
- name: since
|
|
in: query
|
|
schema:
|
|
type: string
|
|
format: date-time
|
|
description: Return only changes since this timestamp (RFC 3339)
|
|
responses:
|
|
'200':
|
|
description: Context delta
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ClientContext'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/clients/{slug}/secrets:
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntitySlug'
|
|
get:
|
|
tags:
|
|
- clients
|
|
operationId: getClientSecrets
|
|
summary: List secrets accessible to this client
|
|
description: Infisical-secured secrets scoped to the client's machine identity
|
|
x-required-scope: agent
|
|
responses:
|
|
'200':
|
|
description: Secret keys accessible to this client
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ClientSecrets'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/entities/provision:
|
|
post:
|
|
tags:
|
|
- entities
|
|
operationId: provisionEntity
|
|
summary: Provision a compute entity (LXC, VM, container) on a host
|
|
description: >
|
|
Creates the entity in planned state, validates constraints (VMID, IP,
|
|
capacity, template), classifies the action against policy, and
|
|
transitions to provisioning on operator approval.
|
|
x-required-scope: operator
|
|
parameters:
|
|
- $ref: '#/components/parameters/IdempotencyKey'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ProvisionRequest'
|
|
responses:
|
|
'201':
|
|
description: Entity created, provisioning queued
|
|
headers:
|
|
ETag:
|
|
$ref: '#/components/headers/ETag'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ProvisionResponse'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/entities/{slug}/provision/status:
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntitySlug'
|
|
get:
|
|
tags:
|
|
- entities
|
|
operationId: getProvisionStatus
|
|
summary: Poll provisioning progress for a compute entity
|
|
x-required-scope: viewer
|
|
responses:
|
|
'200':
|
|
description: Provisioning steps with status
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ProvisionStatus'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
|
|
/ontology:
|
|
get:
|
|
tags:
|
|
- ontology
|
|
operationId: getOntology
|
|
summary: Full ontology — entity types, relationship types, lifecycles
|
|
x-required-scope: viewer
|
|
responses:
|
|
'200':
|
|
description: Ontology
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- entity_types
|
|
- relationship_types
|
|
- lifecycles
|
|
properties:
|
|
entity_types:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/EntityType'
|
|
relationship_types:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/RelationshipType'
|
|
lifecycles:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/LifecycleDef'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/ontology/entity-types:
|
|
post:
|
|
tags:
|
|
- ontology
|
|
operationId: createEntityType
|
|
summary: Extend the ontology with a new entity type
|
|
description: Policy-gated as config_mutation (creates a meta-approval when required).
|
|
x-required-scope: operator
|
|
parameters:
|
|
- $ref: '#/components/parameters/IdempotencyKey'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EntityTypeCreate'
|
|
responses:
|
|
'201':
|
|
description: Created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EntityType'
|
|
'202':
|
|
$ref: '#/components/responses/PendingApproval'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/ontology/entity-types/{name}:
|
|
parameters:
|
|
- name: name
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
patch:
|
|
tags:
|
|
- ontology
|
|
operationId: patchEntityType
|
|
summary: Update or deprecate an entity type
|
|
description: Hard delete is not supported while instances exist — deprecate instead (plan D3).
|
|
x-required-scope: operator
|
|
parameters:
|
|
- $ref: '#/components/parameters/IfMatch'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EntityTypePatch'
|
|
responses:
|
|
'200':
|
|
description: Updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EntityType'
|
|
'202':
|
|
$ref: '#/components/responses/PendingApproval'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/signals:
|
|
get:
|
|
tags:
|
|
- signals
|
|
operationId: listSignals
|
|
summary: List signals
|
|
x-required-scope: viewer
|
|
parameters:
|
|
- name: state
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: severity
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum:
|
|
- info
|
|
- warning
|
|
- critical
|
|
- name: entity_id
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: kind
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- $ref: '#/components/parameters/Cursor'
|
|
- $ref: '#/components/parameters/Limit'
|
|
responses:
|
|
'200':
|
|
description: Signals
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Signal'
|
|
next_cursor:
|
|
type: string
|
|
nullable: true
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/signals/{id}/ack:
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntityId'
|
|
post:
|
|
tags:
|
|
- signals
|
|
operationId: ackSignal
|
|
summary: Acknowledge a signal
|
|
x-required-scope: operator
|
|
responses:
|
|
'200':
|
|
$ref: '#/components/responses/SignalUpdated'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/signals/{id}/resolve:
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntityId'
|
|
post:
|
|
tags:
|
|
- signals
|
|
operationId: resolveSignal
|
|
summary: Resolve a signal manually
|
|
x-required-scope: operator
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
note:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
$ref: '#/components/responses/SignalUpdated'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/signals/{id}/mute:
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntityId'
|
|
post:
|
|
tags:
|
|
- signals
|
|
operationId: muteSignal
|
|
summary: Mute a signal for a TTL
|
|
x-required-scope: operator
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- mute_until
|
|
properties:
|
|
mute_until:
|
|
type: string
|
|
format: date-time
|
|
note:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
$ref: '#/components/responses/SignalUpdated'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/checks:
|
|
get:
|
|
tags:
|
|
- signals
|
|
operationId: listChecks
|
|
summary: List check definitions
|
|
x-required-scope: viewer
|
|
parameters:
|
|
- name: kind
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: target
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: enabled
|
|
in: query
|
|
schema:
|
|
type: boolean
|
|
- $ref: '#/components/parameters/Cursor'
|
|
- $ref: '#/components/parameters/Limit'
|
|
responses:
|
|
'200':
|
|
description: Checks
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Check'
|
|
next_cursor:
|
|
type: string
|
|
nullable: true
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
post:
|
|
tags:
|
|
- signals
|
|
operationId: createCheck
|
|
summary: Create a check (checks-as-data, plan R3-7)
|
|
x-required-scope: operator
|
|
parameters:
|
|
- $ref: '#/components/parameters/IdempotencyKey'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CheckCreate'
|
|
responses:
|
|
'201':
|
|
description: Created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Check'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/checks/{id}:
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntityId'
|
|
patch:
|
|
tags:
|
|
- signals
|
|
operationId: patchCheck
|
|
summary: Update or disable a check
|
|
x-required-scope: operator
|
|
parameters:
|
|
- $ref: '#/components/parameters/IfMatch'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CheckPatch'
|
|
responses:
|
|
'200':
|
|
description: Updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Check'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/executions:
|
|
get:
|
|
tags:
|
|
- executions
|
|
operationId: listExecutions
|
|
summary: List executions
|
|
x-required-scope: viewer
|
|
parameters:
|
|
- name: status
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: target
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: action
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: correlation_id
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- $ref: '#/components/parameters/Cursor'
|
|
- $ref: '#/components/parameters/Limit'
|
|
responses:
|
|
'200':
|
|
description: Executions
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Execution'
|
|
next_cursor:
|
|
type: string
|
|
nullable: true
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
post:
|
|
tags:
|
|
- executions
|
|
operationId: requestExecution
|
|
summary: Request an execution (classify → approval check → enqueue)
|
|
description: 'The handler classifies the (entity, action), checks policy/autonomy,
|
|
|
|
and either enqueues the execution (auto-approved) or creates an
|
|
|
|
approval request and returns the execution in `proposed` state.
|
|
|
|
Also exposed to the agent role — this is the ONLY way agents act.
|
|
|
|
'
|
|
x-required-scope: agent
|
|
parameters:
|
|
- $ref: '#/components/parameters/IdempotencyKey'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ExecutionRequest'
|
|
responses:
|
|
'201':
|
|
description: Execution created (may be pending approval)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Execution'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/executions/{id}:
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntityId'
|
|
get:
|
|
tags:
|
|
- executions
|
|
operationId: getExecution
|
|
summary: Execution status + result
|
|
x-required-scope: viewer
|
|
responses:
|
|
'200':
|
|
description: Execution
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Execution'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/executions/{id}/cancel:
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntityId'
|
|
post:
|
|
tags:
|
|
- executions
|
|
operationId: cancelExecution
|
|
summary: Cancel a proposed/executing execution
|
|
x-required-scope: operator
|
|
responses:
|
|
'200':
|
|
description: Cancelled
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Execution'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/classifications:
|
|
get:
|
|
tags:
|
|
- executions
|
|
operationId: listClassifications
|
|
summary: Classifier decisions (the autonomous-decision audit trail)
|
|
x-required-scope: viewer
|
|
parameters:
|
|
- name: signal_id
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: entity_id
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: route
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum:
|
|
- auto-act
|
|
- escalate
|
|
- hold
|
|
- $ref: '#/components/parameters/Cursor'
|
|
- $ref: '#/components/parameters/Limit'
|
|
responses:
|
|
'200':
|
|
description: Classifications
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Classification'
|
|
next_cursor:
|
|
type: string
|
|
nullable: true
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/approvals:
|
|
get:
|
|
tags:
|
|
- executions
|
|
operationId: listApprovals
|
|
summary: List approvals
|
|
x-required-scope: viewer
|
|
parameters:
|
|
- name: status
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum:
|
|
- pending
|
|
- approved
|
|
- denied
|
|
- expired
|
|
- revoked
|
|
- name: kind
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum:
|
|
- execution
|
|
- policy-change
|
|
- pattern-activation
|
|
- $ref: '#/components/parameters/Cursor'
|
|
- $ref: '#/components/parameters/Limit'
|
|
responses:
|
|
'200':
|
|
description: Approvals
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Approval'
|
|
next_cursor:
|
|
type: string
|
|
nullable: true
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/approvals/{id}/decision:
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntityId'
|
|
post:
|
|
tags:
|
|
- executions
|
|
operationId: decideApproval
|
|
summary: Approve or deny (single-use token verified server-side)
|
|
x-required-scope: operator
|
|
parameters:
|
|
- $ref: '#/components/parameters/IdempotencyKey'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- decision
|
|
properties:
|
|
decision:
|
|
type: string
|
|
enum:
|
|
- approve
|
|
- deny
|
|
- revoke
|
|
note:
|
|
type: string
|
|
token:
|
|
type: string
|
|
description: HMAC approval token (single-use, verified server-side)
|
|
responses:
|
|
'200':
|
|
description: Decision recorded
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Approval'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/patterns:
|
|
get:
|
|
tags:
|
|
- learning
|
|
operationId: listPatterns
|
|
summary: List patterns
|
|
x-required-scope: viewer
|
|
parameters:
|
|
- name: entity_type
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: action
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: status
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- $ref: '#/components/parameters/Cursor'
|
|
- $ref: '#/components/parameters/Limit'
|
|
responses:
|
|
'200':
|
|
description: Patterns
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Pattern'
|
|
next_cursor:
|
|
type: string
|
|
nullable: true
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/patterns/{id}:
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntityId'
|
|
patch:
|
|
tags:
|
|
- learning
|
|
operationId: patchPattern
|
|
summary: Transition a pattern (activate / invalidate / deprecate)
|
|
description: Operator safety valve (plan SG7). Activation is policy-gated config_mutation (S4).
|
|
x-required-scope: operator
|
|
parameters:
|
|
- $ref: '#/components/parameters/IfMatch'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
enum:
|
|
- validated
|
|
- active
|
|
- deprecated
|
|
- invalidated
|
|
quarantined:
|
|
type: boolean
|
|
note:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Pattern'
|
|
'202':
|
|
$ref: '#/components/responses/PendingApproval'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/skills:
|
|
get:
|
|
tags:
|
|
- learning
|
|
operationId: listSkills
|
|
summary: List skills (latest version per skill)
|
|
x-required-scope: viewer
|
|
parameters:
|
|
- name: applies_to
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: action
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: status
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- $ref: '#/components/parameters/Cursor'
|
|
- $ref: '#/components/parameters/Limit'
|
|
responses:
|
|
'200':
|
|
description: Skills
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Skill'
|
|
next_cursor:
|
|
type: string
|
|
nullable: true
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/skills/{id}:
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntityId'
|
|
patch:
|
|
tags:
|
|
- learning
|
|
operationId: patchSkill
|
|
summary: Transition a skill or pin a version
|
|
x-required-scope: operator
|
|
parameters:
|
|
- $ref: '#/components/parameters/IfMatch'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
enum:
|
|
- tested
|
|
- active
|
|
- deprecated
|
|
pinned_version:
|
|
type: integer
|
|
note:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Skill'
|
|
'202':
|
|
$ref: '#/components/responses/PendingApproval'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/skills/{id}/versions:
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntityId'
|
|
get:
|
|
tags:
|
|
- learning
|
|
operationId: listSkillVersions
|
|
summary: Version history of a skill
|
|
x-required-scope: viewer
|
|
responses:
|
|
'200':
|
|
description: Versions
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Skill'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/policy/risk-classes:
|
|
get:
|
|
tags:
|
|
- policy
|
|
operationId: listRiskClasses
|
|
summary: List risk classes
|
|
x-required-scope: viewer
|
|
responses:
|
|
'200':
|
|
description: Risk classes
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/RiskClass'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/policy/approval-rules:
|
|
get:
|
|
tags:
|
|
- policy
|
|
operationId: listApprovalRules
|
|
summary: List approval rules
|
|
x-required-scope: viewer
|
|
responses:
|
|
'200':
|
|
description: Rules
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ApprovalRule'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
post:
|
|
tags:
|
|
- policy
|
|
operationId: createApprovalRule
|
|
summary: Propose a new approval rule (dual-control)
|
|
description: Creates a policy-change approval; the rule applies only after operator approval (plan
|
|
S3).
|
|
x-required-scope: operator
|
|
parameters:
|
|
- $ref: '#/components/parameters/IdempotencyKey'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApprovalRuleCreate'
|
|
responses:
|
|
'202':
|
|
$ref: '#/components/responses/PendingApproval'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/policy/approval-rules/{id}:
|
|
parameters:
|
|
- $ref: '#/components/parameters/EntityId'
|
|
patch:
|
|
tags:
|
|
- policy
|
|
operationId: patchApprovalRule
|
|
summary: Propose a rule change (dual-control)
|
|
x-required-scope: operator
|
|
parameters:
|
|
- $ref: '#/components/parameters/IfMatch'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ApprovalRuleCreate'
|
|
responses:
|
|
'202':
|
|
$ref: '#/components/responses/PendingApproval'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/policy/autonomy:
|
|
get:
|
|
tags:
|
|
- policy
|
|
operationId: getAutonomySettings
|
|
summary: Autonomy settings (kill-switch, never-auto-act list)
|
|
x-required-scope: viewer
|
|
responses:
|
|
'200':
|
|
description: Settings
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/AutonomySetting'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
patch:
|
|
tags:
|
|
- policy
|
|
operationId: patchAutonomySettings
|
|
summary: Propose autonomy changes (dual-control; kill-switch OFF is immediate)
|
|
description: 'Raising autonomy is dual-controlled (202 + approval). Lowering it —
|
|
|
|
setting `global.auto_act: "off"` or adding a never_auto_act key —
|
|
|
|
applies immediately (200): the kill-switch must never wait for an approval.
|
|
|
|
'
|
|
x-required-scope: operator
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Applied (restriction)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/AutonomySetting'
|
|
'202':
|
|
$ref: '#/components/responses/PendingApproval'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/knowledge/search:
|
|
get:
|
|
tags:
|
|
- knowledge
|
|
operationId: searchKnowledge
|
|
summary: Full-text search over knowledge entities (documents, runbooks)
|
|
x-required-scope: viewer
|
|
parameters:
|
|
- name: q
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- $ref: '#/components/parameters/Limit'
|
|
responses:
|
|
'200':
|
|
description: Hits
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/KnowledgeHit'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/knowledge/{entity_id}:
|
|
parameters:
|
|
- name: entity_id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
get:
|
|
tags:
|
|
- knowledge
|
|
operationId: getEntityKnowledge
|
|
summary: All documents/runbooks linked to an entity
|
|
x-required-scope: viewer
|
|
responses:
|
|
'200':
|
|
description: Linked knowledge
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/KnowledgeHit'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/metrics:
|
|
get:
|
|
tags:
|
|
- observability
|
|
operationId: queryMetrics
|
|
summary: Query time-series metrics
|
|
x-required-scope: viewer
|
|
parameters:
|
|
- name: entity_id
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: metric
|
|
in: query
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: string
|
|
style: form
|
|
explode: true
|
|
- name: rollup
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum:
|
|
- raw
|
|
- 1h
|
|
- 1d
|
|
- auto
|
|
default: auto
|
|
- $ref: '#/components/parameters/FromTime'
|
|
- $ref: '#/components/parameters/ToTime'
|
|
responses:
|
|
'200':
|
|
description: Metric series
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/MetricSeries'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/trends/{entity_id}:
|
|
parameters:
|
|
- name: entity_id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
get:
|
|
tags:
|
|
- observability
|
|
operationId: getTrends
|
|
summary: Trend analysis for all metrics on an entity
|
|
x-required-scope: viewer
|
|
parameters:
|
|
- $ref: '#/components/parameters/FromTime'
|
|
- $ref: '#/components/parameters/ToTime'
|
|
responses:
|
|
'200':
|
|
description: Trends
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Trend'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/audit:
|
|
get:
|
|
tags:
|
|
- observability
|
|
operationId: queryAudit
|
|
summary: Audit log
|
|
x-required-scope: operator
|
|
parameters:
|
|
- name: actor_type
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: actor_id
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: entity_id
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: action
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: correlation_id
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- $ref: '#/components/parameters/FromTime'
|
|
- $ref: '#/components/parameters/ToTime'
|
|
- $ref: '#/components/parameters/Cursor'
|
|
- $ref: '#/components/parameters/Limit'
|
|
responses:
|
|
'200':
|
|
description: Audit entries (ts DESC)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/AuditEntry'
|
|
next_cursor:
|
|
type: string
|
|
nullable: true
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/events:
|
|
get:
|
|
tags:
|
|
- observability
|
|
operationId: queryEvents
|
|
summary: Historical events
|
|
x-required-scope: viewer
|
|
parameters:
|
|
- name: type
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: entity_id
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: severity
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: correlation_id
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- $ref: '#/components/parameters/FromTime'
|
|
- $ref: '#/components/parameters/ToTime'
|
|
- $ref: '#/components/parameters/Cursor'
|
|
- $ref: '#/components/parameters/Limit'
|
|
responses:
|
|
'200':
|
|
description: Events (ts DESC)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Event'
|
|
next_cursor:
|
|
type: string
|
|
nullable: true
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/events/stream:
|
|
get:
|
|
tags:
|
|
- observability
|
|
operationId: streamEvents
|
|
summary: Live event stream (SSE)
|
|
description: 'Server-Sent Events. Each event''s `id` is the event row id (resume
|
|
|
|
with `Last-Event-ID`), `event` is the event type, `data` is the JSON
|
|
|
|
Event object. Heartbeat comments every 15s. Best-effort delivery —
|
|
|
|
bounded per-subscriber buffer, drop-oldest (plan P6); use GET /events
|
|
|
|
to backfill.
|
|
|
|
'
|
|
x-required-scope: viewer
|
|
parameters:
|
|
- name: type
|
|
in: query
|
|
schema:
|
|
type: string
|
|
description: Filter by event type prefix
|
|
- name: Last-Event-ID
|
|
in: header
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: SSE stream
|
|
content:
|
|
text/event-stream:
|
|
schema:
|
|
type: string
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/agent-activity:
|
|
get:
|
|
tags:
|
|
- observability
|
|
operationId: queryAgentActivity
|
|
summary: Agent behavior log
|
|
x-required-scope: viewer
|
|
parameters:
|
|
- name: agent_id
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: activity_type
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: entity_id
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- $ref: '#/components/parameters/FromTime'
|
|
- $ref: '#/components/parameters/ToTime'
|
|
- $ref: '#/components/parameters/Cursor'
|
|
- $ref: '#/components/parameters/Limit'
|
|
responses:
|
|
'200':
|
|
description: Activity entries
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/AgentActivity'
|
|
next_cursor:
|
|
type: string
|
|
nullable: true
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/health:
|
|
get:
|
|
tags:
|
|
- observability
|
|
operationId: getFleetHealth
|
|
summary: Fleet health summary with trend indicators
|
|
x-required-scope: viewer
|
|
responses:
|
|
'200':
|
|
description: Health summary
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/HealthSummary'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/dashboard/summary:
|
|
get:
|
|
tags:
|
|
- observability
|
|
operationId: getDashboardSummary
|
|
summary: One-round-trip overview for the control room home page
|
|
x-required-scope: viewer
|
|
responses:
|
|
'200':
|
|
description: Dashboard summary
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/DashboardSummary'
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
/export:
|
|
get:
|
|
tags:
|
|
- system
|
|
operationId: exportSeeds
|
|
summary: Regenerate seed YAMLs from current DB state (DR / version control)
|
|
x-required-scope: operator
|
|
responses:
|
|
'200':
|
|
description: Seed bundle
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- ontology
|
|
- inventory
|
|
- policy
|
|
properties:
|
|
ontology:
|
|
type: string
|
|
description: YAML document
|
|
inventory:
|
|
type: string
|
|
description: YAML document
|
|
policy:
|
|
type: string
|
|
description: YAML document
|
|
default:
|
|
$ref: '#/components/responses/Problem'
|
|
components:
|
|
securitySchemes:
|
|
bearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
description: 'Operator/viewer: Authentik OIDC JWT (validated in-API — Caddy
|
|
|
|
forward-auth is defense-in-depth, not the source of truth).
|
|
|
|
Agent: static bearer token from Infisical (scope `agent`).
|
|
|
|
'
|
|
parameters:
|
|
EntityId:
|
|
name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: UUID or slug (e.g. `host:hubris`)
|
|
Cursor:
|
|
name: cursor
|
|
in: query
|
|
schema:
|
|
type: string
|
|
description: Opaque cursor from a previous response's next_cursor
|
|
Limit:
|
|
name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 50
|
|
maximum: 200
|
|
minimum: 1
|
|
FromTime:
|
|
name: from
|
|
in: query
|
|
schema:
|
|
type: string
|
|
format: date-time
|
|
ToTime:
|
|
name: to
|
|
in: query
|
|
schema:
|
|
type: string
|
|
format: date-time
|
|
IfMatch:
|
|
name: If-Match
|
|
in: header
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: ETag from a prior GET; 412 on version mismatch
|
|
IdempotencyKey:
|
|
name: Idempotency-Key
|
|
in: header
|
|
schema:
|
|
type: string
|
|
maxLength: 128
|
|
description: Client-generated key; replays within 24h return the original response
|
|
EntitySlug:
|
|
name: slug
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Entity slug (e.g. `ws:mac-mini`, `lxc:caddy`)
|
|
headers:
|
|
ETag:
|
|
schema:
|
|
type: string
|
|
description: Resource version for If-Match
|
|
responses:
|
|
Problem:
|
|
description: Error (RFC 9457)
|
|
content:
|
|
application/problem+json:
|
|
schema:
|
|
$ref: '#/components/schemas/Problem'
|
|
PendingApproval:
|
|
description: Change staged; a meta-approval was created (dual-control)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Approval'
|
|
SignalUpdated:
|
|
description: Updated signal
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Signal'
|
|
schemas:
|
|
Problem:
|
|
type: object
|
|
required:
|
|
- title
|
|
- status
|
|
properties:
|
|
type:
|
|
type: string
|
|
format: uri
|
|
default: about:blank
|
|
title:
|
|
type: string
|
|
status:
|
|
type: integer
|
|
detail:
|
|
type: string
|
|
instance:
|
|
type: string
|
|
errors:
|
|
type: array
|
|
description: Field-level validation errors (422)
|
|
items:
|
|
type: object
|
|
required:
|
|
- field
|
|
- reason
|
|
properties:
|
|
field:
|
|
type: string
|
|
reason:
|
|
type: string
|
|
Entity:
|
|
type: object
|
|
required:
|
|
- id
|
|
- slug
|
|
- type
|
|
- name
|
|
- version
|
|
- created_at
|
|
- updated_at
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
slug:
|
|
type: string
|
|
example: host:hubris
|
|
type:
|
|
type: string
|
|
name:
|
|
type: string
|
|
state:
|
|
type: string
|
|
nullable: true
|
|
attributes:
|
|
type: object
|
|
maintenance_until:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
version:
|
|
type: integer
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
health:
|
|
type: string
|
|
description: last observed health, when the entity is monitored
|
|
nullable: true
|
|
enum:
|
|
- healthy
|
|
- degraded
|
|
- down
|
|
- unknown
|
|
- stale
|
|
last_check_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
description: when health was last observed
|
|
EntityCreate:
|
|
type: object
|
|
required:
|
|
- slug
|
|
- type
|
|
- name
|
|
properties:
|
|
slug:
|
|
type: string
|
|
type:
|
|
type: string
|
|
description: Must be a non-abstract entity type
|
|
name:
|
|
type: string
|
|
state:
|
|
type: string
|
|
description: Defaults to the lifecycle's default_state
|
|
attributes:
|
|
type: object
|
|
description: Validated against the type's attribute_schema
|
|
EntityPatch:
|
|
type: object
|
|
description: At least one of the fields must be present.
|
|
properties:
|
|
name:
|
|
type: string
|
|
state:
|
|
type: string
|
|
description: Target lifecycle state (transition validated)
|
|
attributes:
|
|
type: object
|
|
description: Merged; validated against attribute_schema
|
|
maintenance_until:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
Relationship:
|
|
type: object
|
|
required:
|
|
- source
|
|
- target
|
|
- type
|
|
- valid_from
|
|
properties:
|
|
source:
|
|
type: string
|
|
description: Slug of source entity
|
|
target:
|
|
type: string
|
|
description: Slug of target entity
|
|
type:
|
|
type: string
|
|
attributes:
|
|
type: object
|
|
nullable: true
|
|
valid_from:
|
|
type: string
|
|
format: date-time
|
|
valid_to:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
RelationshipCreate:
|
|
type: object
|
|
required:
|
|
- source
|
|
- target
|
|
- type
|
|
properties:
|
|
source:
|
|
type: string
|
|
description: UUID or slug
|
|
target:
|
|
type: string
|
|
description: UUID or slug
|
|
type:
|
|
type: string
|
|
attributes:
|
|
type: object
|
|
GraphView:
|
|
type: object
|
|
required:
|
|
- nodes
|
|
- edges
|
|
properties:
|
|
nodes:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Entity'
|
|
edges:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Relationship'
|
|
truncated:
|
|
type: boolean
|
|
description: True if node cap was hit
|
|
health:
|
|
type: object
|
|
description: entity id -> health, present when include=status was requested
|
|
additionalProperties:
|
|
type: string
|
|
enum:
|
|
- healthy
|
|
- degraded
|
|
- down
|
|
- unknown
|
|
- stale
|
|
EntityType:
|
|
type: object
|
|
required:
|
|
- name
|
|
- domain
|
|
- layer
|
|
- is_abstract
|
|
- status
|
|
properties:
|
|
name:
|
|
type: string
|
|
parent_type:
|
|
type: string
|
|
nullable: true
|
|
is_abstract:
|
|
type: boolean
|
|
domain:
|
|
type: string
|
|
layer:
|
|
type: string
|
|
enum:
|
|
- meta
|
|
- infrastructure
|
|
- governance
|
|
- cognition
|
|
description:
|
|
type: string
|
|
lifecycle_id:
|
|
type: string
|
|
nullable: true
|
|
attribute_schema:
|
|
type: object
|
|
description: JSON Schema
|
|
nullable: true
|
|
schema_version:
|
|
type: integer
|
|
status:
|
|
type: string
|
|
enum:
|
|
- active
|
|
- deprecated
|
|
version:
|
|
type: integer
|
|
EntityTypeCreate:
|
|
type: object
|
|
required:
|
|
- name
|
|
- domain
|
|
- layer
|
|
properties:
|
|
name:
|
|
type: string
|
|
parent_type:
|
|
type: string
|
|
is_abstract:
|
|
type: boolean
|
|
default: false
|
|
domain:
|
|
type: string
|
|
layer:
|
|
type: string
|
|
enum:
|
|
- infrastructure
|
|
- governance
|
|
- cognition
|
|
description:
|
|
type: string
|
|
lifecycle_id:
|
|
type: string
|
|
attribute_schema:
|
|
type: object
|
|
EntityTypePatch:
|
|
type: object
|
|
properties:
|
|
description:
|
|
type: string
|
|
attribute_schema:
|
|
type: object
|
|
status:
|
|
type: string
|
|
enum:
|
|
- active
|
|
- deprecated
|
|
RelationshipType:
|
|
type: object
|
|
required:
|
|
- name
|
|
- source_type
|
|
- target_type
|
|
- cardinality
|
|
properties:
|
|
name:
|
|
type: string
|
|
inverse:
|
|
type: string
|
|
nullable: true
|
|
source_type:
|
|
type: string
|
|
description: May be abstract
|
|
target_type:
|
|
type: string
|
|
description: May be abstract
|
|
cardinality:
|
|
type: string
|
|
enum:
|
|
- one-to-one
|
|
- one-to-many
|
|
- many-to-one
|
|
- many-to-many
|
|
description:
|
|
type: string
|
|
LifecycleDef:
|
|
type: object
|
|
required:
|
|
- id
|
|
- states
|
|
- default_state
|
|
- transitions
|
|
properties:
|
|
id:
|
|
type: string
|
|
states:
|
|
type: array
|
|
items:
|
|
type: string
|
|
default_state:
|
|
type: string
|
|
terminal_states:
|
|
type: array
|
|
items:
|
|
type: string
|
|
transitions:
|
|
type: object
|
|
description: '{from: {to: {requires: [named-check, ...]}}}'
|
|
Signal:
|
|
type: object
|
|
required:
|
|
- id
|
|
- slug
|
|
- kind
|
|
- severity
|
|
- state
|
|
- occurrence_count
|
|
- first_seen_at
|
|
- last_seen_at
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
slug:
|
|
type: string
|
|
kind:
|
|
type: string
|
|
example: service-down
|
|
severity:
|
|
type: string
|
|
enum:
|
|
- info
|
|
- warning
|
|
- critical
|
|
state:
|
|
type: string
|
|
enum:
|
|
- raised
|
|
- acknowledged
|
|
- acting
|
|
- muted
|
|
- resolved
|
|
- failed
|
|
target:
|
|
type: string
|
|
description: Slug of the entity this concerns
|
|
nullable: true
|
|
check_id:
|
|
type: string
|
|
nullable: true
|
|
evidence:
|
|
type: string
|
|
nullable: true
|
|
likely_cause:
|
|
type: string
|
|
nullable: true
|
|
occurrence_count:
|
|
type: integer
|
|
flap_count:
|
|
type: integer
|
|
hold_down_until:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
mute_until:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
first_seen_at:
|
|
type: string
|
|
format: date-time
|
|
last_seen_at:
|
|
type: string
|
|
format: date-time
|
|
Check:
|
|
type: object
|
|
required:
|
|
- id
|
|
- slug
|
|
- kind
|
|
- interval_s
|
|
- timeout_s
|
|
- enabled
|
|
- version
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
slug:
|
|
type: string
|
|
kind:
|
|
type: string
|
|
enum:
|
|
- http
|
|
- tcp
|
|
- disk
|
|
- cert-expiry
|
|
- drift
|
|
- ping
|
|
- ssh-script
|
|
target:
|
|
type: string
|
|
description: Entity slug (instance-scoped)
|
|
nullable: true
|
|
target_type:
|
|
type: string
|
|
description: Entity type (type-scoped)
|
|
nullable: true
|
|
config:
|
|
type: object
|
|
description: Validated per-kind
|
|
interval_s:
|
|
type: integer
|
|
timeout_s:
|
|
type: integer
|
|
zone:
|
|
type: string
|
|
nullable: true
|
|
enabled:
|
|
type: boolean
|
|
version:
|
|
type: integer
|
|
last_health:
|
|
type: string
|
|
description: >-
|
|
This check's own most recent verdict. An entity's health is the
|
|
worst of these across its enabled checks, so this is what explains
|
|
*why* an entity is degraded. Null until the check first runs.
|
|
nullable: true
|
|
enum:
|
|
- healthy
|
|
- degraded
|
|
- down
|
|
- unknown
|
|
last_run_at:
|
|
type: string
|
|
format: date-time
|
|
description: When this check last executed. Null = never run.
|
|
nullable: true
|
|
CheckCreate:
|
|
type: object
|
|
required:
|
|
- slug
|
|
- kind
|
|
properties:
|
|
slug:
|
|
type: string
|
|
kind:
|
|
type: string
|
|
enum:
|
|
- http
|
|
- tcp
|
|
- disk
|
|
- cert-expiry
|
|
- drift
|
|
- ping
|
|
- ssh-script
|
|
target:
|
|
type: string
|
|
target_type:
|
|
type: string
|
|
config:
|
|
type: object
|
|
interval_s:
|
|
type: integer
|
|
default: 600
|
|
timeout_s:
|
|
type: integer
|
|
default: 10
|
|
zone:
|
|
type: string
|
|
enabled:
|
|
type: boolean
|
|
default: true
|
|
CheckPatch:
|
|
type: object
|
|
properties:
|
|
config:
|
|
type: object
|
|
interval_s:
|
|
type: integer
|
|
timeout_s:
|
|
type: integer
|
|
enabled:
|
|
type: boolean
|
|
Execution:
|
|
type: object
|
|
required:
|
|
- id
|
|
- slug
|
|
- action
|
|
- risk_class
|
|
- status
|
|
- correlation_id
|
|
- created_at
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
slug:
|
|
type: string
|
|
target:
|
|
type: string
|
|
nullable: true
|
|
action:
|
|
type: string
|
|
risk_class:
|
|
type: string
|
|
status:
|
|
type: string
|
|
enum:
|
|
- proposed
|
|
- approved
|
|
- auto_approved
|
|
- denied
|
|
- expired
|
|
- executing
|
|
- verifying
|
|
- verified
|
|
- failed
|
|
- timed_out
|
|
- cancelled
|
|
- rolled_back
|
|
- rollback_failed
|
|
classification_id:
|
|
type: string
|
|
nullable: true
|
|
signal_id:
|
|
type: string
|
|
nullable: true
|
|
approval_id:
|
|
type: string
|
|
nullable: true
|
|
agent_id:
|
|
type: string
|
|
nullable: true
|
|
skill_id:
|
|
type: string
|
|
nullable: true
|
|
skill_version:
|
|
type: integer
|
|
nullable: true
|
|
params:
|
|
type: object
|
|
description: Skill params (validated against params_schema)
|
|
result:
|
|
type: object
|
|
nullable: true
|
|
duration_ms:
|
|
type: integer
|
|
nullable: true
|
|
verified:
|
|
type: boolean
|
|
correlation_id:
|
|
type: string
|
|
started_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
completed_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
ExecutionRequest:
|
|
type: object
|
|
required:
|
|
- target
|
|
- action
|
|
properties:
|
|
target:
|
|
type: string
|
|
description: Entity UUID or slug
|
|
action:
|
|
type: string
|
|
example: restart
|
|
params:
|
|
type: object
|
|
signal_id:
|
|
type: string
|
|
description: Signal that motivated this (optional)
|
|
reason:
|
|
type: string
|
|
Classification:
|
|
type: object
|
|
required:
|
|
- id
|
|
- action
|
|
- risk_class
|
|
- route
|
|
- reasoning
|
|
- correlation_id
|
|
- created_at
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
signal_id:
|
|
type: string
|
|
nullable: true
|
|
target:
|
|
type: string
|
|
nullable: true
|
|
action:
|
|
type: string
|
|
recommended_action:
|
|
type: object
|
|
nullable: true
|
|
risk_class:
|
|
type: string
|
|
route:
|
|
type: string
|
|
enum:
|
|
- auto-act
|
|
- escalate
|
|
- hold
|
|
blast_radius:
|
|
type: array
|
|
items:
|
|
type: string
|
|
pattern_confidence:
|
|
type: number
|
|
nullable: true
|
|
skill_id:
|
|
type: string
|
|
nullable: true
|
|
autonomy_check:
|
|
type: string
|
|
reasoning:
|
|
type: object
|
|
correlation_id:
|
|
type: string
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
Approval:
|
|
type: object
|
|
required:
|
|
- id
|
|
- slug
|
|
- action
|
|
- risk_class
|
|
- kind
|
|
- status
|
|
- expires_at
|
|
- created_at
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
slug:
|
|
type: string
|
|
subject:
|
|
type: string
|
|
description: Entity slug the approval concerns
|
|
nullable: true
|
|
action:
|
|
type: string
|
|
risk_class:
|
|
type: string
|
|
kind:
|
|
type: string
|
|
enum:
|
|
- execution
|
|
- policy-change
|
|
- pattern-activation
|
|
payload:
|
|
type: object
|
|
description: e.g. proposed policy diff
|
|
nullable: true
|
|
status:
|
|
type: string
|
|
enum:
|
|
- pending
|
|
- approved
|
|
- denied
|
|
- expired
|
|
- revoked
|
|
expires_at:
|
|
type: string
|
|
format: date-time
|
|
decided_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
decided_by:
|
|
type: string
|
|
nullable: true
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
Pattern:
|
|
type: object
|
|
required:
|
|
- id
|
|
- slug
|
|
- applies_type
|
|
- action
|
|
- pattern
|
|
- confidence
|
|
- evidence_count
|
|
- status
|
|
- version
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
slug:
|
|
type: string
|
|
applies_type:
|
|
type: string
|
|
action:
|
|
type: string
|
|
pattern:
|
|
type: string
|
|
confidence:
|
|
type: number
|
|
description: Wilson lower bound, capped by evidence_count/5
|
|
evidence_count:
|
|
type: integer
|
|
success_count:
|
|
type: integer
|
|
failure_count:
|
|
type: integer
|
|
status:
|
|
type: string
|
|
enum:
|
|
- hypothesized
|
|
- validated
|
|
- active
|
|
- deprecated
|
|
- invalidated
|
|
quarantined:
|
|
type: boolean
|
|
version:
|
|
type: integer
|
|
last_validated_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
Skill:
|
|
type: object
|
|
required:
|
|
- id
|
|
- slug
|
|
- name
|
|
- version
|
|
- action
|
|
- status
|
|
- procedure
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
slug:
|
|
type: string
|
|
name:
|
|
type: string
|
|
version:
|
|
type: integer
|
|
action:
|
|
type: string
|
|
applies_type:
|
|
type: string
|
|
nullable: true
|
|
procedure:
|
|
type: object
|
|
description: Structured steps/verify/rollback/params (plan R3-9)
|
|
required:
|
|
- steps
|
|
- verify
|
|
properties:
|
|
params_schema:
|
|
type: object
|
|
steps:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/SkillStep'
|
|
verify:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/SkillStep'
|
|
rollback:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/SkillStep'
|
|
expected_duration_s:
|
|
type: integer
|
|
known_failure_modes:
|
|
type: array
|
|
items:
|
|
type: string
|
|
pattern_ids:
|
|
type: array
|
|
items:
|
|
type: string
|
|
status:
|
|
type: string
|
|
enum:
|
|
- drafted
|
|
- tested
|
|
- active
|
|
- refined
|
|
- failed
|
|
- deprecated
|
|
success_rate:
|
|
type: number
|
|
nullable: true
|
|
changed_by:
|
|
type: string
|
|
nullable: true
|
|
change_reason:
|
|
type: string
|
|
nullable: true
|
|
last_used_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
SkillStep:
|
|
type: object
|
|
required:
|
|
- runner
|
|
- command
|
|
properties:
|
|
name:
|
|
type: string
|
|
runner:
|
|
type: string
|
|
enum:
|
|
- ssh
|
|
- http
|
|
- internal
|
|
target:
|
|
type: string
|
|
description: Go template over params
|
|
command:
|
|
type: string
|
|
description: Go template over params
|
|
timeout_s:
|
|
type: integer
|
|
default: 60
|
|
expect:
|
|
type: object
|
|
properties:
|
|
exit_code:
|
|
type: integer
|
|
stdout_contains:
|
|
type: string
|
|
retry:
|
|
type: object
|
|
properties:
|
|
attempts:
|
|
type: integer
|
|
delay_s:
|
|
type: integer
|
|
RiskClass:
|
|
type: object
|
|
required:
|
|
- name
|
|
- approval_required
|
|
- autonomy_allowed
|
|
properties:
|
|
name:
|
|
type: string
|
|
description:
|
|
type: string
|
|
approval_required:
|
|
type: string
|
|
enum:
|
|
- none
|
|
- operator
|
|
- operator_confirmed
|
|
autonomy_allowed:
|
|
type: boolean
|
|
ApprovalRule:
|
|
type: object
|
|
required:
|
|
- id
|
|
- action
|
|
- risk_class
|
|
- autonomy_level
|
|
- version
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
entity_type:
|
|
type: string
|
|
description: May be abstract (inherits down)
|
|
nullable: true
|
|
action:
|
|
type: string
|
|
risk_class:
|
|
type: string
|
|
autonomy_level:
|
|
type: string
|
|
enum:
|
|
- auto
|
|
- escalate
|
|
- never
|
|
scope_entity:
|
|
type: string
|
|
description: Entity slug for per-entity overrides
|
|
nullable: true
|
|
version:
|
|
type: integer
|
|
ApprovalRuleCreate:
|
|
type: object
|
|
required:
|
|
- action
|
|
- risk_class
|
|
- autonomy_level
|
|
properties:
|
|
entity_type:
|
|
type: string
|
|
action:
|
|
type: string
|
|
risk_class:
|
|
type: string
|
|
autonomy_level:
|
|
type: string
|
|
enum:
|
|
- auto
|
|
- escalate
|
|
- never
|
|
scope_entity:
|
|
type: string
|
|
AutonomySetting:
|
|
type: object
|
|
required:
|
|
- key
|
|
- value
|
|
- version
|
|
properties:
|
|
key:
|
|
type: string
|
|
example: global.auto_act
|
|
value:
|
|
type: string
|
|
version:
|
|
type: integer
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
KnowledgeHit:
|
|
type: object
|
|
required:
|
|
- id
|
|
- slug
|
|
- type
|
|
- title
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
slug:
|
|
type: string
|
|
type:
|
|
type: string
|
|
enum:
|
|
- document
|
|
- runbook
|
|
- investigation
|
|
title:
|
|
type: string
|
|
source_path:
|
|
type: string
|
|
nullable: true
|
|
snippet:
|
|
type: string
|
|
description: Highlighted match context
|
|
nullable: true
|
|
linked_entities:
|
|
type: array
|
|
items:
|
|
type: string
|
|
rank:
|
|
type: number
|
|
nullable: true
|
|
MetricSeries:
|
|
type: object
|
|
required:
|
|
- entity_id
|
|
- metric
|
|
- rollup
|
|
- samples
|
|
properties:
|
|
entity_id:
|
|
type: string
|
|
metric:
|
|
type: string
|
|
rollup:
|
|
type: string
|
|
enum:
|
|
- raw
|
|
- 1h
|
|
- 1d
|
|
samples:
|
|
type: array
|
|
items:
|
|
type: object
|
|
required:
|
|
- ts
|
|
properties:
|
|
ts:
|
|
type: string
|
|
format: date-time
|
|
value:
|
|
type: number
|
|
description: Raw sample value
|
|
nullable: true
|
|
avg:
|
|
type: number
|
|
nullable: true
|
|
min:
|
|
type: number
|
|
nullable: true
|
|
max:
|
|
type: number
|
|
nullable: true
|
|
count:
|
|
type: integer
|
|
nullable: true
|
|
trend:
|
|
$ref: '#/components/schemas/Trend'
|
|
Trend:
|
|
type: object
|
|
required:
|
|
- metric
|
|
- direction
|
|
properties:
|
|
metric:
|
|
type: string
|
|
direction:
|
|
type: string
|
|
enum:
|
|
- improving
|
|
- degrading
|
|
- stable
|
|
- unknown
|
|
slope:
|
|
type: number
|
|
description: Linear fit per day
|
|
nullable: true
|
|
anomaly:
|
|
type: boolean
|
|
forecast:
|
|
type: number
|
|
description: Simple linear projection, 7d out
|
|
nullable: true
|
|
AuditEntry:
|
|
type: object
|
|
required:
|
|
- id
|
|
- ts
|
|
- actor_type
|
|
- action
|
|
properties:
|
|
id:
|
|
type: integer
|
|
ts:
|
|
type: string
|
|
format: date-time
|
|
actor_type:
|
|
type: string
|
|
enum:
|
|
- agent
|
|
- operator
|
|
- system
|
|
- scheduler
|
|
actor_id:
|
|
type: string
|
|
nullable: true
|
|
action:
|
|
type: string
|
|
entity_id:
|
|
type: string
|
|
nullable: true
|
|
method:
|
|
type: string
|
|
nullable: true
|
|
path:
|
|
type: string
|
|
nullable: true
|
|
status_code:
|
|
type: integer
|
|
nullable: true
|
|
detail:
|
|
type: object
|
|
source_ip:
|
|
type: string
|
|
nullable: true
|
|
correlation_id:
|
|
type: string
|
|
nullable: true
|
|
Event:
|
|
type: object
|
|
required:
|
|
- id
|
|
- ts
|
|
- type
|
|
- severity
|
|
- source
|
|
properties:
|
|
id:
|
|
type: integer
|
|
ts:
|
|
type: string
|
|
format: date-time
|
|
type:
|
|
type: string
|
|
example: signal.raised
|
|
entity_id:
|
|
type: string
|
|
nullable: true
|
|
severity:
|
|
type: string
|
|
enum:
|
|
- info
|
|
- warning
|
|
- critical
|
|
source:
|
|
type: string
|
|
data:
|
|
type: object
|
|
correlation_id:
|
|
type: string
|
|
nullable: true
|
|
AgentActivity:
|
|
type: object
|
|
required:
|
|
- id
|
|
- ts
|
|
- agent_id
|
|
- activity_type
|
|
properties:
|
|
id:
|
|
type: integer
|
|
ts:
|
|
type: string
|
|
format: date-time
|
|
agent_id:
|
|
type: string
|
|
session_id:
|
|
type: string
|
|
nullable: true
|
|
activity_type:
|
|
type: string
|
|
enum:
|
|
- tool_call
|
|
- reasoning
|
|
- decision
|
|
- mcp_query
|
|
- escalation
|
|
tool_name:
|
|
type: string
|
|
nullable: true
|
|
entity_id:
|
|
type: string
|
|
nullable: true
|
|
input_summary:
|
|
type: string
|
|
nullable: true
|
|
output_summary:
|
|
type: string
|
|
nullable: true
|
|
duration_ms:
|
|
type: integer
|
|
nullable: true
|
|
token_count:
|
|
type: integer
|
|
nullable: true
|
|
success:
|
|
type: boolean
|
|
nullable: true
|
|
correlation_id:
|
|
type: string
|
|
nullable: true
|
|
HealthSummary:
|
|
type: object
|
|
required:
|
|
- summary
|
|
- entities
|
|
properties:
|
|
summary:
|
|
type: object
|
|
required:
|
|
- healthy
|
|
- degraded
|
|
- down
|
|
- unknown
|
|
properties:
|
|
healthy:
|
|
type: integer
|
|
degraded:
|
|
type: integer
|
|
down:
|
|
type: integer
|
|
unknown:
|
|
type: integer
|
|
stale:
|
|
type: integer
|
|
description: last observation older than the check's expected cadence
|
|
entities:
|
|
type: array
|
|
items:
|
|
type: object
|
|
required:
|
|
- slug
|
|
- type
|
|
- health
|
|
properties:
|
|
slug:
|
|
type: string
|
|
type:
|
|
type: string
|
|
health:
|
|
type: string
|
|
enum:
|
|
- healthy
|
|
- degraded
|
|
- down
|
|
- unknown
|
|
- stale
|
|
trend:
|
|
type: string
|
|
enum:
|
|
- improving
|
|
- degrading
|
|
- stable
|
|
- unknown
|
|
nullable: true
|
|
last_check_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
DashboardSummary:
|
|
type: object
|
|
required:
|
|
- entities_by_type
|
|
- entities_by_state
|
|
- health
|
|
- signals_by_severity
|
|
- approvals_pending
|
|
- executions_by_state
|
|
- event_rate
|
|
properties:
|
|
entities_by_type:
|
|
type: object
|
|
description: entity counts keyed by type
|
|
additionalProperties:
|
|
type: integer
|
|
entities_by_state:
|
|
type: object
|
|
description: entity counts keyed by state
|
|
additionalProperties:
|
|
type: integer
|
|
health:
|
|
type: object
|
|
required:
|
|
- healthy
|
|
- degraded
|
|
- down
|
|
- unknown
|
|
properties:
|
|
healthy:
|
|
type: integer
|
|
degraded:
|
|
type: integer
|
|
down:
|
|
type: integer
|
|
unknown:
|
|
type: integer
|
|
stale:
|
|
type: integer
|
|
description: last observation older than the check's expected cadence
|
|
signals_by_severity:
|
|
type: object
|
|
description: open (non-resolved) signal counts keyed by severity
|
|
additionalProperties:
|
|
type: integer
|
|
approvals_pending:
|
|
type: integer
|
|
executions_by_state:
|
|
type: object
|
|
description: execution counts keyed by state, last 24h
|
|
additionalProperties:
|
|
type: integer
|
|
event_rate:
|
|
type: array
|
|
description: event counts bucketed by 5-minute interval, most recent last
|
|
items:
|
|
type: object
|
|
required:
|
|
- bucket
|
|
- count
|
|
properties:
|
|
bucket:
|
|
type: string
|
|
format: date-time
|
|
count:
|
|
type: integer
|
|
EnrollRequest:
|
|
type: object
|
|
required:
|
|
- slug
|
|
properties:
|
|
slug:
|
|
type: string
|
|
description: Entity slug (e.g. ws:new-laptop)
|
|
hostname:
|
|
type: string
|
|
description: Actual hostname of the enrolling machine
|
|
mesh_ip:
|
|
type: string
|
|
description: Source mesh IP for identity validation
|
|
EnrollResponse:
|
|
type: object
|
|
required:
|
|
- age_public_key
|
|
- age_private_key
|
|
- infisical_client_id
|
|
- infisical_client_secret
|
|
properties:
|
|
age_public_key:
|
|
type: string
|
|
description: age1... public key for SOPS recipients
|
|
age_private_key:
|
|
type: string
|
|
description: AGE-SECRET-KEY-... for local decryption
|
|
infisical_client_id:
|
|
type: string
|
|
description: Infisical UniversalAuth client ID
|
|
infisical_client_secret:
|
|
type: string
|
|
description: Infisical UniversalAuth client secret
|
|
machine_identity_token:
|
|
type: string
|
|
description: Infisical machine identity access token
|
|
ClientContext:
|
|
type: object
|
|
required:
|
|
- version
|
|
properties:
|
|
version:
|
|
type: integer
|
|
description: Monotonic context version number
|
|
agent_files_changed:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: Paths of agent instruction files that changed
|
|
sops_config_changed:
|
|
type: boolean
|
|
description: True if .sops.yaml recipients changed
|
|
tools_changed:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: Paths of tools/*.setup.sh that changed
|
|
since:
|
|
type: string
|
|
format: date-time
|
|
description: Timestamp for the next poll request
|
|
ClientSecrets:
|
|
type: object
|
|
required:
|
|
- keys
|
|
properties:
|
|
keys:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: Infisical secret keys accessible to this client
|
|
ProvisionRequest:
|
|
type: object
|
|
required:
|
|
- slug
|
|
- type
|
|
- name
|
|
- host
|
|
properties:
|
|
slug:
|
|
type: string
|
|
description: e.g. lxc:jellyfin
|
|
type:
|
|
type: string
|
|
description: Must be lxc, vm, or docker-container
|
|
name:
|
|
type: string
|
|
description: Human-readable name
|
|
host:
|
|
type: string
|
|
description: Slug of the Proxmox host (e.g. host:hubris)
|
|
attributes:
|
|
type: object
|
|
description: VMID, cores, ram_mb, disk_gb, ip, template, mounts, services
|
|
ProvisionResponse:
|
|
type: object
|
|
required:
|
|
- entity
|
|
- execution_id
|
|
properties:
|
|
entity:
|
|
$ref: '#/components/schemas/Entity'
|
|
execution_id:
|
|
type: string
|
|
format: uuid
|
|
description: Execution ID to track provisioning progress
|
|
ProvisionStatus:
|
|
type: object
|
|
required:
|
|
- slug
|
|
- state
|
|
- steps
|
|
properties:
|
|
slug:
|
|
type: string
|
|
state:
|
|
type: string
|
|
description: Current entity state
|
|
steps:
|
|
type: array
|
|
items:
|
|
type: object
|
|
required:
|
|
- step
|
|
- status
|
|
properties:
|
|
step:
|
|
type: string
|
|
status:
|
|
type: string
|
|
enum:
|
|
- pending
|
|
- running
|
|
- ok
|
|
- failed
|
|
- skipped
|
|
error_message:
|
|
type: string
|
|
nullable: true
|
|
started_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
finished_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
error:
|
|
type: string
|
|
nullable: true
|
|
description: Overall error if provisioning failed
|