Files

90 lines
7.8 KiB
JSON
Raw Permalink Normal View History

{
"openapi": "3.1.0",
"info": {
"title": "YoVision Bell loopback alert console",
"version": "1.0.0",
"description": "Engineering-only, loopback API for the Event to Rule to Alert to acknowledgement vertical slice. Tenant, site and actor context are server-side configuration, never client input."
},
"servers": [{"url": "http://127.0.0.1:{port}/bell-console/api/v1", "variables": {"port": {"default": "8081"}}}],
"security": [{"consoleBearer": []}],
"paths": {
"/alerts": {
"get": {
"operationId": "listAlerts",
"parameters": [
{"name": "state", "in": "query", "schema": {"$ref": "#/components/schemas/AlertState"}},
{"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 16}},
{"name": "cursor", "in": "query", "schema": {"$ref": "#/components/schemas/AlertId"}}
],
"responses": {
"200": {"description": "Stable newest-first page", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AlertPage"}}}},
"400": {"$ref": "#/components/responses/BadRequest"},
"401": {"$ref": "#/components/responses/Unauthorized"}
}
}
},
"/alerts/{alert_id}": {
"get": {
"operationId": "getAlert",
"parameters": [{"$ref": "#/components/parameters/AlertId"}],
"responses": {
"200": {"description": "Alert, related event facts and append-only transitions", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AlertDetail"}}}},
"401": {"$ref": "#/components/responses/Unauthorized"},
"404": {"$ref": "#/components/responses/NotFound"}
}
}
},
"/alerts/{alert_id}:ack": {
"post": {
"operationId": "acknowledgeAlert",
"parameters": [{"$ref": "#/components/parameters/AlertId"}, {"$ref": "#/components/parameters/IdempotencyKey"}],
"requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CommandBody"}}}},
"responses": {
"200": {"description": "First acknowledgement or exact idempotent replay", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CommandResponse"}}}},
"409": {"description": "Already acknowledged (including actual first actor/time), or reused key", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CommandResponse"}}}},
"401": {"$ref": "#/components/responses/Unauthorized"},
"404": {"$ref": "#/components/responses/NotFound"}
}
}
},
"/alerts/{alert_id}:close": {
"post": {
"operationId": "closeAlert",
"parameters": [{"$ref": "#/components/parameters/AlertId"}, {"$ref": "#/components/parameters/IdempotencyKey"}],
"requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CommandBody"}}}},
"responses": {
"200": {"description": "Close after acknowledgement or exact idempotent replay", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CommandResponse"}}}},
"409": {"description": "Acknowledgement required, already closed, or reused key", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CommandResponse"}}}},
"401": {"$ref": "#/components/responses/Unauthorized"},
"404": {"$ref": "#/components/responses/NotFound"}
}
}
}
},
"components": {
"securitySchemes": {"consoleBearer": {"type": "http", "scheme": "bearer", "description": "External engineering-console token; never persisted in browser storage."}},
"parameters": {
"AlertId": {"name": "alert_id", "in": "path", "required": true, "schema": {"$ref": "#/components/schemas/AlertId"}},
"IdempotencyKey": {"name": "Idempotency-Key", "in": "header", "required": true, "schema": {"type": "string", "minLength": 8, "maxLength": 128, "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"}}
},
"responses": {
"BadRequest": {"description": "Invalid bounded input", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
"Unauthorized": {"description": "Missing or invalid console token", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
"NotFound": {"description": "Alert absent from configured tenant/site", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}
},
"schemas": {
"AlertId": {"type": "string", "pattern": "^alt_[0-9A-HJKMNP-TV-Z]{26}$"},
"AlertState": {"type": "string", "enum": ["open", "acknowledged", "closed"]},
"Severity": {"type": "string", "enum": ["low", "medium", "high", "critical"]},
"AlertSummary": {"type": "object", "additionalProperties": false, "required": ["id", "severity", "title", "state", "rule_key", "rule_version", "created_at"], "properties": {"id": {"$ref": "#/components/schemas/AlertId"}, "severity": {"$ref": "#/components/schemas/Severity"}, "title": {"type": "string", "minLength": 1, "maxLength": 120}, "state": {"$ref": "#/components/schemas/AlertState"}, "rule_key": {"type": "string"}, "rule_version": {"type": "integer", "minimum": 1}, "created_at": {"type": "string", "format": "date-time"}}},
"AlertPage": {"type": "object", "additionalProperties": false, "required": ["items", "next_cursor"], "properties": {"items": {"type": "array", "maxItems": 100, "items": {"$ref": "#/components/schemas/AlertSummary"}}, "next_cursor": {"oneOf": [{"$ref": "#/components/schemas/AlertId"}, {"type": "null"}]}}},
"EventRef": {"type": "object", "additionalProperties": false, "required": ["id", "device_id", "kind", "severity", "occurred_at"], "properties": {"id": {"type": "string", "pattern": "^evt_[0-9A-HJKMNP-TV-Z]{26}$"}, "device_id": {"type": "integer", "minimum": 1}, "kind": {"type": "string"}, "severity": {"$ref": "#/components/schemas/Severity"}, "occurred_at": {"type": "string", "format": "date-time"}}},
"Transition": {"type": "object", "additionalProperties": false, "required": ["sequence", "from_state", "to_state", "actor_ref", "note", "occurred_at"], "properties": {"sequence": {"type": "integer", "minimum": 1}, "from_state": {"oneOf": [{"$ref": "#/components/schemas/AlertState"}, {"type": "null"}]}, "to_state": {"$ref": "#/components/schemas/AlertState"}, "actor_ref": {"type": "string"}, "note": {"oneOf": [{"type": "string", "maxLength": 500}, {"type": "null"}]}, "occurred_at": {"type": "string", "format": "date-time"}}},
"AlertDetail": {"allOf": [{"$ref": "#/components/schemas/AlertSummary"}, {"type": "object", "additionalProperties": false, "required": ["events", "transitions", "evidence_status", "delivery_status"], "properties": {"events": {"type": "array", "items": {"$ref": "#/components/schemas/EventRef"}}, "transitions": {"type": "array", "items": {"$ref": "#/components/schemas/Transition"}}, "evidence_status": {"const": "not_enabled"}, "delivery_status": {"const": "not_enabled"}}}]},
"CommandBody": {"type": "object", "additionalProperties": false, "properties": {"note": {"oneOf": [{"type": "string", "maxLength": 500}, {"type": "null"}]}}},
"CommandResponse": {"type": "object", "additionalProperties": false, "required": ["alert_id", "state", "actor_ref", "occurred_at"], "properties": {"alert_id": {"$ref": "#/components/schemas/AlertId"}, "state": {"$ref": "#/components/schemas/AlertState"}, "actor_ref": {"type": "string"}, "occurred_at": {"type": "string", "format": "date-time"}, "code": {"type": "string", "enum": ["already_acknowledged", "acknowledgement_required", "already_closed", "invalid_state"]}}},
"Error": {"type": "object", "additionalProperties": false, "required": ["code", "message"], "properties": {"code": {"type": "string"}, "message": {"type": "string"}}}
}
}
}