{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://spec.docuccino.app/uir/2.0/extension.schema.json",
  "title": "Docuccino Extension",
  "type": "object",
  "description": "The Docuccino extension: the `x-docuccino` member a Docuccino-built document carries. This schema describes that member alone, so it applies on top of ANY OpenAPI document — nothing else about the document is assumed. The document root carries the shape below; every object node of the document carries `#/$defs/node`. Strictly closed and carrying no timestamps by design, so no non-deterministic member can be introduced.",
  "x-canonicalOrder": ["document", "generator", "content", "workflows", "diagnostics"],
  "properties": {
    "document": { "$ref": "#/$defs/documentMeta" },
    "generator": { "$ref": "#/$defs/generator" },
    "content": { "$ref": "#/$defs/content" },
    "workflows": { "type": "array", "items": { "$ref": "#/$defs/workflow" } },
    "diagnostics": { "type": "array", "items": { "$ref": "#/$defs/diagnostic" } }
  },
  "additionalProperties": false,
  "$defs": {
    "node": {
      "type": "object",
      "description": "Node-level x-docuccino. Strictly closed (additionalProperties false) so no timestamp-like or non-deterministic members can be introduced, EXCEPT the `facts` container: integration-recorded semantic facts (representation-independent, e.g. a withTrashed route binding), whose contents are integration-defined and which consumers ignore when unknown. Facts carry no timestamps, preserving determinism.",
      "x-canonicalOrder": ["id", "provenance", "mock", "facts"],
      "properties": {
        "id": { "$ref": "#/$defs/nodeId" },
        "provenance": { "type": "array", "items": { "$ref": "#/$defs/provenanceRecord" } },
        "mock": { "$ref": "#/$defs/mockHint" },
        "facts": { "type": "object", "additionalProperties": true }
      },
      "additionalProperties": false
    },
    "documentMeta": {
      "type": "object",
      "x-canonicalOrder": ["id", "configHash", "contentHash"],
      "required": ["id"],
      "properties": {
        "id": { "$ref": "#/$defs/docId" },
        "configHash": { "type": "string" },
        "contentHash": { "type": "string" }
      },
      "additionalProperties": false
    },
    "generator": {
      "type": "object",
      "description": "What built this document, rather than anything about the API: the tool, its version, the extension spec version the document is written to, and the URL that spec is served at. Excluded from contentHash by design, so a tool or spec upgrade never dirties a committed diff.",
      "x-canonicalOrder": ["name", "version", "specVersion", "schema"],
      "required": ["name", "version", "specVersion"],
      "properties": {
        "name": { "type": "string" },
        "version": { "type": "string" },
        "specVersion": { "$ref": "#/$defs/semver" },
        "schema": { "type": "string", "format": "uri" }
      },
      "additionalProperties": false
    },
    "content": {
      "type": "object",
      "description": "The narrative content layer: the compiled `pages` registry and the `nav` tree consumers render the sidebar from. Participates in contentHash, so a prose edit or a nav move is a visible (non-breaking) changelog entry.",
      "x-canonicalOrder": ["pages", "nav"],
      "properties": {
        "pages": { "type": "array", "items": { "$ref": "#/$defs/page" } },
        "nav": { "type": "array", "items": { "$ref": "#/$defs/navNode" } }
      },
      "additionalProperties": false
    },
    "page": {
      "type": "object",
      "x-canonicalOrder": ["id", "slug", "title", "summary", "order", "tags", "content", "provenance"],
      "required": ["id", "slug"],
      "properties": {
        "id": { "$ref": "#/$defs/pageId" },
        "slug": { "type": "string" },
        "title": { "type": "string" },
        "summary": { "type": "string" },
        "order": { "type": "integer" },
        "tags": { "type": "array", "items": { "type": "string" } },
        "content": { "type": "string" },
        "provenance": { "type": "array", "items": { "$ref": "#/$defs/provenanceRecord" } }
      },
      "additionalProperties": false
    },
    "navNode": {
      "type": "object",
      "description": "One node of the compiled navigation tree. `group` nodes carry `children`; `page`/`operation` nodes reference a stable id via `ref` (a `page:`/`op:` id); `tag` nodes reference an OAS tag name. Broken operation/tag refs are diagnostics at assembly, never emitted silently.",
      "x-canonicalOrder": ["type", "ref", "title", "children"],
      "required": ["type"],
      "properties": {
        "type": { "enum": ["group", "page", "operation", "tag"] },
        "ref": { "type": "string" },
        "title": { "type": "string" },
        "children": { "type": "array", "items": { "$ref": "#/$defs/navNode" } }
      },
      "additionalProperties": false
    },
    "workflow": {
      "type": "object",
      "description": "One declared multi-step workflow: a named sequence of this document's own operations, what it takes in, and what it hands back. Participates in contentHash, so adding or re-ordering a step is a visible, non-breaking changelog entry.",
      "x-canonicalOrder": ["id", "summary", "description", "inputs", "steps", "outputs"],
      "required": ["id", "steps"],
      "properties": {
        "id": { "$ref": "#/$defs/workflowName" },
        "summary": { "type": "string" },
        "description": { "type": "string" },
        "inputs": { "$ref": "#/$defs/schema" },
        "steps": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/workflowStep" } },
        "outputs": { "type": "object", "additionalProperties": { "type": "string" } }
      },
      "additionalProperties": false
    },
    "workflowStep": {
      "type": "object",
      "description": "One step of a workflow. `operation` is the called operation's own node id rather than its operationId: an operationId is a name minted from the route and re-minted when the route changes, so a workflow keyed on one points at nothing after a rename, while a node id is a function of the operation itself. Emitters resolve it to whatever name their format addresses operations by.",
      "x-canonicalOrder": ["id", "operation", "description", "parameters", "body", "outputs"],
      "required": ["id", "operation"],
      "properties": {
        "id": { "$ref": "#/$defs/workflowName" },
        "operation": { "$ref": "#/$defs/nodeId" },
        "description": { "type": "string" },
        "parameters": { "type": "array", "items": { "$ref": "#/$defs/stepParameter" } },
        "body": { "$ref": "#/$defs/stepBody" },
        "outputs": { "type": "object", "additionalProperties": { "type": "string" } }
      },
      "additionalProperties": false
    },
    "stepParameter": {
      "type": "object",
      "description": "One value a step passes to the operation it calls. `in` is OpenAPI's own parameter location, because the parameter being supplied is one the operation already declares.",
      "x-canonicalOrder": ["name", "in", "value"],
      "required": ["name", "in"],
      "properties": {
        "name": { "type": "string" },
        "in": { "enum": ["path", "query", "header", "cookie"] },
        "value": {}
      },
      "additionalProperties": false
    },
    "stepBody": {
      "type": "object",
      "description": "The request body a step sends. The payload is carried as written — part literal, part runtime expression — rather than checked against the operation's request schema, because an expression has no value until the workflow runs.",
      "x-canonicalOrder": ["contentType", "payload"],
      "required": ["contentType"],
      "properties": {
        "contentType": { "type": "string" },
        "payload": {}
      },
      "additionalProperties": false
    },
    "workflowName": {
      "type": "string",
      "description": "A workflow or step identifier, constrained to the character set Arazzo allows for its own workflowId and stepId so a declared name never has to be rewritten to be emitted.",
      "pattern": "^[A-Za-z0-9_-]+$"
    },
    "provenanceRecord": {
      "type": "object",
      "x-canonicalOrder": ["producer", "layer", "fields", "source", "confidence", "overrode"],
      "required": ["producer", "layer"],
      "properties": {
        "producer": { "$ref": "#/$defs/producer" },
        "layer": { "$ref": "#/$defs/layer" },
        "fields": { "type": "array", "items": { "type": "string" } },
        "source": { "$ref": "#/$defs/sourceRecord" },
        "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
        "overrode": { "type": "array", "items": { "$ref": "#/$defs/overrodeEntry" } }
      },
      "additionalProperties": false
    },
    "overrodeEntry": {
      "type": "object",
      "x-canonicalOrder": ["field", "value", "producer"],
      "required": ["field"],
      "properties": {
        "field": { "type": "string" },
        "value": true,
        "producer": { "$ref": "#/$defs/producer" }
      },
      "additionalProperties": false
    },
    "sourceRecord": {
      "type": "object",
      "x-canonicalOrder": ["file", "line", "symbol"],
      "required": ["file"],
      "properties": {
        "file": { "type": "string" },
        "line": { "type": "integer", "minimum": 0 },
        "symbol": { "type": "string" }
      },
      "additionalProperties": false
    },
    "mockHint": {
      "type": "object",
      "x-canonicalOrder": ["faker", "seedGroup"],
      "properties": {
        "faker": { "type": "string" },
        "seedGroup": { "type": "string" }
      },
      "additionalProperties": false
    },
    "diagnostic": {
      "type": "object",
      "x-canonicalOrder": ["severity", "code", "message", "source", "routeSignature", "help"],
      "required": ["severity", "code", "message"],
      "properties": {
        "severity": { "enum": ["error", "warning", "info", "hint"] },
        "code": { "type": "string" },
        "message": { "type": "string" },
        "source": { "$ref": "#/$defs/sourceRecord" },
        "routeSignature": { "type": "string" },
        "help": { "type": "string" }
      },
      "additionalProperties": false
    },
    "schema": {
      "type": ["object", "boolean"],
      "x-canonicalOrder": ["x-docuccino", "$ref", "type", "format", "enum", "const", "default", "items", "prefixItems", "properties", "required", "additionalProperties", "allOf", "anyOf", "oneOf", "not"],
      "properties": {
        "x-docuccino": { "$ref": "#/$defs/node" },
        "properties": { "type": "object", "additionalProperties": { "$ref": "#/$defs/schema" } },
        "patternProperties": { "type": "object", "additionalProperties": { "$ref": "#/$defs/schema" } },
        "items": { "$ref": "#/$defs/schema" },
        "prefixItems": { "type": "array", "items": { "$ref": "#/$defs/schema" } },
        "allOf": { "type": "array", "items": { "$ref": "#/$defs/schema" } },
        "anyOf": { "type": "array", "items": { "$ref": "#/$defs/schema" } },
        "oneOf": { "type": "array", "items": { "$ref": "#/$defs/schema" } },
        "not": { "$ref": "#/$defs/schema" }
      },
      "patternProperties": { "^x-": true },
      "additionalProperties": true
    },
    "nodeId": {
      "type": "string",
      "pattern": "^(op|par|sch|res):v1:[0-9a-z]{16}$"
    },
    "docId": {
      "type": "string",
      "pattern": "^doc:.+$"
    },
    "pageId": {
      "type": "string",
      "pattern": "^page:v1:[0-9a-z]{16}$"
    },
    "producer": {
      "type": "string",
      "pattern": "^(inference|attribute|docblock|overlay|config|fallback|integration:[a-z0-9]([a-z0-9-]*[a-z0-9])?)$"
    },
    "layer": {
      "enum": ["inference", "integration", "docblock", "attribute", "overlay", "config", "fallback"]
    },
    "semver": {
      "type": "string",
      "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-[0-9A-Za-z-.]+)?(?:\\+[0-9A-Za-z-.]+)?$"
    }
  }
}
