{
  "openapi": "3.1.0",
  "info": {
    "title": "Daritas Automation Continuity API",
    "version": "1.0.0",
    "description": "Read-only, advisory access to your verified control-system model — the same evidence-backed facts the app shows, scoped to your organization by API key. Nothing here instructs a control action."
  },
  "servers": [
    {
      "url": "https://daritas.com",
      "description": "Daritas"
    }
  ],
  "tags": [
    {
      "name": "Index",
      "description": "Discovery and key check."
    },
    {
      "name": "Assessments",
      "description": "Read the verified model: assessments, behaviours, governed context, drift."
    },
    {
      "name": "AI governance",
      "description": "Record what your own AI systems did, and what AI exposure a floor scan found."
    }
  ],
  "security": [
    {
      "bearerAuth": []
    },
    {
      "apiKeyHeader": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Authorization: Bearer <your key>"
      },
      "apiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "X-API-Key: <your key>"
      }
    }
  },
  "paths": {
    "/api/v1": {
      "get": {
        "operationId": "index",
        "tags": [
          "Index"
        ],
        "summary": "API index",
        "description": "Lists the available endpoints. Key-authenticated, so it doubles as a cheap \"is my key live?\" check.",
        "responses": {
          "200": {
            "description": "The endpoint index.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "product": "Daritas — Automation Continuity read API (v1)",
                  "note": "Read-only, advisory. Every response is scoped to your organization.",
                  "endpoints": {
                    "GET /api/v1/assessments": "List your assessments (id, title, status, latest version)."
                  },
                  "auth": "Authorization: Bearer <your key>  (or  X-API-Key: <your key>)"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "Provide a valid API key via Authorization: Bearer <key>."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/assessments": {
      "get": {
        "operationId": "list-assessments",
        "tags": [
          "Assessments"
        ],
        "summary": "List assessments",
        "description": "Every assessment in your organization, newest first, with the version number and counts of its latest model baseline.",
        "responses": {
          "200": {
            "description": "Your assessments.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "assessments": [
                    {
                      "id": "8f3b1c62-5d94-4a17-9f0e-2c6a7b41d8e5",
                      "title": "AHU-1 air handling unit",
                      "status": "delivered",
                      "latest_version": 3,
                      "counts": {
                        "nodes": 201,
                        "edges": 344,
                        "behaviours": 68
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "Provide a valid API key via Authorization: Bearer <key>."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/assessments/{id}": {
      "get": {
        "operationId": "get-assessment",
        "tags": [
          "Assessments"
        ],
        "summary": "Get one assessment",
        "description": "One assessment with the system it is of, its latest model version, the counts in that baseline and the mean confidence.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The assessment id.",
            "schema": {
              "type": "string"
            },
            "example": "8f3b1c62-5d94-4a17-9f0e-2c6a7b41d8e5"
          }
        ],
        "responses": {
          "200": {
            "description": "The assessment.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "id": "8f3b1c62-5d94-4a17-9f0e-2c6a7b41d8e5",
                  "title": "AHU-1 air handling unit",
                  "status": "delivered",
                  "system_name": "AHU-1",
                  "version": 3,
                  "generated_at": "2026-07-18T09:14:02.000Z",
                  "counts": {
                    "nodes": 201,
                    "edges": 344,
                    "behaviours": 68
                  },
                  "confidence": {
                    "mean": 0.82
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "Provide a valid API key via Authorization: Bearer <key>."
                }
              }
            }
          },
          "404": {
            "description": "No such assessment in your organization. (Same answer whether it does not exist or belongs to someone else — the API never discloses another org.)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "not_found",
                  "message": "No such assessment in your organization."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/assessments/{id}/behaviours": {
      "get": {
        "operationId": "get-behaviours",
        "tags": [
          "Assessments"
        ],
        "summary": "Get grounded behaviours",
        "description": "The behaviours in the latest baseline. Each carries the evidence it was grounded in (source file, locator, quote), the extraction confidence, and the human review status: confirmed · corrected · flagged · unverified.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The assessment id.",
            "schema": {
              "type": "string"
            },
            "example": "8f3b1c62-5d94-4a17-9f0e-2c6a7b41d8e5"
          }
        ],
        "responses": {
          "200": {
            "description": "Behaviours for the latest model version. `version` is null and the list empty when no baseline has been loaded yet.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "version": 3,
                  "behaviours": [
                    {
                      "claim_id": "B-014",
                      "statement": "The heating valve opens when supply air falls more than 2 °C below setpoint.",
                      "subjects": [
                        "HeatValve",
                        "SupplyTemp"
                      ],
                      "function": "temperature-control",
                      "confidence": 0.86,
                      "state": "grounded",
                      "safety_relevant": false,
                      "review_status": "confirmed",
                      "evidence": [
                        {
                          "sourceRef": {
                            "file": "AHU1_Main.st",
                            "locator": "lines 412-418"
                          },
                          "quote": "IF SupplyTemp < SetPoint - 2.0 THEN HeatValve := TRUE;"
                        }
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "Provide a valid API key via Authorization: Bearer <key>."
                }
              }
            }
          },
          "404": {
            "description": "No such assessment in your organization. (Same answer whether it does not exist or belongs to someone else — the API never discloses another org.)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "not_found",
                  "message": "No such assessment in your organization."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/assessments/{id}/context": {
      "get": {
        "operationId": "get-context",
        "tags": [
          "Assessments"
        ],
        "summary": "Get the governed AI context",
        "description": "A bounded context pack built for feeding an AI copilot: the verified facts it may rely on, the known-unknowns it must not assert, the approved evidence sources, coverage numbers, and the usage policy the model is served under. Prefer this over the raw behaviours when an AI is doing the reading.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The assessment id.",
            "schema": {
              "type": "string"
            },
            "example": "8f3b1c62-5d94-4a17-9f0e-2c6a7b41d8e5"
          }
        ],
        "responses": {
          "200": {
            "description": "The governed context pack.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "assessment": {
                    "id": "8f3b1c62-5d94-4a17-9f0e-2c6a7b41d8e5",
                    "title": "AHU-1 air handling unit",
                    "system": "AHU-1",
                    "model_version": 3,
                    "generated_at": "2026-07-18T09:14:02.000Z"
                  },
                  "usage_policy": {
                    "read_only": true,
                    "advisory_only": true,
                    "must_cite_evidence": true,
                    "must_flag_unknowns": true,
                    "no_control_actions": true,
                    "note": "Rely only on verified_behaviours. Treat known_unknowns as UNCONFIRMED — do not assert them as fact. Always cite the evidence file/locator…"
                  },
                  "coverage": {
                    "total": 68,
                    "verified": 41,
                    "unverified": 27,
                    "safety_total": 9,
                    "safety_verified": 9,
                    "coverage_pct": 60
                  },
                  "approved_sources": [
                    "AHU1_Main.st",
                    "AHU1_Alarms.st"
                  ],
                  "verified_behaviours": [
                    {
                      "claim_id": "B-014",
                      "statement": "The heating valve opens when supply air falls more than 2 °C below setpoint.",
                      "function": "temperature-control",
                      "safety_relevant": false,
                      "confidence": 0.86,
                      "evidence": [
                        {
                          "sourceRef": {
                            "file": "AHU1_Main.st",
                            "locator": "lines 412-418"
                          },
                          "quote": "IF SupplyTemp < SetPoint - 2.0 THEN HeatValve := TRUE;"
                        }
                      ]
                    }
                  ],
                  "known_unknowns": [
                    {
                      "claim_id": "B-052",
                      "statement": "Night setback is disabled while the fire damper is open.",
                      "function": "scheduling",
                      "safety_relevant": true,
                      "confidence": 0.41,
                      "evidence": [],
                      "review_status": "unverified",
                      "state": "inferred",
                      "caveat": "Not human-verified — do not assert as fact."
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "Provide a valid API key via Authorization: Bearer <key>."
                }
              }
            }
          },
          "404": {
            "description": "No such assessment in your organization. (Same answer whether it does not exist or belongs to someone else — the API never discloses another org.)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "not_found",
                  "message": "No such assessment in your organization."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/assessments/{id}/changes": {
      "get": {
        "operationId": "get-changes",
        "tags": [
          "Assessments"
        ],
        "summary": "Get drift between baselines",
        "description": "What moved between the two latest model versions — behaviours added, removed and changed — and, importantly, which human sign-offs those changes invalidated. With a single baseline the diff is empty and `note` says so.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The assessment id.",
            "schema": {
              "type": "string"
            },
            "example": "8f3b1c62-5d94-4a17-9f0e-2c6a7b41d8e5"
          }
        ],
        "responses": {
          "200": {
            "description": "The diff between the two latest versions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "from": 2,
                  "to": 3,
                  "unchanged": 61,
                  "invalidated_signoffs": 2,
                  "changed": [
                    {
                      "claim_id": "B-014",
                      "statement": "The heating valve opens when supply air falls more than 2 °C below setpoint.",
                      "safety_relevant": false,
                      "statement_changed": true,
                      "evidence_changed": false,
                      "was_verified": true
                    }
                  ],
                  "added": [
                    {
                      "claim_id": "B-069",
                      "statement": "A filter-blocked alarm latches until acknowledged.",
                      "safety_relevant": false
                    }
                  ],
                  "removed": [
                    {
                      "claim_id": "B-031",
                      "statement": "Fan runs on after shutdown for 90 s.",
                      "safety_relevant": false,
                      "was_verified": true
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "Provide a valid API key via Authorization: Bearer <key>."
                }
              }
            }
          },
          "404": {
            "description": "No such assessment in your organization. (Same answer whether it does not exist or belongs to someone else — the API never discloses another org.)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "not_found",
                  "message": "No such assessment in your organization."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/ai-events": {
      "get": {
        "operationId": "list-ai-events",
        "tags": [
          "AI governance"
        ],
        "summary": "Read the AI runtime ledger",
        "description": "Your organization’s AI event ledger, newest first (up to 200).",
        "parameters": [
          {
            "name": "assessment_id",
            "in": "query",
            "required": false,
            "description": "Restrict to one assessment. Omit for the whole organization.",
            "schema": {
              "type": "string"
            },
            "example": "8f3b1c62-5d94-4a17-9f0e-2c6a7b41d8e5"
          }
        ],
        "responses": {
          "200": {
            "description": "Recorded AI events.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "events": [
                    {
                      "id": "3a9c1f80-6b2d-4d51-8b0a-1f7d2c3e4a55",
                      "job_id": "8f3b1c62-5d94-4a17-9f0e-2c6a7b41d8e5",
                      "source": "hmi-copilot",
                      "actor": "operator:erik",
                      "model": "claude-opus-5",
                      "prompt": "Why did AHU-1 trip last night?",
                      "response": "The filter-blocked alarm latched at 02:14…",
                      "action": "advisory",
                      "influence_level": "L1",
                      "approved_by": null,
                      "linked_behaviour": "B-069",
                      "created_at": "2026-07-19T02:31:44.000Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "Provide a valid API key via Authorization: Bearer <key>."
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "record-ai-event",
        "tags": [
          "AI governance"
        ],
        "summary": "Record an AI event",
        "description": "Append one AI event from your own AI systems (HMI copilot, agent, edge assistant) to the auditable runtime ledger. Every field is optional — record what you have. `assessment_id`, when given, must belong to your organization.",
        "requestBody": {
          "required": true,
          "description": "The event. Unknown fields are ignored; `metadata` takes any JSON you want to keep alongside it.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "example": {
                "source": "hmi-copilot",
                "actor": "operator:erik",
                "model": "claude-opus-5",
                "prompt": "Why did AHU-1 trip last night?",
                "response": "The filter-blocked alarm latched at 02:14…",
                "action": "advisory",
                "influence_level": "L1",
                "approved_by": null,
                "assessment_id": "8f3b1c62-5d94-4a17-9f0e-2c6a7b41d8e5",
                "linked_behaviour": "B-069",
                "metadata": {
                  "session": "abc-123"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Recorded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "id": "3a9c1f80-6b2d-4d51-8b0a-1f7d2c3e4a55",
                  "recorded": true
                }
              }
            }
          },
          "400": {
            "description": "The body was not JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Body must be JSON."
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "Provide a valid API key via Authorization: Bearer <key>."
                }
              }
            }
          },
          "404": {
            "description": "`assessment_id` is not in your organization.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "not_found",
                  "message": "assessment_id not in your organization"
                }
              }
            }
          },
          "500": {
            "description": "The ledger table is not present in this install.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "store_failed",
                  "message": "Could not record the event — has docs/db-ai-ledger.sql been run?"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/exposure": {
      "get": {
        "operationId": "list-exposure",
        "tags": [
          "AI governance"
        ],
        "summary": "Read exposure findings",
        "description": "AI-in-OT exposure findings previously pushed from floor scans.",
        "parameters": [
          {
            "name": "assessment_id",
            "in": "query",
            "required": false,
            "description": "Restrict to one assessment. Omit for the whole organization.",
            "schema": {
              "type": "string"
            },
            "example": "8f3b1c62-5d94-4a17-9f0e-2c6a7b41d8e5"
          },
          {
            "name": "scan_id",
            "in": "query",
            "required": false,
            "description": "Restrict to one scan run.",
            "schema": {
              "type": "string"
            },
            "example": "scan-2026-07-19"
          }
        ],
        "responses": {
          "200": {
            "description": "Exposure findings, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "findings": [
                    {
                      "id": "7c1e4b23-0d55-4a9f-9c31-8ab0e2d47f16",
                      "job_id": "8f3b1c62-5d94-4a17-9f0e-2c6a7b41d8e5",
                      "scan_id": "scan-2026-07-19",
                      "source": "exposure-scan",
                      "file": "hmi/scripts/assistant.py",
                      "line": 88,
                      "kind": "llm-call",
                      "provider": "openai",
                      "snippet": "client.chat.completions.create(...)",
                      "influence_level": "L2",
                      "severity": "medium",
                      "gaps": [
                        "no human approval step",
                        "no evidence citation"
                      ],
                      "status": "open",
                      "created_at": "2026-07-19T06:02:11.000Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "Provide a valid API key via Authorization: Bearer <key>."
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "push-exposure",
        "tags": [
          "AI governance"
        ],
        "summary": "Push exposure findings",
        "description": "Bulk-push findings from a floor exposure scan (`scripts/exposure-scan.mjs --post`). `findings[]` is required; up to 5000 per call.",
        "requestBody": {
          "required": true,
          "description": "The scan run and its findings.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "example": {
                "source": "exposure-scan",
                "scan_id": "scan-2026-07-19",
                "assessment_id": "8f3b1c62-5d94-4a17-9f0e-2c6a7b41d8e5",
                "findings": [
                  {
                    "file": "hmi/scripts/assistant.py",
                    "line": 88,
                    "kind": "llm-call",
                    "provider": "openai",
                    "snippet": "client.chat.completions.create(...)",
                    "influence_level": "L2",
                    "severity": "medium",
                    "gaps": [
                      "no human approval step"
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Stored.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "inserted": 1,
                  "scan_id": "scan-2026-07-19"
                }
              }
            }
          },
          "400": {
            "description": "Body was not JSON, or `findings[]` was missing.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "bad_request",
                  "message": "findings[] required."
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "Provide a valid API key via Authorization: Bearer <key>."
                }
              }
            }
          },
          "404": {
            "description": "`assessment_id` is not in your organization.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "not_found",
                  "message": "assessment_id not in your organization"
                }
              }
            }
          },
          "500": {
            "description": "The exposure table is not present in this install.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "error": "store_failed",
                  "message": "Run docs/db-exposure.sql first."
                }
              }
            }
          }
        }
      }
    }
  }
}