{
  "openapi": "3.1.0",
  "info": {
    "title": "QTI",
    "description": "The QTI API manages tenant-scoped QTI assessment content and delivery records. Assessment items are keyed by tenant and QTI identifier. Package import, export, and scoring workflows are supported on the product default wire behavior. All endpoints require a bearer token; tenant isolation is row-level and derived from the authenticated principal.",
    "version": "1.0"
  },
  "tags": [
    {
      "name": "Artifact",
      "description": "The QTI artifact union master: one row per content object regardless of artifact kind. Content module projections reshape this master by restricting artifact_kind and extending with Alpha-owned columns."
    },
    {
      "name": "Artifact Version",
      "description": "An immutable version snapshot of a QTI artifact. Each version is write-once: the XML payload columns are immutable after creation. Versions form a linear chain via supersedes_version_id."
    },
    {
      "name": "Assessment Item",
      "description": "A tenant-scoped QTI assessment item: one question, task, or prompt whose XML is the source authority and whose product identity is the QTI identifier."
    },
    {
      "name": "Assessment Stimulus",
      "description": "A tenant-scoped QTI assessment stimulus: reusable passage, media prompt, or shared context whose XML is the source authority and whose product identity is the QTI identifier."
    },
    {
      "name": "Assessment Test",
      "description": "A tenant-scoped QTI assessment test: the authored test structure whose XML is the source authority and whose product identity is the QTI test identifier."
    },
    {
      "name": "Attempt",
      "description": "A tenant-scoped QTI runtime attempt for one assessment item inside a delivery session. It records the attempt sequence, the closed runtime status enum, and the server-managed scoring outputs written by the `submitResponses` hook."
    },
    {
      "name": "Component",
      "description": "A QTI component in the recursive assessment structure tree. Each component represents one structural element (test, section, part, item reference) in the assessment hierarchy, with parent-child relationships via the self-referencing parentComponentId."
    },
    {
      "name": "Content Package",
      "description": "The receipt row written by a QTI package import command (JSON-envelope or ZIP). The command writes this receipt in the same transaction as the hook-owned materialization, and this entity's plain GET is the import status endpoint."
    },
    {
      "name": "Delivery Session",
      "description": "A tenant-scoped QTI runtime delivery session for one pseudonymous candidate taking one assessment test. The lifecycle states are platform runtime states, not QTI result-document `sessionStatus`; export mapping is hook-owned."
    },
    {
      "name": "Package Resource",
      "description": "A resource within a QTI content package: one file entry from the package manifest. Resources are identified by their manifest resource identifier within the package scope."
    },
    {
      "name": "QTI conformance evidence",
      "description": "A release-tooling-owned summary of one QTI conformance run. Product callers can read the latest profile-specific trust status without receiving a public conformance-run execution door."
    },
    {
      "name": "Response Declaration",
      "description": "A tenant-scoped QTI response declaration for one item response variable. It records the write-validated QTI base type and cardinality plus JSON authority for correct-response and mapping data."
    },
    {
      "name": "Result Export",
      "description": "The receipt row written by QTI export commands. It records requested refs, status, output pointers, mapping outcomes, counts, errors, and freshness while XML generation and bulk assembly stay hook-owned."
    },
    {
      "name": "Test Item Reference",
      "description": "A tenant-scoped QTI test item reference: one ordered placement of an assessment item inside an assessment test section."
    }
  ],
  "paths": {
    "/qti/artifacts": {
      "get": {
        "operationId": "listArtifacts",
        "summary": "List QTI artifacts",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Artifact"
        ],
        "parameters": [
          {
            "name": "artifactKind",
            "in": "query",
            "required": false,
            "description": "Filter by artifact kind.",
            "schema": {
              "type": "string",
              "enum": [
                "item",
                "test",
                "section",
                "stimulus",
                "outcome-declaration",
                "response-processing",
                "result",
                "usage-data",
                "metadata",
                "manifest-resource"
              ]
            },
            "x-filter": {
              "column": "artifactKind",
              "operator": "eq"
            }
          },
          {
            "name": "qtiIdentifier",
            "in": "query",
            "required": false,
            "description": "Filter by the artifact's QTI identifier (matches assessmentItem.identifier for item artifacts).",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            },
            "x-filter": {
              "column": "qtiIdentifier",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Artifact"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createArtifact",
        "summary": "Create a QTI artifact",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Artifact"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateArtifactRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Artifact"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/artifacts/{id}": {
      "get": {
        "operationId": "getArtifact",
        "summary": "Get a QTI artifact by id",
        "description": "> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Artifact"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Artifact"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (artifact_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateArtifact",
        "summary": "Update a QTI artifact",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Artifact"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateArtifactRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Artifact"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (artifact_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteArtifact",
        "summary": "Delete a QTI artifact",
        "description": "> **Requires role:** `admin`",
        "tags": [
          "Artifact"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Deleted."
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/artifact-versions": {
      "post": {
        "operationId": "createArtifactVersion",
        "summary": "Create an artifact version",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Artifact Version"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateArtifactVersionRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ArtifactVersion"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listArtifactVersions",
        "summary": "List artifact versions",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Artifact Version"
        ],
        "parameters": [
          {
            "name": "artifactId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "artifactId",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ArtifactVersion"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/artifact-versions/{id}": {
      "get": {
        "operationId": "getArtifactVersion",
        "summary": "Get an artifact version by id",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Artifact Version"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ArtifactVersion"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (artifact_version_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/artifact-versions/{id}/qti-xml": {
      "get": {
        "operationId": "getQtiXml",
        "summary": "Get stored canonical QTI XML for an artifact version",
        "description": "Serves the version's stored canonicalXml as a JSON envelope (mediaType, byteLength, xml) after verifying the UTF-8 bytes against xmlHash. ZIP-imported versions have stored bytes; JSON-envelope imports do not. Never reconstructs XML from the component shred. Answer-bearing — admin/author only.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Artifact Version"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The artifact version UUID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "mediaType": {
                      "type": "string",
                      "const": "application/xml",
                      "description": "MIME type of the served XML payload."
                    },
                    "byteLength": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "UTF-8 byte length of the xml string."
                    },
                    "xml": {
                      "type": "string",
                      "minLength": 1,
                      "description": "The stored canonical QTI XML bytes as a UTF-8 string."
                    }
                  },
                  "required": [
                    "mediaType",
                    "byteLength",
                    "xml"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (qti_xml_not_available).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (qti_xml_hash_mismatch).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/items": {
      "post": {
        "operationId": "createAssessmentItem",
        "summary": "Create assessment item",
        "description": "Creates a QTI assessment item master row from authoring input or an import adapter. The item identifier is the tenant-scoped natural key and the XML hash points to the canonical XML authority.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Assessment Item"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAssessmentItemRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssessmentItem"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listAssessmentItems",
        "summary": "List assessment items",
        "description": "Lists QTI assessment items visible in the caller's tenant using the product-default cursor envelope. Filters are fixed to declared item columns.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Assessment Item"
        ],
        "parameters": [
          {
            "name": "interactionType",
            "in": "query",
            "required": false,
            "description": "Return only items with this QTI interaction family.",
            "schema": {
              "type": "string",
              "enum": [
                "choiceInteraction",
                "orderInteraction",
                "associateInteraction",
                "matchInteraction",
                "gapMatchInteraction",
                "textEntryInteraction",
                "extendedTextInteraction",
                "inlineChoiceInteraction",
                "hottextInteraction",
                "hotspotInteraction",
                "selectPointInteraction",
                "graphicOrderInteraction",
                "graphicAssociateInteraction",
                "graphicGapMatchInteraction",
                "positionObjectInteraction",
                "sliderInteraction",
                "uploadInteraction",
                "drawingInteraction",
                "mediaInteraction",
                "endAttemptInteraction",
                "portableCustomInteraction",
                "customInteraction"
              ]
            },
            "x-filter": {
              "column": "interactionType",
              "operator": "eq"
            }
          },
          {
            "name": "language",
            "in": "query",
            "required": false,
            "description": "Return only items whose main language tag matches exactly.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "language",
              "operator": "eq"
            }
          },
          {
            "name": "titleContains",
            "in": "query",
            "required": false,
            "description": "Return only items whose title contains this text.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "title",
              "operator": "contains"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AssessmentItem"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/items/{id}": {
      "get": {
        "operationId": "getAssessmentItem",
        "summary": "Get assessment item",
        "description": "Gets one assessment item by its tenant-scoped QTI identifier and returns the current ETag derived from the managed update timestamp.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Assessment Item"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The QTI item identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssessmentItem"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (assessment_item_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateAssessmentItem",
        "summary": "Update assessment item",
        "description": "Updates author-controlled item metadata and the XML authority pointer. Optimistic concurrency requires the caller's If-Match value to match the current item version.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Assessment Item"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The QTI item identifier.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAssessmentItemRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssessmentItem"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (assessment_item_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Problem (precondition_failed).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteAssessmentItem",
        "summary": "Delete assessment item",
        "description": "Soft-deletes an assessment item in the caller's tenant. The identifier remains reserved so imports and authoring writes cannot silently revive a tombstoned item.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Assessment Item"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The QTI item identifier.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "The item was deleted."
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (assessment_item_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Problem (precondition_failed).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/items/{identifier}/resolve-assets": {
      "post": {
        "operationId": "resolveAssets",
        "summary": "Resolve item asset hrefs to presigned GET URLs",
        "description": "For each requested href, finds the matching packageResource in the item's package scope (via artifact.packageId when present) and returns a 15-minute presigned GET URL when storageRef is set. Unresolved hrefs are omitted; the batch never 404s for missing assets.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Assessment Item"
        ],
        "parameters": [
          {
            "name": "identifier",
            "in": "path",
            "required": true,
            "description": "The QTI item identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "hrefs": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 2048
                    },
                    "minItems": 1,
                    "maxItems": 50,
                    "description": "Package-relative hrefs to resolve against the item's package resources."
                  }
                },
                "required": [
                  "hrefs"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "assets": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "href": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 2048,
                            "description": "The package-relative href that was resolved."
                          },
                          "url": {
                            "type": "string",
                            "minLength": 1,
                            "description": "Presigned S3 GET URL for the media bytes."
                          },
                          "expiresAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "Authoritative expiry instant for the presigned URL (15-minute TTL)."
                          },
                          "mimeType": {
                            "type": "string",
                            "pattern": "^[a-z]+/[a-z0-9.+-]+$",
                            "minLength": 3,
                            "maxLength": 255,
                            "description": "MIME type from the packageResource row."
                          }
                        },
                        "required": [
                          "href",
                          "url",
                          "expiresAt",
                          "mimeType"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Successfully resolved assets. Unresolved hrefs are omitted."
                    }
                  },
                  "required": [
                    "assets"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (assessment_item_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/stimuli": {
      "post": {
        "operationId": "createAssessmentStimulus",
        "summary": "Create assessment stimulus",
        "description": "Creates a QTI assessment stimulus master row from authoring input or an import adapter. The stimulus identifier is the tenant-scoped natural key and the XML hash points to the canonical XML authority.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Assessment Stimulus"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAssessmentStimulusRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssessmentStimulus"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listAssessmentStimuli",
        "summary": "List assessment stimuli",
        "description": "Lists reusable QTI stimuli visible in the caller's tenant using the product-default cursor envelope. Filters are fixed to declared stimulus columns.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Assessment Stimulus"
        ],
        "parameters": [
          {
            "name": "language",
            "in": "query",
            "required": false,
            "description": "Return only stimuli whose main language tag matches exactly.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "language",
              "operator": "eq"
            }
          },
          {
            "name": "titleContains",
            "in": "query",
            "required": false,
            "description": "Return only stimuli whose title contains this text.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "title",
              "operator": "contains"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AssessmentStimulus"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/stimuli/{id}": {
      "get": {
        "operationId": "getAssessmentStimulus",
        "summary": "Get assessment stimulus",
        "description": "Gets one assessment stimulus by its tenant-scoped QTI identifier and returns the current ETag derived from the managed update timestamp.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Assessment Stimulus"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The QTI stimulus identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssessmentStimulus"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (assessment_stimulus_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateAssessmentStimulus",
        "summary": "Update assessment stimulus",
        "description": "Updates author-controlled stimulus metadata and the XML authority pointer. Optimistic concurrency requires the caller's If-Match value to match the current stimulus version.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Assessment Stimulus"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The QTI stimulus identifier.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAssessmentStimulusRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssessmentStimulus"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (assessment_stimulus_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Problem (precondition_failed).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteAssessmentStimulus",
        "summary": "Delete assessment stimulus",
        "description": "Soft-deletes an assessment stimulus in the caller's tenant. The identifier remains reserved so imports and authoring writes cannot silently revive a tombstoned stimulus.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Assessment Stimulus"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The QTI stimulus identifier.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "The stimulus was deleted."
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (assessment_stimulus_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Problem (precondition_failed).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/tests": {
      "post": {
        "operationId": "createAssessmentTest",
        "summary": "Create assessment test",
        "description": "Creates a QTI assessment test master row from authoring input or an import adapter. The test identifier is the tenant-scoped natural key and the XML hash points to the canonical XML authority.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Assessment Test"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAssessmentTestRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssessmentTest"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listAssessmentTests",
        "summary": "List assessment tests",
        "description": "Lists QTI assessment tests visible in the caller's tenant using the product-default cursor envelope. Filters are fixed to declared test columns.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Assessment Test"
        ],
        "parameters": [
          {
            "name": "navigationMode",
            "in": "query",
            "required": false,
            "description": "Return only tests with this QTI navigation mode.",
            "schema": {
              "type": "string",
              "enum": [
                "linear",
                "nonlinear"
              ]
            },
            "x-filter": {
              "column": "navigationMode",
              "operator": "eq"
            }
          },
          {
            "name": "submissionMode",
            "in": "query",
            "required": false,
            "description": "Return only tests with this QTI submission mode.",
            "schema": {
              "type": "string",
              "enum": [
                "individual",
                "simultaneous"
              ]
            },
            "x-filter": {
              "column": "submissionMode",
              "operator": "eq"
            }
          },
          {
            "name": "titleContains",
            "in": "query",
            "required": false,
            "description": "Return only tests whose title contains this text.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "title",
              "operator": "contains"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AssessmentTest"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/tests/{id}": {
      "get": {
        "operationId": "getAssessmentTest",
        "summary": "Get assessment test",
        "description": "Gets one assessment test by its tenant-scoped QTI identifier and returns the current ETag derived from the managed update timestamp.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Assessment Test"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The QTI test identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssessmentTest"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (assessment_test_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateAssessmentTest",
        "summary": "Update assessment test",
        "description": "Updates author-controlled test metadata and the XML authority pointer. Optimistic concurrency requires the caller's If-Match value to match the current test version.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Assessment Test"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The QTI test identifier.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAssessmentTestRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssessmentTest"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (assessment_test_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Problem (precondition_failed).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteAssessmentTest",
        "summary": "Delete assessment test",
        "description": "Soft-deletes an assessment test in the caller's tenant. The identifier remains reserved so imports and authoring writes cannot silently revive a tombstoned test.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Assessment Test"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The QTI test identifier.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "The test was deleted."
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (assessment_test_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Problem (precondition_failed).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/attempts": {
      "post": {
        "operationId": "createAttempt",
        "summary": "Create attempt",
        "description": "Creates an item attempt inside a delivery session. The score and processing trace remain server-managed outputs and are filled by `submitResponses`.\n\n> **Requires role:** `admin` · `runtime`",
        "tags": [
          "Attempt"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAttemptRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Attempt"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listAttempts",
        "summary": "List attempts",
        "description": "Lists item attempts visible in the caller's tenant, normally filtered by delivery session, item, or runtime status.\n\n> **Requires role:** `admin` · `runtime`",
        "tags": [
          "Attempt"
        ],
        "parameters": [
          {
            "name": "deliverySessionId",
            "in": "query",
            "required": false,
            "description": "Return only attempts in this delivery session.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "deliverySessionId",
              "operator": "eq"
            }
          },
          {
            "name": "itemIdentifier",
            "in": "query",
            "required": false,
            "description": "Return only attempts for this QTI assessment item.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "itemIdentifier",
              "operator": "eq"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Return only attempts in this runtime status.",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "suspended",
                "submitted",
                "reviewed",
                "voided"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Attempt"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/attempts/{id}": {
      "get": {
        "operationId": "getAttempt",
        "summary": "Get attempt",
        "description": "Gets one item attempt by its server UUID, including any server-managed score and processing trace already written by the submit hook.\n\n> **Requires role:** `admin` · `runtime`",
        "tags": [
          "Attempt"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The attempt UUID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Attempt"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (attempt_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/attempts/{id}/submit": {
      "post": {
        "operationId": "submitResponses",
        "summary": "Submit responses",
        "description": "Submits candidate response values for scoring. The required hook validates each value-union response against the item's response declarations, runs QTI response processing, and writes `score` plus `processingTrace` in the same transaction; unsupported operators fail closed with `422 unsupported_processing`.\n\n> **Requires role:** `admin` · `runtime`",
        "tags": [
          "Attempt"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The attempt UUID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "The idempotency key (max 128 chars). REQUIRED — absent returns 428. A completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "responses": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "responseIdentifier": {
                          "type": "string",
                          "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
                          "minLength": 1,
                          "maxLength": 255,
                          "description": "The QTI response declaration identifier this submitted value answers."
                        },
                        "value": {
                          "oneOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "number"
                            },
                            {
                              "type": "boolean"
                            },
                            {
                              "type": "array",
                              "items": {
                                "oneOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "number"
                                  },
                                  {
                                    "type": "boolean"
                                  },
                                  {
                                    "type": "object"
                                  }
                                ]
                              }
                            },
                            {
                              "type": "object"
                            }
                          ],
                          "description": "The submitted response value. Accepts scalar, collection, file, and record response shapes; the hook validates the chosen shape against the response declaration's `baseType` and `cardinality`."
                        }
                      },
                      "required": [
                        "responseIdentifier",
                        "value"
                      ],
                      "additionalProperties": false
                    },
                    "minItems": 1,
                    "description": "The response variables submitted for this item attempt."
                  }
                },
                "required": [
                  "responses"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Attempt"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (attempt_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict — an operation with this Idempotency-Key is already in progress (60s lock).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Problem (unsupported_processing).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/attempts/{id}/delivery": {
      "get": {
        "operationId": "getAttemptDelivery",
        "summary": "Get attempt delivery content",
        "description": "Returns the attempt-bound, answer-stripped delivery descriptor for one item attempt. The server resolves the item's current artifact version from the authenticated tenant; clients never supply content ids. Answer keys are stripped at the DOM layer before the XML is returned.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Attempt"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The attempt UUID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "attemptId": {
                      "type": "string",
                      "format": "uuid",
                      "description": "The attempt UUID that was delivered."
                    },
                    "itemIdentifier": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 255,
                      "description": "The QTI assessment item identifier bound to the attempt."
                    },
                    "artifactVersionId": {
                      "type": "string",
                      "format": "uuid",
                      "description": "The artifact version UUID whose canonical XML was stripped and served."
                    },
                    "deliveryXml": {
                      "type": "string",
                      "description": "Answer-stripped QTI item XML safe for a runtime renderer. Never includes response processing, correct responses, mapping, or outcome declarations."
                    },
                    "attemptStatus": {
                      "type": "string",
                      "enum": [
                        "active",
                        "suspended",
                        "submitted",
                        "reviewed",
                        "voided"
                      ],
                      "description": "The attempt's current runtime status at delivery time."
                    }
                  },
                  "required": [
                    "attemptId",
                    "itemIdentifier",
                    "artifactVersionId",
                    "deliveryXml",
                    "attemptStatus"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (attempt_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (attempt_not_deliverable).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/components": {
      "post": {
        "operationId": "createComponent",
        "summary": "Create a component",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Component"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateComponentRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Component"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listComponents",
        "summary": "List components",
        "description": "> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Component"
        ],
        "parameters": [
          {
            "name": "parentComponentId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "parentComponentId",
              "operator": "eq"
            }
          },
          {
            "name": "artifactVersionId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "artifactVersionId",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Component"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/components/{id}": {
      "get": {
        "operationId": "getComponent",
        "summary": "Get a component by id",
        "description": "> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Component"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Component"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (component_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/content-packages": {
      "post": {
        "operationId": "importQtiPackage",
        "summary": "Import QTI package",
        "description": "Accepts the JSON-envelope QTI package import, dispatches to the required importQtiPackage hook, and returns the receipt row at 202. The hook materializes items, stimuli, tests, response declarations, item refs, canonical XML pointers, collision handling, and quarantine records inside the operation transaction.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Content Package"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "The idempotency key (max 128 chars). REQUIRED — absent returns 428. A completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sourceAdapterId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "The source adapter submitting the package envelope."
                  },
                  "producerPackageRef": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255,
                    "description": "The producer's package or batch reference, if supplied."
                  },
                  "packageHash": {
                    "type": "string",
                    "pattern": "^sha256:[0-9a-f]{64}$",
                    "description": "The caller's declared SHA-256 content address for the canonical JSON envelope. When omitted, the hook computes the canonical-JSON hash itself; when supplied, the hook may recompute and reject mismatches."
                  },
                  "manifestMetadata": {
                    "type": "object",
                    "description": "The QTI manifest metadata as a JSON envelope. This is metadata, not a raw IMS package ZIP."
                  },
                  "resources": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "minLength": 1,
                          "description": "Resource kind discriminator (assessmentItem, assessmentStimulus, assessmentTest, responseDeclaration, testItemRef, packageResource, …)."
                        },
                        "identifier": {
                          "type": "string",
                          "minLength": 1,
                          "description": "Manifest resource identifier when known."
                        },
                        "content": {
                          "type": "object",
                          "description": "Typed payload for assessment* / responseDeclaration / testItemRef masters, or packageResource media fields."
                        },
                        "href": {
                          "type": "string",
                          "maxLength": 2048,
                          "description": "Package-relative href for packageResource media rows."
                        },
                        "resourceType": {
                          "type": "string",
                          "maxLength": 255,
                          "description": "QTI manifest resource type for packageResource rows."
                        },
                        "mediaType": {
                          "type": "string",
                          "pattern": "^[a-z]+/[a-z0-9.+-]+$",
                          "minLength": 3,
                          "maxLength": 255,
                          "description": "MIME type for packageResource media rows."
                        },
                        "contentHash": {
                          "type": "string",
                          "pattern": "^sha256:[0-9a-f]{64}$",
                          "description": "SHA-256 of the bytes already uploaded to the content store (packageResource)."
                        },
                        "byteSize": {
                          "type": "integer",
                          "minimum": 0,
                          "description": "Expected ContentLength of the S3 object for packageResource rows."
                        }
                      },
                      "description": "One manifest resource descriptor from the JSON-envelope import. Typed masters use `type` + `content`; packageResource media rows may also carry href/resourceType/mediaType/contentHash/byteSize at the top level or under content."
                    },
                    "description": "JSON-envelope resource entries containing manifest-linked QTI content descriptors. XML canonicalization, identifier namespacing, and materialization are hook-owned. May be empty for a metadata-only receipt. Media packageResource entries may carry contentHash/byteSize so the hook can verify S3 objects and persist storageRef."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Validate and compute counts without materializing content; the returned receipt uses status dryRun."
                  }
                },
                "required": [
                  "sourceAdapterId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentPackage"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentPackage"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict — an operation with this Idempotency-Key is already in progress (60s lock).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Problem (qti_package_rejected).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listContentPackages",
        "summary": "List content-package import receipts.",
        "description": "Lists content-package import receipts for the tenant with cursor pagination, newest first by default ordering. Optional packageHash filter supports ZIP re-import duplicate detection.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Content Package"
        ],
        "parameters": [
          {
            "name": "packageHash",
            "in": "query",
            "required": false,
            "description": "Return only receipts whose packageHash equals this SHA-256 content address.",
            "schema": {
              "type": "string",
              "pattern": "^sha256:[0-9a-f]{64}$"
            },
            "x-filter": {
              "column": "packageHash",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ContentPackage"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/content-packages/import-zip": {
      "post": {
        "operationId": "importQtiPackageZip",
        "summary": "Import QTI/CC package ZIP",
        "description": "Imports a QTI or Common Cartridge ZIP already uploaded to the content store (via upload-slots). Validates HeadObject + byteSize, streams and parses imsmanifest.xml, materializes QTI masters through the same path as importQtiPackage, PutObjects media with content-addressed dedup, and writes a contentPackage receipt with packageStorageRef pointing at the original ZIP. Hard caps: byteSize ≤ 256 MiB and ≤ 2,000 manifest resources (422 naming the cap). dryRun validates without media PutObject or master/resource materialization beyond the receipt.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Content Package"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "The idempotency key (max 128 chars). REQUIRED — absent returns 428. A completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contentHash": {
                    "type": "string",
                    "pattern": "^sha256:[0-9a-f]{64}$",
                    "description": "SHA-256 of the ZIP bytes already uploaded to the content store."
                  },
                  "byteSize": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "Expected ContentLength of the uploaded ZIP object (must be ≤ 256 MiB)."
                  },
                  "sourceAdapterId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "The source adapter submitting the ZIP package import."
                  },
                  "producerPackageRef": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255,
                    "description": "The producer's package or batch reference, if supplied."
                  },
                  "dryRun": {
                    "type": "boolean",
                    "description": "Parse and validate the ZIP (counts/errors) without PutObject or master/resource materialization; the returned receipt uses status dryRun."
                  }
                },
                "required": [
                  "contentHash",
                  "byteSize",
                  "sourceAdapterId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentPackage"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentPackage"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict — an operation with this Idempotency-Key is already in progress (60s lock).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Problem (qti_package_rejected).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/content-packages/upload-slots": {
      "post": {
        "operationId": "requestUploadSlots",
        "summary": "Request presigned PUT upload slots",
        "description": "Derives immutable content-addressed keys for each file and returns 15-minute presigned PUT URLs. The same contentHash always yields the same key/slot; no receipt row is written.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Content Package"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "files": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "contentHash": {
                          "type": "string",
                          "pattern": "^sha256:[0-9a-f]{64}$",
                          "description": "SHA-256 content address of the bytes to upload."
                        },
                        "byteSize": {
                          "type": "integer",
                          "minimum": 0,
                          "description": "Byte length of the object the caller will PUT."
                        },
                        "mediaType": {
                          "type": "string",
                          "pattern": "^[a-z]+/[a-z0-9.+-]+$",
                          "minLength": 3,
                          "maxLength": 255,
                          "description": "MIME type of the object the caller will PUT."
                        }
                      },
                      "required": [
                        "contentHash",
                        "byteSize",
                        "mediaType"
                      ],
                      "additionalProperties": false
                    },
                    "minItems": 1,
                    "maxItems": 200,
                    "description": "Files the caller intends to PUT into the content store before import."
                  }
                },
                "required": [
                  "files"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "slots": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "contentHash": {
                            "type": "string",
                            "pattern": "^sha256:[0-9a-f]{64}$",
                            "description": "Echo of the requested content hash."
                          },
                          "url": {
                            "type": "string",
                            "minLength": 1,
                            "description": "Presigned S3 PUT URL for the immutable content-addressed key."
                          },
                          "expiresAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "Authoritative expiry instant for the presigned URL (15-minute TTL)."
                          }
                        },
                        "required": [
                          "contentHash",
                          "url",
                          "expiresAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Presigned PUT slots, one per requested file (deduped by contentHash key)."
                    }
                  },
                  "required": [
                    "slots"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/content-packages/{id}": {
      "get": {
        "operationId": "getContentPackage",
        "summary": "Get package import status",
        "description": "Gets the content-package import receipt by server-assigned id. This plain CRUD read is the status endpoint for importQtiPackage and exposes response timestamps for freshness.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Content Package"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The server-assigned contentPackage receipt id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentPackage"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (content_package_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/delivery-sessions": {
      "post": {
        "operationId": "createDeliverySession",
        "summary": "Create delivery session",
        "description": "Creates a runtime delivery session for a pseudonymous candidate and an assessment test. The session starts in the `created` lifecycle state and is advanced by the transition operation.\n\n> **Requires role:** `admin` · `runtime`",
        "tags": [
          "Delivery Session"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDeliverySessionRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliverySession"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listDeliverySessions",
        "summary": "List delivery sessions",
        "description": "Lists delivery sessions visible in the caller's tenant. Filters support runtime lookup by test, pseudonymous candidate, or lifecycle state.\n\n> **Requires role:** `admin` · `runtime`",
        "tags": [
          "Delivery Session"
        ],
        "parameters": [
          {
            "name": "testIdentifier",
            "in": "query",
            "required": false,
            "description": "Return only sessions delivering this QTI assessment test.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "testIdentifier",
              "operator": "eq"
            }
          },
          {
            "name": "candidateRef",
            "in": "query",
            "required": false,
            "description": "Return only sessions for this pseudonymous candidate UUID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "candidateRef",
              "operator": "eq"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Return only sessions in this runtime lifecycle state.",
            "schema": {
              "type": "string",
              "enum": [
                "created",
                "active",
                "suspended",
                "submitted",
                "review",
                "closed",
                "voided"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DeliverySession"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/delivery-sessions/{id}": {
      "get": {
        "operationId": "getDeliverySession",
        "summary": "Get delivery session",
        "description": "Gets one delivery session by its server UUID.\n\n> **Requires role:** `admin` · `runtime`",
        "tags": [
          "Delivery Session"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The delivery session UUID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliverySession"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (delivery_session_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/delivery-sessions/{id}/transition": {
      "post": {
        "operationId": "transitionDeliverySession",
        "summary": "Transition delivery session",
        "description": "Advances a delivery session along a legal lifecycle edge. Illegal current-to-target edges return `409 illegal_transition`.\n\n> **Requires role:** `admin` · `runtime`",
        "tags": [
          "Delivery Session"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The delivery session UUID.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "status"
                ],
                "additionalProperties": false,
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "created",
                      "active",
                      "suspended",
                      "submitted",
                      "review",
                      "closed",
                      "voided"
                    ],
                    "description": "The target lifecycle state — the server enforces the legal current → target edge (409 on an illegal transition)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliverySession"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (delivery_session_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (illegal_transition).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/package-resources": {
      "post": {
        "operationId": "createPackageResource",
        "summary": "Create a package resource",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Package Resource"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePackageResourceRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PackageResource"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listPackageResources",
        "summary": "List package resources",
        "description": "> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Package Resource"
        ],
        "parameters": [
          {
            "name": "packageId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "packageId",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PackageResource"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/package-resources/{id}": {
      "get": {
        "operationId": "getPackageResource",
        "summary": "Get a package resource by id",
        "description": "> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Package Resource"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PackageResource"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (package_resource_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/conformance/evidence": {
      "post": {
        "operationId": "createQtiConformanceEvidence",
        "summary": "Record release-generated QTI conformance evidence",
        "description": "> **Requires role:** `admin` · `conformance`",
        "tags": [
          "QTI conformance evidence"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateQtiConformanceEvidenceRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QtiConformanceEvidence"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listQtiConformanceEvidence",
        "summary": "List QTI conformance evidence",
        "description": "> **Requires role:** `admin` · `conformance`",
        "tags": [
          "QTI conformance evidence"
        ],
        "parameters": [
          {
            "name": "profile",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "profile",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/QtiConformanceEvidence"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/conformance/evidence/{id}": {
      "get": {
        "operationId": "getQtiConformanceEvidence",
        "summary": "Get one QTI conformance evidence record",
        "description": "> **Requires role:** `admin` · `conformance`",
        "tags": [
          "QTI conformance evidence"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QtiConformanceEvidence"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (qti_conformance_evidence_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/trust-status": {
      "get": {
        "operationId": "getQtiTrustStatus",
        "summary": "Read latest QTI trust status",
        "description": "Returns the latest conformance evidence for a profile. Conformance execution remains release-tooling-owned and is not a public mutation.\n\n> **Requires role:** `admin` · `author` · `runtime` · `conformance`",
        "tags": [
          "QTI conformance evidence"
        ],
        "parameters": [
          {
            "name": "profile",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "default": "qti-3.0"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "profile": {
                      "type": "string"
                    },
                    "bundleHash": {
                      "type": "string",
                      "pattern": "^sha256:[0-9a-f]{64}$"
                    },
                    "runnerVersion": {
                      "type": "string"
                    },
                    "lastRunStatus": {
                      "type": "string",
                      "enum": [
                        "checking",
                        "trusted",
                        "failed",
                        "error"
                      ]
                    },
                    "startedAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "finishedAt": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true
                    },
                    "assertionSummary": {
                      "type": "object",
                      "properties": {
                        "passed": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "failed": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "skipped": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "error": {
                          "type": "integer",
                          "minimum": 0
                        }
                      },
                      "required": [
                        "passed",
                        "failed",
                        "skipped",
                        "error"
                      ]
                    },
                    "surfaceQcUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "provenance": {
                      "type": "object"
                    }
                  },
                  "required": [
                    "profile",
                    "bundleHash",
                    "runnerVersion",
                    "lastRunStatus",
                    "startedAt",
                    "finishedAt",
                    "assertionSummary",
                    "surfaceQcUrl",
                    "provenance"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (qti_trust_evidence_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/response-declarations": {
      "post": {
        "operationId": "createResponseDeclaration",
        "summary": "Create response declaration",
        "description": "Creates one response declaration for an existing QTI assessment item. The item identifier, response identifier, and tenant form the natural key.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Response Declaration"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateResponseDeclarationRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseDeclaration"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listResponseDeclarations",
        "summary": "List response declarations",
        "description": "Lists response declarations visible in the caller's tenant using fixed filters for item, base type, and cardinality.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Response Declaration"
        ],
        "parameters": [
          {
            "name": "itemIdentifier",
            "in": "query",
            "required": false,
            "description": "Return only declarations owned by this QTI assessment item identifier.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "itemIdentifier",
              "operator": "eq"
            }
          },
          {
            "name": "baseType",
            "in": "query",
            "required": false,
            "description": "Return only declarations with this QTI baseType.",
            "schema": {
              "type": "string",
              "enum": [
                "boolean",
                "directedPair",
                "duration",
                "file",
                "float",
                "identifier",
                "integer",
                "pair",
                "point",
                "string",
                "uri"
              ]
            },
            "x-filter": {
              "column": "baseType",
              "operator": "eq"
            }
          },
          {
            "name": "cardinality",
            "in": "query",
            "required": false,
            "description": "Return only declarations with this QTI cardinality.",
            "schema": {
              "type": "string",
              "enum": [
                "single",
                "multiple",
                "ordered",
                "record"
              ]
            },
            "x-filter": {
              "column": "cardinality",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ResponseDeclaration"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/response-declarations/{itemIdentifier}/{responseIdentifier}": {
      "get": {
        "operationId": "getResponseDeclaration",
        "summary": "Get response declaration",
        "description": "Gets one response declaration by its natural key (item identifier + response identifier).\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Response Declaration"
        ],
        "parameters": [
          {
            "name": "itemIdentifier",
            "in": "path",
            "required": true,
            "description": "The tenant-scoped QTI assessment item identifier (first natural-key leg).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "responseIdentifier",
            "in": "path",
            "required": true,
            "description": "The QTI response variable identifier within the item (second natural-key leg).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseDeclaration"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (response_declaration_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "updateResponseDeclaration",
        "summary": "Update response declaration",
        "description": "Updates declaration metadata and JSON authority for an item response variable. Optimistic concurrency requires the caller's If-Match value to match the current declaration version.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Response Declaration"
        ],
        "parameters": [
          {
            "name": "itemIdentifier",
            "in": "path",
            "required": true,
            "description": "The tenant-scoped QTI assessment item identifier (first natural-key leg).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "responseIdentifier",
            "in": "path",
            "required": true,
            "description": "The QTI response variable identifier within the item (second natural-key leg).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateResponseDeclarationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseDeclaration"
                }
              }
            },
            "headers": {
              "ETag": {
                "description": "The resource's current entity-tag (RFC 9110, quoted). Send it back in If-Match on the next write (optimistic concurrency).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (response_declaration_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Problem (precondition_failed).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteResponseDeclaration",
        "summary": "Delete response declaration",
        "description": "Soft-deletes one response declaration by its natural key (item identifier + response identifier) while preserving the item-level natural key so imports cannot silently revive a tombstoned declaration.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Response Declaration"
        ],
        "parameters": [
          {
            "name": "itemIdentifier",
            "in": "path",
            "required": true,
            "description": "The tenant-scoped QTI assessment item identifier (first natural-key leg).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "responseIdentifier",
            "in": "path",
            "required": true,
            "description": "The QTI response variable identifier within the item (second natural-key leg).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The resource's current ETag (from the last GET/write response), quoted per RFC 9110. REQUIRED — absent returns 428; a stale ETag returns 412 (refetch and retry). Send `*` to overwrite unconditionally.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "The response declaration was deleted."
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (response_declaration_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "description": "Problem (precondition_failed).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this write requires the If-Match header (send the resource's ETag).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/result-exports/assessment-results": {
      "post": {
        "operationId": "exportAssessmentResult",
        "summary": "Export assessment result",
        "description": "Creates a QTI assessmentResult export receipt for one closed delivery session. The required hook loads the session, applies the runtime-to-QTI `sessionStatus` mapping, generates canonical XML bytes into content-addressed storage, and returns the receipt with the output hash.\n\n> **Requires role:** `admin` · `runtime`",
        "tags": [
          "Result Export"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "The idempotency key (max 128 chars). REQUIRED — absent returns 428. A completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "deliverySessionId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "The closed QTI delivery session to export as an assessmentResult document."
                  }
                },
                "required": [
                  "deliverySessionId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultExport"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultExport"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (delivery_session_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Problem (delivery_session_not_closed).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Problem (qti_result_export_rejected).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/result-exports/entities": {
      "post": {
        "operationId": "exportQtiEntities",
        "summary": "Export QTI entities",
        "description": "Creates a bulk QTI entity export receipt for the caller's tenant. The required hook assembles the JSON-envelope artifact from QTI masters and runtime records, applies the optional `modifiedSince` freshness bound, stores the artifact by content hash, and returns this receipt at 202 so consumers do not read directly from Aurora.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Result Export"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "The idempotency key (max 128 chars). REQUIRED — absent returns 428. A completed replay returns the stored response at 200 with idempotency-replayed: true.",
            "schema": {
              "type": "string",
              "maxLength": 128
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "modifiedSince": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Export only records whose exposed response timestamps are newer than this instant. Omit it for a full tenant export."
                  },
                  "testIdentifier": {
                    "type": "string",
                    "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
                    "minLength": 1,
                    "maxLength": 255,
                    "description": "Optionally narrow the bulk export to one QTI assessment test and its related QTI content."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultExport"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultExport"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (assessment_test_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict — an operation with this Idempotency-Key is already in progress (60s lock).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Problem (qti_entities_export_rejected).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "428": {
            "description": "Precondition Required — this operation requires the Idempotency-Key header.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/result-exports/{id}": {
      "get": {
        "operationId": "getResultExport",
        "summary": "Get result export status",
        "description": "Gets the result-export receipt by server-assigned id. This plain CRUD read is the status endpoint for both export commands and exposes response timestamps for freshness.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Result Export"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The server-assigned resultExport receipt id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultExport"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (result_export_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/result-exports": {
      "get": {
        "operationId": "listResultExports",
        "summary": "List result-export receipts.",
        "description": "Lists result-export receipts for the tenant with cursor pagination.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Result Export"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ResultExport"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/test-item-refs": {
      "post": {
        "operationId": "createTestItemRef",
        "summary": "Create test item reference",
        "description": "Creates one item placement within a QTI assessment test. The natural key is the tenant, test identifier, and item identifier; the ordinal and section identifier carry the test structure.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Test Item Reference"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTestItemRefRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestItemRef"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listTestItemRefs",
        "summary": "List test item references",
        "description": "Lists QTI item placements visible in the caller's tenant, normally filtered to one assessment test and ordered by the test structure.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Test Item Reference"
        ],
        "parameters": [
          {
            "name": "testIdentifier",
            "in": "query",
            "required": false,
            "description": "Return only item references for this QTI assessment test.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "testIdentifier",
              "operator": "eq"
            }
          },
          {
            "name": "itemIdentifier",
            "in": "query",
            "required": false,
            "description": "Return only item references that place this QTI assessment item.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "itemIdentifier",
              "operator": "eq"
            }
          },
          {
            "name": "sectionIdentifier",
            "in": "query",
            "required": false,
            "description": "Return only item references in this QTI assessment section.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "sectionIdentifier",
              "operator": "eq"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return on this page (clamped server-side).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor — pass the previous page's `nextCursor` to fetch the next page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TestItemRef"
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor for the next page, or null when this is the last page."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Not Found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qti/test-item-refs/{testIdentifier}/{itemIdentifier}": {
      "get": {
        "operationId": "getTestItemRef",
        "summary": "Get test item reference",
        "description": "Gets one QTI item placement by its natural key (test identifier + item identifier).\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Test Item Reference"
        ],
        "parameters": [
          {
            "name": "testIdentifier",
            "in": "path",
            "required": true,
            "description": "The tenant-scoped QTI assessment test identifier (first natural-key leg).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "itemIdentifier",
            "in": "path",
            "required": true,
            "description": "The QTI assessment item identifier placed in the test (second natural-key leg).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestItemRef"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (test_item_ref_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateTestItemRef",
        "summary": "Update test item reference",
        "description": "Updates the authored section placement metadata for an existing QTI item reference without changing the natural-key legs.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Test Item Reference"
        ],
        "parameters": [
          {
            "name": "testIdentifier",
            "in": "path",
            "required": true,
            "description": "The tenant-scoped QTI assessment test identifier (first natural-key leg).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "itemIdentifier",
            "in": "path",
            "required": true,
            "description": "The QTI assessment item identifier placed in the test (second natural-key leg).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateTestItemRefRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestItemRef"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (test_item_ref_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteTestItemRef",
        "summary": "Delete test item reference",
        "description": "Soft-deletes one QTI item placement from a test structure in the caller's tenant.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Test Item Reference"
        ],
        "parameters": [
          {
            "name": "testIdentifier",
            "in": "path",
            "required": true,
            "description": "The tenant-scoped QTI assessment test identifier (first natural-key leg).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "itemIdentifier",
            "in": "path",
            "required": true,
            "description": "The QTI assessment item identifier placed in the test (second natural-key leg).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "The item reference was deleted."
                }
              }
            }
          },
          "400": {
            "description": "Bad Request.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Problem (test_item_ref_not_found).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Conflict.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Not Implemented.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Artifact": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Server-assigned surrogate identifier for the artifact.",
            "readOnly": true
          },
          "artifactKind": {
            "type": "string",
            "enum": [
              "item",
              "test",
              "section",
              "stimulus",
              "outcome-declaration",
              "response-processing",
              "result",
              "usage-data",
              "metadata",
              "manifest-resource"
            ],
            "description": "The open QTI artifact kind vocabulary. Content projections restrict this to the public subset."
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "The artifact title."
          },
          "language": {
            "type": "string",
            "pattern": "^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$",
            "minLength": 2,
            "maxLength": 35,
            "description": "BCP 47 language tag for the artifact."
          },
          "qtiIdentifier": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The original QTI identifier from the source package."
          },
          "latestVersionId": {
            "type": "string",
            "format": "uuid",
            "description": "The id of the most recent artifact version."
          },
          "packageId": {
            "type": "string",
            "format": "uuid",
            "description": "The content package this artifact was imported from."
          },
          "resourceId": {
            "type": "string",
            "format": "uuid",
            "description": "The package resource this artifact corresponds to."
          },
          "contentKind": {
            "type": "string",
            "enum": [
              "question",
              "test",
              "test_spec",
              "test_bank",
              "article",
              "video",
              "audio",
              "image",
              "interactive",
              "media_asset",
              "external_link",
              "script",
              "stimulus"
            ],
            "description": "Alpha content kind. Nullable on the QTI union master; Content projection/hooks enforce write requiredness. Includes Incept `stimulus` as a public contentKind home (artifactKind provenance remains `stimulus`)."
          },
          "phonicsSet": {
            "type": "object",
            "description": "Decodable phonics constraint set (module-content extends.phonics_set jsonb; public API camelCase phonicsSet). Nullable Alpha column on the union master; Content hooks guard writes to subtype=decodable.",
            "additionalProperties": true
          },
          "subtype": {
            "type": "string",
            "enum": [
              "diagram",
              "decodable",
              "script"
            ],
            "description": "Governed content subtype for specialized content variants. Nullable Alpha column on the union master."
          },
          "sourceSystem": {
            "type": "string",
            "enum": [
              "qti",
              "alpha_content",
              "external_content_import"
            ],
            "description": "Originating system that produced this content. Nullable Alpha column on the union master."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published",
              "retired",
              "archived"
            ],
            "description": "Content lifecycle status. Nullable Alpha column on the union master; Content hooks enforce write requiredness."
          },
          "subjectId": {
            "type": "string",
            "enum": [
              "math",
              "reading",
              "language",
              "science",
              "vocabulary",
              "writing"
            ],
            "description": "Canonical subject id. Nullable Alpha column on the union master."
          },
          "targetGradeId": {
            "type": "string",
            "enum": [
              "pre_k",
              "k",
              "1",
              "2",
              "3",
              "4",
              "5",
              "6",
              "7",
              "8",
              "9",
              "10",
              "11",
              "12",
              "postsecondary",
              "ungraded"
            ],
            "description": "Target grade (alpha_grade_id). Nullable Alpha column on the union master."
          },
          "dok": {
            "type": "string",
            "enum": [
              "dok1",
              "dok2",
              "dok3",
              "dok4"
            ],
            "description": "Webb Depth of Knowledge. Nullable Alpha column on the union master."
          },
          "expectedXp": {
            "type": "integer",
            "minimum": 0,
            "description": "Student-independent expected XP config. Nullable Alpha column on the union master."
          },
          "subjectFamily": {
            "type": "string",
            "description": "proxy classification (map vs proxy) as metadata. Optional Alpha column on the union master."
          },
          "externalUrl": {
            "type": "string",
            "format": "uri",
            "pattern": "^https?://",
            "description": "Canonical http(s) destination for external-link content. Nullable Alpha column on the union master."
          },
          "displayUrl": {
            "type": "string",
            "maxLength": 512,
            "description": "Safe author-facing display label for the external URL. Nullable Alpha column on the union master."
          },
          "openPolicy": {
            "type": "string",
            "enum": [
              "same_tab",
              "new_tab",
              "embedded_iframe_allowed",
              "external_app_handoff"
            ],
            "description": "Governed client navigation policy for external-link content. Nullable Alpha column on the union master.",
            "default": "new_tab"
          },
          "externalLinkLastValidatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Most recent external destination validation timestamp. Nullable Alpha column on the union master."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "id",
          "title",
          "language",
          "qtiIdentifier",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "ArtifactVersion": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Server-assigned surrogate identifier for the artifact version.",
            "readOnly": true
          },
          "versionNumber": {
            "type": "integer",
            "minimum": 1,
            "description": "Monotonically increasing version number within the parent artifact."
          },
          "xmlHash": {
            "type": "string",
            "minLength": 32,
            "maxLength": 64,
            "description": "Content hash of the canonical XML for this version. Part of the dedup unique constraint."
          },
          "sourceXml": {
            "type": "string",
            "description": "The original source XML as imported."
          },
          "canonicalXml": {
            "type": "string",
            "description": "The canonicalized XML form for deterministic comparison."
          },
          "objectGraph": {
            "type": "object",
            "description": "The shredded object graph representation of the QTI XML.",
            "additionalProperties": true
          },
          "authoringJson": {
            "type": "object",
            "description": "The authoring-surface JSON representation.",
            "additionalProperties": true
          },
          "deliveryBody": {
            "type": "string",
            "description": "The rendered delivery HTML body derived from the QTI XML for the delivery surface."
          },
          "specTrace": {
            "type": "string",
            "description": "QTI specification traceability metadata."
          },
          "supersedesVersionId": {
            "type": "string",
            "format": "uuid",
            "description": "Self-FK to the previous version this one supersedes. NULL for the first version.",
            "x-references": "artifactVersion.id",
            "x-onDelete": "restrict"
          },
          "createdBy": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The authenticated principal who authored this version."
          },
          "artifactId": {
            "type": "string",
            "format": "uuid",
            "description": "FK to the parent artifact.",
            "x-references": "artifact.id",
            "x-onDelete": "cascade"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "versionNumber",
          "xmlHash",
          "createdBy",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "AssessmentItem": {
        "type": "object",
        "properties": {
          "identifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The product-canonical QTI item identifier. It is assigned at import or authoring time, follows the QTI NCName shape, and is unique within a tenant."
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "The item title used by authors and item-bank workflows to browse, select, and reuse this item."
          },
          "interactionType": {
            "type": "string",
            "enum": [
              "choiceInteraction",
              "orderInteraction",
              "associateInteraction",
              "matchInteraction",
              "gapMatchInteraction",
              "textEntryInteraction",
              "extendedTextInteraction",
              "inlineChoiceInteraction",
              "hottextInteraction",
              "hotspotInteraction",
              "selectPointInteraction",
              "graphicOrderInteraction",
              "graphicAssociateInteraction",
              "graphicGapMatchInteraction",
              "positionObjectInteraction",
              "sliderInteraction",
              "uploadInteraction",
              "drawingInteraction",
              "mediaInteraction",
              "endAttemptInteraction",
              "portableCustomInteraction",
              "customInteraction"
            ],
            "description": "The primary QTI interaction family for the item. The value is the closed 22-value QTI interaction vocabulary and is validated at write time."
          },
          "xmlHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$",
            "description": "The SHA-256 content address of the canonical QTI item XML. The XML bytes and shred graph are hook-owned; this field is the stable authority pointer."
          },
          "language": {
            "type": "string",
            "pattern": "^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$",
            "minLength": 2,
            "maxLength": 35,
            "description": "The main language of the item as a BCP 47 language tag when known."
          },
          "responseProcessing": {
            "type": "object",
            "description": "The item's declared response-processing spec, projected from the canonical QTI XML at import/authoring time: spec version, standard template name or normalized inline rules, and normalized outcome declarations. Absent or unparseable processing MUST be represented explicitly (template \"none\" / \"unsupported\") — a null field fails closed at submit. Execution semantics are hook-owned. Canonical shape is validated by the shared hook-owned parser (specVersion, template, outcomes, rules, unsupportedReason).",
            "additionalProperties": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "identifier",
          "title",
          "interactionType",
          "xmlHash",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "AssessmentStimulus": {
        "type": "object",
        "properties": {
          "identifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The product-canonical QTI stimulus identifier. It is assigned at import or authoring time, follows the QTI NCName shape, and is unique within a tenant."
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "The stimulus title used by authors and content workflows to browse, select, and reuse this shared context."
          },
          "xmlHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$",
            "description": "The SHA-256 content address of the canonical QTI stimulus XML. The XML bytes and any shred graph are hook-owned; this field is the stable authority pointer."
          },
          "language": {
            "type": "string",
            "pattern": "^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$",
            "minLength": 2,
            "maxLength": 35,
            "description": "The main language of the stimulus as a BCP 47 language tag when known."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "identifier",
          "title",
          "xmlHash",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "AssessmentTest": {
        "type": "object",
        "properties": {
          "identifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The product-canonical QTI test identifier. It is assigned at import or authoring time, follows the QTI NCName shape, and is unique within a tenant."
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "The test title used by authors and assessment workflows to browse, assemble, and deliver this assessment test."
          },
          "navigationMode": {
            "type": "string",
            "enum": [
              "linear",
              "nonlinear"
            ],
            "description": "The QTI navigation mode for the test. `linear` requires candidates to proceed in sequence; `nonlinear` permits non-sequential navigation."
          },
          "submissionMode": {
            "type": "string",
            "enum": [
              "individual",
              "simultaneous"
            ],
            "description": "The QTI submission mode for the test. `individual` submits item responses as separate response transactions; `simultaneous` submits the test's responses together."
          },
          "xmlHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$",
            "description": "The SHA-256 content address of the canonical QTI test XML. The XML bytes and any structural shred are hook-owned; this field is the stable authority pointer."
          },
          "isMasteryGate": {
            "type": "boolean",
            "description": "Typed structural fact: whether this test is a mastery gate. Nullable Alpha column on the QTI assessment_test master."
          },
          "testType": {
            "type": "string",
            "enum": [
              "end_of_course",
              "end_of_grade",
              "test_out",
              "placement",
              "diagnostic",
              "screener"
            ],
            "description": "Alpha test-type vocabulary. Nullable Alpha column on the QTI assessment_test master."
          },
          "assessmentRole": {
            "type": "string",
            "enum": [
              "form",
              "spec",
              "bank"
            ],
            "description": "Assessment role: form, blueprint spec overlay, or bank overlay. Nullable Alpha column on the QTI assessment_test master."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "identifier",
          "title",
          "navigationMode",
          "submissionMode",
          "xmlHash",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "Attempt": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The server-minted UUID that identifies this item attempt.",
            "readOnly": true
          },
          "deliverySessionId": {
            "type": "object",
            "description": "A OneRoster GUIDRef to a deliverySession — the referenced resource's sourcedId, its type, and a dereferenceable href. On write, either this object (its sourcedId is used) or the bare sourcedId string is accepted.",
            "required": [
              "sourcedId",
              "type"
            ],
            "properties": {
              "href": {
                "type": "string",
                "description": "The dereferenceable URL of the referenced resource."
              },
              "sourcedId": {
                "type": "string",
                "description": "The sourcedId of the referenced resource."
              },
              "type": {
                "type": "string",
                "const": "deliverySession",
                "description": "The referenced resource type."
              }
            }
          },
          "itemIdentifier": {
            "type": "object",
            "description": "A OneRoster GUIDRef to a assessmentItem — the referenced resource's sourcedId, its type, and a dereferenceable href. On write, either this object (its sourcedId is used) or the bare sourcedId string is accepted.",
            "required": [
              "sourcedId",
              "type"
            ],
            "properties": {
              "href": {
                "type": "string",
                "description": "The dereferenceable URL of the referenced resource."
              },
              "sourcedId": {
                "type": "string",
                "description": "The sourcedId of the referenced resource."
              },
              "type": {
                "type": "string",
                "const": "assessmentItem",
                "description": "The referenced resource type."
              }
            }
          },
          "attemptNumber": {
            "type": "integer",
            "minimum": 1,
            "description": "The one-based sequence number for this candidate's attempts at the item within the delivery session."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "submitted",
              "reviewed",
              "voided"
            ],
            "description": "The closed runtime status enum for an item attempt. `active` means responses may still change; `submitted` means responses reached the submit hook; `reviewed` means scoring or review finished; `voided` means the attempt must not count.",
            "default": "active"
          },
          "score": {
            "type": "number",
            "description": "The numeric score written by the `submitResponses` scoring hook. It is never accepted from API clients and is absent until the runtime has scored the attempt.",
            "readOnly": true,
            "x-server-managed": true
          },
          "processingTrace": {
            "type": "object",
            "description": "The response-processing trace written by the `submitResponses` hook, including which response operators ran and any fail-closed unsupported-processing evidence.",
            "readOnly": true,
            "x-server-managed": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "id",
          "deliverySessionId",
          "itemIdentifier",
          "attemptNumber",
          "status",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "Component": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Server-assigned surrogate identifier for the component.",
            "readOnly": true
          },
          "parentComponentId": {
            "type": "string",
            "format": "uuid",
            "description": "Self-referencing FK to the parent component in the tree. NULL for root-level components (tests).",
            "x-references": "component.id",
            "x-onDelete": "cascade"
          },
          "elementName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The QTI XML element name (assessmentTest, testPart, assessmentSection, assessmentItemRef, etc.)."
          },
          "typeName": {
            "type": "string",
            "maxLength": 255,
            "description": "The QTI type name when the element carries an explicit xsi:type. Used for disambiguation when element_name alone is insufficient."
          },
          "ordinal": {
            "type": "integer",
            "minimum": 0,
            "description": "Position of this component among its siblings within the parent. Preserves document order."
          },
          "attributes": {
            "type": "object",
            "description": "The QTI XML attributes on this element as a JSON object.",
            "additionalProperties": true
          },
          "sourceTrace": {
            "type": "string",
            "description": "Import source traceability metadata."
          },
          "namespaceUri": {
            "type": "string",
            "maxLength": 512,
            "description": "The XML namespace URI for this element."
          },
          "qualifiedName": {
            "type": "string",
            "maxLength": 512,
            "description": "The fully qualified XML element name."
          },
          "artifactVersionId": {
            "type": "string",
            "format": "uuid",
            "description": "FK to the artifact version this component belongs to.",
            "x-references": "artifactVersion.id",
            "x-onDelete": "cascade"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "elementName",
          "ordinal",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "ContentPackage": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Stable server-assigned identifier for this import receipt. It is not a QTI content identifier and is never a cross-module foreign-key target.",
            "readOnly": true
          },
          "status": {
            "type": "string",
            "enum": [
              "accepted",
              "partial",
              "rejected",
              "dryRun"
            ],
            "description": "The terminal outcome of the synchronous import: fully materialized, materialized with quarantined records, rejected without materialization, or validated without writes."
          },
          "sourceAdapterId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120,
            "description": "The pluggable source adapter that produced the JSON-envelope import. It identifies the adapter contract, not a binary upload channel."
          },
          "producerPackageRef": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The producer's package or batch reference when the source system supplies one. Domain-level duplicate handling remains hook-owned."
          },
          "packageHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$",
            "description": "The SHA-256 content address of the imported package: the canonical JSON envelope hash for importQtiPackage, or the uploaded ZIP contentHash for importQtiPackageZip."
          },
          "manifestHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$",
            "description": "The SHA-256 content address of the normalized QTI manifest metadata carried inside the JSON envelope."
          },
          "manifestMetadata": {
            "type": "object",
            "description": "JSON-envelope metadata extracted from the QTI manifest, such as manifest identifier, package title, schema version, and declared resource summaries. The hook interprets and validates the manifest shape."
          },
          "resourceCount": {
            "type": "integer",
            "minimum": 0,
            "description": "How many manifest resources the JSON envelope declared for import."
          },
          "itemCount": {
            "type": "integer",
            "minimum": 0,
            "description": "How many assessment item masters the hook materialized or validated from the package."
          },
          "stimulusCount": {
            "type": "integer",
            "minimum": 0,
            "description": "How many assessment stimulus masters the hook materialized or validated from the package."
          },
          "testCount": {
            "type": "integer",
            "minimum": 0,
            "description": "How many assessment test masters the hook materialized or validated from the package."
          },
          "responseDeclarationCount": {
            "type": "integer",
            "minimum": 0,
            "description": "How many response declarations the hook materialized or validated from item XML metadata."
          },
          "testItemRefCount": {
            "type": "integer",
            "minimum": 0,
            "description": "How many test-to-item references the hook materialized or validated from test structures."
          },
          "errorCount": {
            "type": "integer",
            "minimum": 0,
            "description": "How many fatal import errors were recorded for this package."
          },
          "quarantineCount": {
            "type": "integer",
            "minimum": 0,
            "description": "How many package records were quarantined instead of coerced or silently overwritten."
          },
          "errorSummary": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string",
                  "minLength": 1,
                  "description": "Stable problem code for the import error."
                },
                "message": {
                  "type": "string",
                  "minLength": 1,
                  "description": "Human-readable summary of the import error."
                },
                "resourceIdentifier": {
                  "type": "string",
                  "minLength": 1,
                  "description": "Manifest resource identifier associated with the error when known."
                }
              },
              "required": [
                "code",
                "message"
              ],
              "additionalProperties": false
            },
            "description": "A bounded list of fatal validation or adapter errors, suitable for status reads. Full diagnostic payloads and remediation workflow are hook-owned."
          },
          "quarantineSummary": {
            "type": "object",
            "description": "Hook-written summary of quarantined identifiers, collision decisions, and source rows that could not be reconciled. The receipt stores the summary only; collision handling and quarantine materialization are hook-owned."
          },
          "completedAt": {
            "type": "string",
            "format": "date-time",
            "description": "The server instant when the import hook completed validation and wrote the receipt.",
            "readOnly": true
          },
          "packageStorageRef": {
            "type": "string",
            "pattern": "^qti/[0-9a-f-]{36}/sha256:[0-9a-f]{64}$",
            "description": "Provenance pointer to the untouched uploaded ZIP object in the content store (tenant-scoped content-addressed key). Null for JSON-envelope imports that never had a binary package."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "id",
          "status",
          "sourceAdapterId",
          "packageHash",
          "manifestHash",
          "manifestMetadata",
          "resourceCount",
          "itemCount",
          "stimulusCount",
          "testCount",
          "responseDeclarationCount",
          "testItemRefCount",
          "errorCount",
          "quarantineCount",
          "completedAt",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "DeliverySession": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The server-minted UUID that identifies this delivery session.",
            "readOnly": true
          },
          "testIdentifier": {
            "type": "object",
            "description": "A OneRoster GUIDRef to a assessmentTest — the referenced resource's sourcedId, its type, and a dereferenceable href. On write, either this object (its sourcedId is used) or the bare sourcedId string is accepted.",
            "required": [
              "sourcedId",
              "type"
            ],
            "properties": {
              "href": {
                "type": "string",
                "description": "The dereferenceable URL of the referenced resource."
              },
              "sourcedId": {
                "type": "string",
                "description": "The sourcedId of the referenced resource."
              },
              "type": {
                "type": "string",
                "const": "assessmentTest",
                "description": "The referenced resource type."
              }
            }
          },
          "candidateRef": {
            "type": "string",
            "format": "uuid",
            "description": "The immutable pseudonymous candidate reference for this session. It is deliberately a UUID and never an OneRoster user FK, SIS id, JWT subject, or directly identifying person value."
          },
          "status": {
            "type": "string",
            "enum": [
              "created",
              "active",
              "suspended",
              "submitted",
              "review",
              "closed",
              "voided"
            ],
            "description": "The runtime session lifecycle state. It is advanced only through `transitionDeliverySession`; these values are distinct from QTI result export `sessionStatus`.",
            "default": "created",
            "readOnly": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "id",
          "testIdentifier",
          "candidateRef",
          "status",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "PackageResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Server-assigned surrogate identifier for the package resource.",
            "readOnly": true
          },
          "resourceIdentifier": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1024,
            "description": "The manifest resource identifier from the QTI package. Stable across re-imports."
          },
          "packageId": {
            "type": "string",
            "format": "uuid",
            "description": "FK to the content package this resource belongs to.",
            "x-references": "contentPackage.id",
            "x-onDelete": "cascade"
          },
          "href": {
            "type": "string",
            "maxLength": 2048,
            "description": "The relative path/href of this resource within the package."
          },
          "resourceType": {
            "type": "string",
            "maxLength": 255,
            "description": "The QTI resource type from the manifest."
          },
          "mediaRole": {
            "type": "string",
            "enum": [
              "primary",
              "supporting",
              "thumbnail",
              "caption",
              "transcript",
              "worksheet",
              "source_file"
            ],
            "description": "Governed media role for Content media_asset projection. Nullable Alpha column on the QTI package_resource master (no companion extension table)."
          },
          "mediaType": {
            "type": "string",
            "pattern": "^[a-z]+/[a-z0-9.+-]+$",
            "minLength": 3,
            "maxLength": 255,
            "description": "Authoritative MIME type for Content media_asset projection. Nullable Alpha column on the QTI package_resource master."
          },
          "deliveryPolicy": {
            "type": "string",
            "enum": [
              "inline",
              "download",
              "stream",
              "external_link"
            ],
            "description": "How the media asset is delivered. Nullable Alpha column on the QTI package_resource master."
          },
          "storageRef": {
            "type": "string",
            "pattern": "^qti/[0-9a-f-]{36}/sha256:[0-9a-f]{64}$",
            "description": "Content-addressed S3 object key for this resource's bytes (`qti/<tenantId>/<contentHash>`). Null when the resource has no bytes in the content store (XML-only or unresolved)."
          },
          "byteSize": {
            "type": "integer",
            "minimum": 0,
            "description": "Byte length of the immutable object at storageRef. Null when storageRef is null."
          },
          "contentHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$",
            "description": "SHA-256 content address of the bytes at storageRef. Must be consistent with storageRef when both are set."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "id",
          "resourceIdentifier",
          "packageId",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "QtiConformanceEvidence": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Stable server-assigned evidence identifier.",
            "readOnly": true
          },
          "profile": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "Conformance profile, normally qti-3.0."
          },
          "bundleHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$",
            "description": "Content address of the conformance bundle used by the runner."
          },
          "runnerVersion": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "Version of the release conformance runner."
          },
          "runStatus": {
            "type": "string",
            "enum": [
              "running",
              "passed",
              "failed",
              "error"
            ],
            "description": "Raw release-runner status. The trust read maps passed to trusted and running to checking."
          },
          "startedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the conformance run began."
          },
          "finishedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the conformance run ended; absent while running."
          },
          "assertionSummary": {
            "type": "object",
            "properties": {
              "passed": {
                "type": "integer",
                "minimum": 0
              },
              "failed": {
                "type": "integer",
                "minimum": 0
              },
              "skipped": {
                "type": "integer",
                "minimum": 0
              },
              "error": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "passed",
              "failed",
              "skipped",
              "error"
            ],
            "description": "Counts of assertion outcomes recorded by release tooling.",
            "additionalProperties": false
          },
          "summary": {
            "type": "object",
            "description": "Optional bounded runner diagnostics."
          },
          "surfaceQcUrl": {
            "type": "string",
            "format": "uri",
            "description": "Published surface-QC evidence for this release."
          }
        },
        "required": [
          "id",
          "profile",
          "bundleHash",
          "runnerVersion",
          "runStatus",
          "startedAt",
          "assertionSummary",
          "surfaceQcUrl"
        ],
        "additionalProperties": false
      },
      "ResponseDeclaration": {
        "type": "object",
        "properties": {
          "itemIdentifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The tenant-scoped QTI identifier of the assessment item that owns this response declaration. The composite foreign key carries the tenant leg through to `assessmentItem.identifier`.",
            "x-references": "assessmentItem.identifier",
            "x-onDelete": "restrict"
          },
          "responseIdentifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The QTI response variable identifier inside the owning item. It follows the QTI NCName shape and is unique within the item for this tenant."
          },
          "baseType": {
            "type": "string",
            "enum": [
              "boolean",
              "directedPair",
              "duration",
              "file",
              "float",
              "identifier",
              "integer",
              "pair",
              "point",
              "string",
              "uri"
            ],
            "description": "The QTI baseType for values carried by this response variable. The closed 11-value XSD vocabulary is enforced at write time."
          },
          "cardinality": {
            "type": "string",
            "enum": [
              "single",
              "multiple",
              "ordered",
              "record"
            ],
            "description": "The QTI cardinality for values carried by this response variable. The closed 4-value XSD vocabulary is enforced at write time."
          },
          "correctResponse": {
            "type": "object",
            "description": "The JSONB representation of the QTI `correctResponse` payload for this declaration. The XML authority and baseType/cardinality-aware decoding remain hook-owned.",
            "additionalProperties": true
          },
          "mapping": {
            "type": "object",
            "description": "The JSONB representation of QTI mapping data, including map entries or default values when present. Response processing semantics remain hook-owned.",
            "additionalProperties": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "itemIdentifier",
          "responseIdentifier",
          "baseType",
          "cardinality",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "ResultExport": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Stable server-assigned identifier for this export receipt. It is not a QTI content identifier and is never a cross-module foreign-key target.",
            "readOnly": true
          },
          "exportKind": {
            "type": "string",
            "enum": [
              "assessmentResult",
              "qtiEntities"
            ],
            "description": "The export door that produced this receipt: `assessmentResult` for `exportAssessmentResult`, or `qtiEntities` for `exportQtiEntities`."
          },
          "status": {
            "type": "string",
            "enum": [
              "succeeded",
              "partial"
            ],
            "description": "The terminal outcome of the synchronous export hook. `succeeded` means the artifact pointer is complete; `partial` means the artifact was produced with bounded errors recorded on the receipt."
          },
          "deliverySessionId": {
            "type": "string",
            "format": "uuid",
            "description": "The delivery session requested for an `assessmentResult` export. The export hook resolves this receipt-captured UUID against the QTI runtime session before writing the receipt, and the field is omitted for tenant-wide bulk entity exports."
          },
          "testIdentifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The QTI assessment test associated with the export when the request targets one test or derives a test from a delivery session. It uses the same tenant-scoped QTI identifier shape as `assessmentTest.identifier`."
          },
          "candidateRef": {
            "type": "string",
            "format": "uuid",
            "description": "The pseudonymous candidate reference associated with an `assessmentResult` export when known. It deliberately remains a UUID value, not an OneRoster user FK."
          },
          "modifiedSince": {
            "type": "string",
            "format": "date-time",
            "description": "The caller-supplied lower freshness bound for a bulk QTI entity export. When omitted, the hook exports the full tenant-visible QTI entity set."
          },
          "runtimeStatus": {
            "type": "string",
            "enum": [
              "created",
              "active",
              "suspended",
              "submitted",
              "review",
              "closed",
              "voided"
            ],
            "description": "The delivery-session runtime status observed by the export hook before mapping to the QTI result-document `sessionStatus` vocabulary."
          },
          "qtiSessionStatus": {
            "type": "string",
            "enum": [
              "final",
              "initial",
              "pendingExternalScoring",
              "pendingResponseProcessing",
              "pendingSubmission"
            ],
            "description": "The QTI result-document `sessionStatus` value produced by the hook-owned runtime-to-QTI mapping for an assessmentResult export."
          },
          "sessionStatusCounts": {
            "type": "object",
            "description": "Bulk-export counts by QTI `sessionStatus` value when `exportQtiEntities` includes delivery or attempt records. The mapping calculation is hook-owned; this field stores the resulting summary."
          },
          "outputHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$",
            "description": "The SHA-256 content address of the canonical export artifact written by the hook. The receipt stores the pointer, not the XML or package bytes."
          },
          "outputRef": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1024,
            "description": "The content-addressed storage reference for the generated export artifact. Binary response transport is not supported yet; clients poll this receipt and dereference through hook-owned storage."
          },
          "outputMediaType": {
            "type": "string",
            "enum": [
              "application/xml",
              "application/json"
            ],
            "description": "The media type of the artifact behind `outputRef`: QTI assessmentResult XML for session exports, or a JSON-envelope bulk entity export for supported bulk exports."
          },
          "outputByteLength": {
            "type": "integer",
            "minimum": 0,
            "description": "The byte length of the generated artifact stored behind `outputRef`, recorded for audit and client preflight without returning bytes inline."
          },
          "itemCount": {
            "type": "integer",
            "minimum": 0,
            "description": "How many assessment item records or item-result entries the export artifact contains."
          },
          "stimulusCount": {
            "type": "integer",
            "minimum": 0,
            "description": "How many assessment stimulus records the export artifact contains."
          },
          "testCount": {
            "type": "integer",
            "minimum": 0,
            "description": "How many assessment test records or test-result sections the export artifact contains."
          },
          "responseDeclarationCount": {
            "type": "integer",
            "minimum": 0,
            "description": "How many response declarations the export artifact contains or used while producing assessment result output."
          },
          "testItemRefCount": {
            "type": "integer",
            "minimum": 0,
            "description": "How many test-to-item references the export artifact contains or used while producing assessment result output."
          },
          "deliverySessionCount": {
            "type": "integer",
            "minimum": 0,
            "description": "How many delivery sessions the export artifact contains or summarizes."
          },
          "attemptCount": {
            "type": "integer",
            "minimum": 0,
            "description": "How many item attempts the export artifact contains or summarizes."
          },
          "assessmentResultCount": {
            "type": "integer",
            "minimum": 0,
            "description": "How many QTI assessmentResult documents the export produced. A single-session `exportAssessmentResult` normally records one."
          },
          "errorCount": {
            "type": "integer",
            "minimum": 0,
            "description": "How many bounded export errors were recorded on this receipt. Fatal validation failures reject the command instead of creating a successful receipt."
          },
          "errorSummary": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string",
                  "minLength": 1,
                  "description": "Stable problem code for the export error."
                },
                "message": {
                  "type": "string",
                  "minLength": 1,
                  "description": "Human-readable summary of the export error."
                },
                "entityKind": {
                  "type": "string",
                  "minLength": 1,
                  "description": "The QTI entity kind associated with the error when known."
                },
                "entityIdentifier": {
                  "type": "string",
                  "minLength": 1,
                  "description": "The QTI entity identifier associated with the error when known."
                }
              },
              "required": [
                "code",
                "message"
              ],
              "additionalProperties": false
            },
            "description": "A bounded list of export errors suitable for status reads. Full artifact assembly diagnostics remain hook-owned."
          },
          "requestedAt": {
            "type": "string",
            "format": "date-time",
            "description": "The server instant when the export command was accepted by the hook.",
            "readOnly": true
          },
          "completedAt": {
            "type": "string",
            "format": "date-time",
            "description": "The server instant when the export hook completed artifact assembly and wrote the receipt.",
            "readOnly": true
          },
          "freshnessCutoff": {
            "type": "string",
            "format": "date-time",
            "description": "The export watermark: records with managed response timestamps at or before this instant are represented by the artifact, subject to the request scope.",
            "readOnly": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "id",
          "exportKind",
          "status",
          "outputHash",
          "outputRef",
          "outputMediaType",
          "outputByteLength",
          "itemCount",
          "stimulusCount",
          "testCount",
          "responseDeclarationCount",
          "testItemRefCount",
          "deliverySessionCount",
          "attemptCount",
          "assessmentResultCount",
          "errorCount",
          "requestedAt",
          "completedAt",
          "freshnessCutoff",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "TestItemRef": {
        "type": "object",
        "properties": {
          "testIdentifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The QTI assessment test that owns this item placement. Same-tenant composite FK to `assessmentTest.identifier`.",
            "x-references": "assessmentTest.identifier",
            "x-onDelete": "soft-cascade"
          },
          "itemIdentifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The QTI assessment item placed in the test. Same-tenant composite FK to `assessmentItem.identifier`.",
            "x-references": "assessmentItem.identifier",
            "x-onDelete": "restrict"
          },
          "ordinal": {
            "type": "integer",
            "minimum": 1,
            "description": "The one-based presentation order of this item reference within its test structure."
          },
          "sectionIdentifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The QTI assessment section identifier that contains this item reference inside the test XML."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed row-creation timestamp (RFC 3339). Read-only — never accepted on create or update."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-managed last-update timestamp (RFC 3339). Read-only — never accepted on create or update."
          }
        },
        "required": [
          "testIdentifier",
          "itemIdentifier",
          "ordinal",
          "sectionIdentifier",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": false
      },
      "CreateArtifactRequest": {
        "type": "object",
        "description": "Create-Artifact request body (readOnly/server-managed fields excluded).",
        "required": [
          "title",
          "language",
          "qtiIdentifier"
        ],
        "additionalProperties": false,
        "properties": {
          "artifactKind": {
            "type": "string",
            "enum": [
              "item",
              "test",
              "section",
              "stimulus",
              "outcome-declaration",
              "response-processing",
              "result",
              "usage-data",
              "metadata",
              "manifest-resource"
            ],
            "description": "The open QTI artifact kind vocabulary. Content projections restrict this to the public subset."
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "The artifact title."
          },
          "language": {
            "type": "string",
            "pattern": "^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$",
            "minLength": 2,
            "maxLength": 35,
            "description": "BCP 47 language tag for the artifact."
          },
          "qtiIdentifier": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The original QTI identifier from the source package."
          },
          "latestVersionId": {
            "type": "string",
            "format": "uuid",
            "description": "The id of the most recent artifact version."
          },
          "packageId": {
            "type": "string",
            "format": "uuid",
            "description": "The content package this artifact was imported from."
          },
          "resourceId": {
            "type": "string",
            "format": "uuid",
            "description": "The package resource this artifact corresponds to."
          },
          "contentKind": {
            "type": "string",
            "enum": [
              "question",
              "test",
              "test_spec",
              "test_bank",
              "article",
              "video",
              "audio",
              "image",
              "interactive",
              "media_asset",
              "external_link",
              "script",
              "stimulus"
            ],
            "description": "Alpha content kind. Nullable on the QTI union master; Content projection/hooks enforce write requiredness. Includes Incept `stimulus` as a public contentKind home (artifactKind provenance remains `stimulus`)."
          },
          "phonicsSet": {
            "type": "object",
            "description": "Decodable phonics constraint set (module-content extends.phonics_set jsonb; public API camelCase phonicsSet). Nullable Alpha column on the union master; Content hooks guard writes to subtype=decodable.",
            "additionalProperties": true
          },
          "subtype": {
            "type": "string",
            "enum": [
              "diagram",
              "decodable",
              "script"
            ],
            "description": "Governed content subtype for specialized content variants. Nullable Alpha column on the union master."
          },
          "sourceSystem": {
            "type": "string",
            "enum": [
              "qti",
              "alpha_content",
              "external_content_import"
            ],
            "description": "Originating system that produced this content. Nullable Alpha column on the union master."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published",
              "retired",
              "archived"
            ],
            "description": "Content lifecycle status. Nullable Alpha column on the union master; Content hooks enforce write requiredness."
          },
          "subjectId": {
            "type": "string",
            "enum": [
              "math",
              "reading",
              "language",
              "science",
              "vocabulary",
              "writing"
            ],
            "description": "Canonical subject id. Nullable Alpha column on the union master."
          },
          "targetGradeId": {
            "type": "string",
            "enum": [
              "pre_k",
              "k",
              "1",
              "2",
              "3",
              "4",
              "5",
              "6",
              "7",
              "8",
              "9",
              "10",
              "11",
              "12",
              "postsecondary",
              "ungraded"
            ],
            "description": "Target grade (alpha_grade_id). Nullable Alpha column on the union master."
          },
          "dok": {
            "type": "string",
            "enum": [
              "dok1",
              "dok2",
              "dok3",
              "dok4"
            ],
            "description": "Webb Depth of Knowledge. Nullable Alpha column on the union master."
          },
          "expectedXp": {
            "type": "integer",
            "minimum": 0,
            "description": "Student-independent expected XP config. Nullable Alpha column on the union master."
          },
          "subjectFamily": {
            "type": "string",
            "description": "proxy classification (map vs proxy) as metadata. Optional Alpha column on the union master."
          },
          "externalUrl": {
            "type": "string",
            "format": "uri",
            "pattern": "^https?://",
            "description": "Canonical http(s) destination for external-link content. Nullable Alpha column on the union master."
          },
          "displayUrl": {
            "type": "string",
            "maxLength": 512,
            "description": "Safe author-facing display label for the external URL. Nullable Alpha column on the union master."
          },
          "openPolicy": {
            "type": "string",
            "enum": [
              "same_tab",
              "new_tab",
              "embedded_iframe_allowed",
              "external_app_handoff"
            ],
            "description": "Governed client navigation policy for external-link content. Nullable Alpha column on the union master.",
            "default": "new_tab"
          },
          "externalLinkLastValidatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Most recent external destination validation timestamp. Nullable Alpha column on the union master."
          }
        }
      },
      "UpdateArtifactRequest": {
        "type": "object",
        "description": "Update-Artifact request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "The artifact title."
          },
          "language": {
            "type": "string",
            "pattern": "^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$",
            "minLength": 2,
            "maxLength": 35,
            "description": "BCP 47 language tag for the artifact."
          },
          "latestVersionId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The id of the most recent artifact version."
          },
          "packageId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The content package this artifact was imported from."
          },
          "resourceId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The package resource this artifact corresponds to."
          },
          "contentKind": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "question",
              "test",
              "test_spec",
              "test_bank",
              "article",
              "video",
              "audio",
              "image",
              "interactive",
              "media_asset",
              "external_link",
              "script",
              "stimulus",
              null
            ],
            "description": "Alpha content kind. Nullable on the QTI union master; Content projection/hooks enforce write requiredness. Includes Incept `stimulus` as a public contentKind home (artifactKind provenance remains `stimulus`)."
          },
          "phonicsSet": {
            "type": [
              "object",
              "null"
            ],
            "description": "Decodable phonics constraint set (module-content extends.phonics_set jsonb; public API camelCase phonicsSet). Nullable Alpha column on the union master; Content hooks guard writes to subtype=decodable.",
            "additionalProperties": true
          },
          "subtype": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "diagram",
              "decodable",
              "script",
              null
            ],
            "description": "Governed content subtype for specialized content variants. Nullable Alpha column on the union master."
          },
          "sourceSystem": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "qti",
              "alpha_content",
              "external_content_import",
              null
            ],
            "description": "Originating system that produced this content. Nullable Alpha column on the union master."
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "draft",
              "published",
              "retired",
              "archived",
              null
            ],
            "description": "Content lifecycle status. Nullable Alpha column on the union master; Content hooks enforce write requiredness."
          },
          "subjectId": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "math",
              "reading",
              "language",
              "science",
              "vocabulary",
              "writing",
              null
            ],
            "description": "Canonical subject id. Nullable Alpha column on the union master."
          },
          "targetGradeId": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "pre_k",
              "k",
              "1",
              "2",
              "3",
              "4",
              "5",
              "6",
              "7",
              "8",
              "9",
              "10",
              "11",
              "12",
              "postsecondary",
              "ungraded",
              null
            ],
            "description": "Target grade (alpha_grade_id). Nullable Alpha column on the union master."
          },
          "dok": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "dok1",
              "dok2",
              "dok3",
              "dok4",
              null
            ],
            "description": "Webb Depth of Knowledge. Nullable Alpha column on the union master."
          },
          "expectedXp": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Student-independent expected XP config. Nullable Alpha column on the union master."
          },
          "subjectFamily": {
            "type": [
              "string",
              "null"
            ],
            "description": "proxy classification (map vs proxy) as metadata. Optional Alpha column on the union master."
          },
          "externalUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "pattern": "^https?://",
            "description": "Canonical http(s) destination for external-link content. Nullable Alpha column on the union master."
          },
          "displayUrl": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 512,
            "description": "Safe author-facing display label for the external URL. Nullable Alpha column on the union master."
          },
          "openPolicy": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "same_tab",
              "new_tab",
              "embedded_iframe_allowed",
              "external_app_handoff",
              null
            ],
            "description": "Governed client navigation policy for external-link content. Nullable Alpha column on the union master.",
            "default": "new_tab"
          },
          "externalLinkLastValidatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Most recent external destination validation timestamp. Nullable Alpha column on the union master."
          }
        }
      },
      "CreateArtifactVersionRequest": {
        "type": "object",
        "description": "Create-ArtifactVersion request body (readOnly/server-managed fields excluded).",
        "required": [
          "versionNumber",
          "xmlHash",
          "createdBy"
        ],
        "additionalProperties": false,
        "properties": {
          "versionNumber": {
            "type": "integer",
            "minimum": 1,
            "description": "Monotonically increasing version number within the parent artifact."
          },
          "xmlHash": {
            "type": "string",
            "minLength": 32,
            "maxLength": 64,
            "description": "Content hash of the canonical XML for this version. Part of the dedup unique constraint."
          },
          "sourceXml": {
            "type": "string",
            "description": "The original source XML as imported."
          },
          "canonicalXml": {
            "type": "string",
            "description": "The canonicalized XML form for deterministic comparison."
          },
          "objectGraph": {
            "type": "object",
            "description": "The shredded object graph representation of the QTI XML.",
            "additionalProperties": true
          },
          "authoringJson": {
            "type": "object",
            "description": "The authoring-surface JSON representation.",
            "additionalProperties": true
          },
          "deliveryBody": {
            "type": "string",
            "description": "The rendered delivery HTML body derived from the QTI XML for the delivery surface."
          },
          "specTrace": {
            "type": "string",
            "description": "QTI specification traceability metadata."
          },
          "supersedesVersionId": {
            "type": "string",
            "format": "uuid",
            "description": "Self-FK to the previous version this one supersedes. NULL for the first version.",
            "x-references": "artifactVersion.id",
            "x-onDelete": "restrict"
          },
          "createdBy": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The authenticated principal who authored this version."
          },
          "artifactId": {
            "type": "string",
            "format": "uuid",
            "description": "FK to the parent artifact.",
            "x-references": "artifact.id",
            "x-onDelete": "cascade"
          }
        }
      },
      "CreateAssessmentItemRequest": {
        "type": "object",
        "description": "Create-AssessmentItem request body (readOnly/server-managed fields excluded).",
        "required": [
          "identifier",
          "title",
          "interactionType",
          "xmlHash"
        ],
        "additionalProperties": false,
        "properties": {
          "identifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The product-canonical QTI item identifier. It is assigned at import or authoring time, follows the QTI NCName shape, and is unique within a tenant."
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "The item title used by authors and item-bank workflows to browse, select, and reuse this item."
          },
          "interactionType": {
            "type": "string",
            "enum": [
              "choiceInteraction",
              "orderInteraction",
              "associateInteraction",
              "matchInteraction",
              "gapMatchInteraction",
              "textEntryInteraction",
              "extendedTextInteraction",
              "inlineChoiceInteraction",
              "hottextInteraction",
              "hotspotInteraction",
              "selectPointInteraction",
              "graphicOrderInteraction",
              "graphicAssociateInteraction",
              "graphicGapMatchInteraction",
              "positionObjectInteraction",
              "sliderInteraction",
              "uploadInteraction",
              "drawingInteraction",
              "mediaInteraction",
              "endAttemptInteraction",
              "portableCustomInteraction",
              "customInteraction"
            ],
            "description": "The primary QTI interaction family for the item. The value is the closed 22-value QTI interaction vocabulary and is validated at write time."
          },
          "xmlHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$",
            "description": "The SHA-256 content address of the canonical QTI item XML. The XML bytes and shred graph are hook-owned; this field is the stable authority pointer."
          },
          "language": {
            "type": "string",
            "pattern": "^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$",
            "minLength": 2,
            "maxLength": 35,
            "description": "The main language of the item as a BCP 47 language tag when known."
          },
          "responseProcessing": {
            "type": "object",
            "description": "The item's declared response-processing spec, projected from the canonical QTI XML at import/authoring time: spec version, standard template name or normalized inline rules, and normalized outcome declarations. Absent or unparseable processing MUST be represented explicitly (template \"none\" / \"unsupported\") — a null field fails closed at submit. Execution semantics are hook-owned. Canonical shape is validated by the shared hook-owned parser (specVersion, template, outcomes, rules, unsupportedReason).",
            "additionalProperties": true
          }
        }
      },
      "UpdateAssessmentItemRequest": {
        "type": "object",
        "description": "Update-AssessmentItem request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "The item title used by authors and item-bank workflows to browse, select, and reuse this item."
          },
          "interactionType": {
            "type": "string",
            "enum": [
              "choiceInteraction",
              "orderInteraction",
              "associateInteraction",
              "matchInteraction",
              "gapMatchInteraction",
              "textEntryInteraction",
              "extendedTextInteraction",
              "inlineChoiceInteraction",
              "hottextInteraction",
              "hotspotInteraction",
              "selectPointInteraction",
              "graphicOrderInteraction",
              "graphicAssociateInteraction",
              "graphicGapMatchInteraction",
              "positionObjectInteraction",
              "sliderInteraction",
              "uploadInteraction",
              "drawingInteraction",
              "mediaInteraction",
              "endAttemptInteraction",
              "portableCustomInteraction",
              "customInteraction"
            ],
            "description": "The primary QTI interaction family for the item. The value is the closed 22-value QTI interaction vocabulary and is validated at write time."
          },
          "xmlHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$",
            "description": "The SHA-256 content address of the canonical QTI item XML. The XML bytes and shred graph are hook-owned; this field is the stable authority pointer."
          },
          "language": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$",
            "minLength": 2,
            "maxLength": 35,
            "description": "The main language of the item as a BCP 47 language tag when known."
          },
          "responseProcessing": {
            "type": [
              "object",
              "null"
            ],
            "description": "The item's declared response-processing spec, projected from the canonical QTI XML at import/authoring time: spec version, standard template name or normalized inline rules, and normalized outcome declarations. Absent or unparseable processing MUST be represented explicitly (template \"none\" / \"unsupported\") — a null field fails closed at submit. Execution semantics are hook-owned. Canonical shape is validated by the shared hook-owned parser (specVersion, template, outcomes, rules, unsupportedReason).",
            "additionalProperties": true
          }
        }
      },
      "CreateAssessmentStimulusRequest": {
        "type": "object",
        "description": "Create-AssessmentStimulus request body (readOnly/server-managed fields excluded).",
        "required": [
          "identifier",
          "title",
          "xmlHash"
        ],
        "additionalProperties": false,
        "properties": {
          "identifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The product-canonical QTI stimulus identifier. It is assigned at import or authoring time, follows the QTI NCName shape, and is unique within a tenant."
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "The stimulus title used by authors and content workflows to browse, select, and reuse this shared context."
          },
          "xmlHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$",
            "description": "The SHA-256 content address of the canonical QTI stimulus XML. The XML bytes and any shred graph are hook-owned; this field is the stable authority pointer."
          },
          "language": {
            "type": "string",
            "pattern": "^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$",
            "minLength": 2,
            "maxLength": 35,
            "description": "The main language of the stimulus as a BCP 47 language tag when known."
          }
        }
      },
      "UpdateAssessmentStimulusRequest": {
        "type": "object",
        "description": "Update-AssessmentStimulus request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "The stimulus title used by authors and content workflows to browse, select, and reuse this shared context."
          },
          "xmlHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$",
            "description": "The SHA-256 content address of the canonical QTI stimulus XML. The XML bytes and any shred graph are hook-owned; this field is the stable authority pointer."
          },
          "language": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$",
            "minLength": 2,
            "maxLength": 35,
            "description": "The main language of the stimulus as a BCP 47 language tag when known."
          }
        }
      },
      "CreateAssessmentTestRequest": {
        "type": "object",
        "description": "Create-AssessmentTest request body (readOnly/server-managed fields excluded).",
        "required": [
          "identifier",
          "title",
          "navigationMode",
          "submissionMode",
          "xmlHash"
        ],
        "additionalProperties": false,
        "properties": {
          "identifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The product-canonical QTI test identifier. It is assigned at import or authoring time, follows the QTI NCName shape, and is unique within a tenant."
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "The test title used by authors and assessment workflows to browse, assemble, and deliver this assessment test."
          },
          "navigationMode": {
            "type": "string",
            "enum": [
              "linear",
              "nonlinear"
            ],
            "description": "The QTI navigation mode for the test. `linear` requires candidates to proceed in sequence; `nonlinear` permits non-sequential navigation."
          },
          "submissionMode": {
            "type": "string",
            "enum": [
              "individual",
              "simultaneous"
            ],
            "description": "The QTI submission mode for the test. `individual` submits item responses as separate response transactions; `simultaneous` submits the test's responses together."
          },
          "xmlHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$",
            "description": "The SHA-256 content address of the canonical QTI test XML. The XML bytes and any structural shred are hook-owned; this field is the stable authority pointer."
          },
          "isMasteryGate": {
            "type": "boolean",
            "description": "Typed structural fact: whether this test is a mastery gate. Nullable Alpha column on the QTI assessment_test master."
          },
          "testType": {
            "type": "string",
            "enum": [
              "end_of_course",
              "end_of_grade",
              "test_out",
              "placement",
              "diagnostic",
              "screener"
            ],
            "description": "Alpha test-type vocabulary. Nullable Alpha column on the QTI assessment_test master."
          },
          "assessmentRole": {
            "type": "string",
            "enum": [
              "form",
              "spec",
              "bank"
            ],
            "description": "Assessment role: form, blueprint spec overlay, or bank overlay. Nullable Alpha column on the QTI assessment_test master."
          }
        }
      },
      "UpdateAssessmentTestRequest": {
        "type": "object",
        "description": "Update-AssessmentTest request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "The test title used by authors and assessment workflows to browse, assemble, and deliver this assessment test."
          },
          "navigationMode": {
            "type": "string",
            "enum": [
              "linear",
              "nonlinear"
            ],
            "description": "The QTI navigation mode for the test. `linear` requires candidates to proceed in sequence; `nonlinear` permits non-sequential navigation."
          },
          "submissionMode": {
            "type": "string",
            "enum": [
              "individual",
              "simultaneous"
            ],
            "description": "The QTI submission mode for the test. `individual` submits item responses as separate response transactions; `simultaneous` submits the test's responses together."
          },
          "xmlHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$",
            "description": "The SHA-256 content address of the canonical QTI test XML. The XML bytes and any structural shred are hook-owned; this field is the stable authority pointer."
          },
          "isMasteryGate": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Typed structural fact: whether this test is a mastery gate. Nullable Alpha column on the QTI assessment_test master."
          },
          "testType": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "end_of_course",
              "end_of_grade",
              "test_out",
              "placement",
              "diagnostic",
              "screener",
              null
            ],
            "description": "Alpha test-type vocabulary. Nullable Alpha column on the QTI assessment_test master."
          },
          "assessmentRole": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "form",
              "spec",
              "bank",
              null
            ],
            "description": "Assessment role: form, blueprint spec overlay, or bank overlay. Nullable Alpha column on the QTI assessment_test master."
          }
        }
      },
      "CreateAttemptRequest": {
        "type": "object",
        "description": "Create-Attempt request body (readOnly/server-managed fields excluded).",
        "required": [
          "deliverySessionId",
          "itemIdentifier",
          "attemptNumber",
          "status"
        ],
        "additionalProperties": false,
        "properties": {
          "deliverySessionId": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "object",
                "description": "A OneRoster GUIDRef to a deliverySession — the referenced resource's sourcedId, its type, and a dereferenceable href. On write, either this object (its sourcedId is used) or the bare sourcedId string is accepted.",
                "required": [
                  "sourcedId",
                  "type"
                ],
                "properties": {
                  "href": {
                    "type": "string",
                    "description": "The dereferenceable URL of the referenced resource."
                  },
                  "sourcedId": {
                    "type": "string",
                    "description": "The sourcedId of the referenced resource."
                  },
                  "type": {
                    "type": "string",
                    "const": "deliverySession",
                    "description": "The referenced resource type."
                  }
                }
              }
            ],
            "description": "A OneRoster GUIDRef to a deliverySession, or the bare sourcedId string — both write the scalar deliverySessionId."
          },
          "itemIdentifier": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "object",
                "description": "A OneRoster GUIDRef to a assessmentItem — the referenced resource's sourcedId, its type, and a dereferenceable href. On write, either this object (its sourcedId is used) or the bare sourcedId string is accepted.",
                "required": [
                  "sourcedId",
                  "type"
                ],
                "properties": {
                  "href": {
                    "type": "string",
                    "description": "The dereferenceable URL of the referenced resource."
                  },
                  "sourcedId": {
                    "type": "string",
                    "description": "The sourcedId of the referenced resource."
                  },
                  "type": {
                    "type": "string",
                    "const": "assessmentItem",
                    "description": "The referenced resource type."
                  }
                }
              }
            ],
            "description": "A OneRoster GUIDRef to a assessmentItem, or the bare sourcedId string — both write the scalar itemIdentifier."
          },
          "attemptNumber": {
            "type": "integer",
            "minimum": 1,
            "description": "The one-based sequence number for this candidate's attempts at the item within the delivery session."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "submitted",
              "reviewed",
              "voided"
            ],
            "description": "The closed runtime status enum for an item attempt. `active` means responses may still change; `submitted` means responses reached the submit hook; `reviewed` means scoring or review finished; `voided` means the attempt must not count.",
            "default": "active"
          }
        }
      },
      "CreateComponentRequest": {
        "type": "object",
        "description": "Create-Component request body (readOnly/server-managed fields excluded).",
        "required": [
          "elementName",
          "ordinal"
        ],
        "additionalProperties": false,
        "properties": {
          "parentComponentId": {
            "type": "string",
            "format": "uuid",
            "description": "Self-referencing FK to the parent component in the tree. NULL for root-level components (tests).",
            "x-references": "component.id",
            "x-onDelete": "cascade"
          },
          "elementName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The QTI XML element name (assessmentTest, testPart, assessmentSection, assessmentItemRef, etc.)."
          },
          "typeName": {
            "type": "string",
            "maxLength": 255,
            "description": "The QTI type name when the element carries an explicit xsi:type. Used for disambiguation when element_name alone is insufficient."
          },
          "ordinal": {
            "type": "integer",
            "minimum": 0,
            "description": "Position of this component among its siblings within the parent. Preserves document order."
          },
          "attributes": {
            "type": "object",
            "description": "The QTI XML attributes on this element as a JSON object.",
            "additionalProperties": true
          },
          "sourceTrace": {
            "type": "string",
            "description": "Import source traceability metadata."
          },
          "namespaceUri": {
            "type": "string",
            "maxLength": 512,
            "description": "The XML namespace URI for this element."
          },
          "qualifiedName": {
            "type": "string",
            "maxLength": 512,
            "description": "The fully qualified XML element name."
          },
          "artifactVersionId": {
            "type": "string",
            "format": "uuid",
            "description": "FK to the artifact version this component belongs to.",
            "x-references": "artifactVersion.id",
            "x-onDelete": "cascade"
          }
        }
      },
      "CreateDeliverySessionRequest": {
        "type": "object",
        "description": "Create-DeliverySession request body (readOnly/server-managed fields excluded).",
        "required": [
          "testIdentifier",
          "candidateRef"
        ],
        "additionalProperties": false,
        "properties": {
          "testIdentifier": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "object",
                "description": "A OneRoster GUIDRef to a assessmentTest — the referenced resource's sourcedId, its type, and a dereferenceable href. On write, either this object (its sourcedId is used) or the bare sourcedId string is accepted.",
                "required": [
                  "sourcedId",
                  "type"
                ],
                "properties": {
                  "href": {
                    "type": "string",
                    "description": "The dereferenceable URL of the referenced resource."
                  },
                  "sourcedId": {
                    "type": "string",
                    "description": "The sourcedId of the referenced resource."
                  },
                  "type": {
                    "type": "string",
                    "const": "assessmentTest",
                    "description": "The referenced resource type."
                  }
                }
              }
            ],
            "description": "A OneRoster GUIDRef to a assessmentTest, or the bare sourcedId string — both write the scalar testIdentifier."
          },
          "candidateRef": {
            "type": "string",
            "format": "uuid",
            "description": "The immutable pseudonymous candidate reference for this session. It is deliberately a UUID and never an OneRoster user FK, SIS id, JWT subject, or directly identifying person value."
          }
        }
      },
      "CreatePackageResourceRequest": {
        "type": "object",
        "description": "Create-PackageResource request body (readOnly/server-managed fields excluded).",
        "required": [
          "resourceIdentifier",
          "packageId"
        ],
        "additionalProperties": false,
        "properties": {
          "resourceIdentifier": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1024,
            "description": "The manifest resource identifier from the QTI package. Stable across re-imports."
          },
          "packageId": {
            "type": "string",
            "format": "uuid",
            "description": "FK to the content package this resource belongs to.",
            "x-references": "contentPackage.id",
            "x-onDelete": "cascade"
          },
          "href": {
            "type": "string",
            "maxLength": 2048,
            "description": "The relative path/href of this resource within the package."
          },
          "resourceType": {
            "type": "string",
            "maxLength": 255,
            "description": "The QTI resource type from the manifest."
          },
          "mediaRole": {
            "type": "string",
            "enum": [
              "primary",
              "supporting",
              "thumbnail",
              "caption",
              "transcript",
              "worksheet",
              "source_file"
            ],
            "description": "Governed media role for Content media_asset projection. Nullable Alpha column on the QTI package_resource master (no companion extension table)."
          },
          "mediaType": {
            "type": "string",
            "pattern": "^[a-z]+/[a-z0-9.+-]+$",
            "minLength": 3,
            "maxLength": 255,
            "description": "Authoritative MIME type for Content media_asset projection. Nullable Alpha column on the QTI package_resource master."
          },
          "deliveryPolicy": {
            "type": "string",
            "enum": [
              "inline",
              "download",
              "stream",
              "external_link"
            ],
            "description": "How the media asset is delivered. Nullable Alpha column on the QTI package_resource master."
          },
          "storageRef": {
            "type": "string",
            "pattern": "^qti/[0-9a-f-]{36}/sha256:[0-9a-f]{64}$",
            "description": "Content-addressed S3 object key for this resource's bytes (`qti/<tenantId>/<contentHash>`). Null when the resource has no bytes in the content store (XML-only or unresolved)."
          },
          "byteSize": {
            "type": "integer",
            "minimum": 0,
            "description": "Byte length of the immutable object at storageRef. Null when storageRef is null."
          },
          "contentHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$",
            "description": "SHA-256 content address of the bytes at storageRef. Must be consistent with storageRef when both are set."
          }
        }
      },
      "CreateQtiConformanceEvidenceRequest": {
        "type": "object",
        "description": "Create-QtiConformanceEvidence request body (readOnly/server-managed fields excluded).",
        "required": [
          "profile",
          "bundleHash",
          "runnerVersion",
          "runStatus",
          "startedAt",
          "assertionSummary",
          "surfaceQcUrl"
        ],
        "additionalProperties": false,
        "properties": {
          "profile": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "Conformance profile, normally qti-3.0."
          },
          "bundleHash": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$",
            "description": "Content address of the conformance bundle used by the runner."
          },
          "runnerVersion": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "Version of the release conformance runner."
          },
          "runStatus": {
            "type": "string",
            "enum": [
              "running",
              "passed",
              "failed",
              "error"
            ],
            "description": "Raw release-runner status. The trust read maps passed to trusted and running to checking."
          },
          "startedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the conformance run began."
          },
          "finishedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the conformance run ended; absent while running."
          },
          "assertionSummary": {
            "type": "object",
            "properties": {
              "passed": {
                "type": "integer",
                "minimum": 0
              },
              "failed": {
                "type": "integer",
                "minimum": 0
              },
              "skipped": {
                "type": "integer",
                "minimum": 0
              },
              "error": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "passed",
              "failed",
              "skipped",
              "error"
            ],
            "description": "Counts of assertion outcomes recorded by release tooling.",
            "additionalProperties": false
          },
          "summary": {
            "type": "object",
            "description": "Optional bounded runner diagnostics."
          },
          "surfaceQcUrl": {
            "type": "string",
            "format": "uri",
            "description": "Published surface-QC evidence for this release."
          }
        }
      },
      "CreateResponseDeclarationRequest": {
        "type": "object",
        "description": "Create-ResponseDeclaration request body (readOnly/server-managed fields excluded).",
        "required": [
          "itemIdentifier",
          "responseIdentifier",
          "baseType",
          "cardinality"
        ],
        "additionalProperties": false,
        "properties": {
          "itemIdentifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The tenant-scoped QTI identifier of the assessment item that owns this response declaration. The composite foreign key carries the tenant leg through to `assessmentItem.identifier`.",
            "x-references": "assessmentItem.identifier",
            "x-onDelete": "restrict"
          },
          "responseIdentifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The QTI response variable identifier inside the owning item. It follows the QTI NCName shape and is unique within the item for this tenant."
          },
          "baseType": {
            "type": "string",
            "enum": [
              "boolean",
              "directedPair",
              "duration",
              "file",
              "float",
              "identifier",
              "integer",
              "pair",
              "point",
              "string",
              "uri"
            ],
            "description": "The QTI baseType for values carried by this response variable. The closed 11-value XSD vocabulary is enforced at write time."
          },
          "cardinality": {
            "type": "string",
            "enum": [
              "single",
              "multiple",
              "ordered",
              "record"
            ],
            "description": "The QTI cardinality for values carried by this response variable. The closed 4-value XSD vocabulary is enforced at write time."
          },
          "correctResponse": {
            "type": "object",
            "description": "The JSONB representation of the QTI `correctResponse` payload for this declaration. The XML authority and baseType/cardinality-aware decoding remain hook-owned.",
            "additionalProperties": true
          },
          "mapping": {
            "type": "object",
            "description": "The JSONB representation of QTI mapping data, including map entries or default values when present. Response processing semantics remain hook-owned.",
            "additionalProperties": true
          }
        }
      },
      "UpdateResponseDeclarationRequest": {
        "type": "object",
        "description": "Update-ResponseDeclaration request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "baseType": {
            "type": "string",
            "enum": [
              "boolean",
              "directedPair",
              "duration",
              "file",
              "float",
              "identifier",
              "integer",
              "pair",
              "point",
              "string",
              "uri"
            ],
            "description": "The QTI baseType for values carried by this response variable. The closed 11-value XSD vocabulary is enforced at write time."
          },
          "cardinality": {
            "type": "string",
            "enum": [
              "single",
              "multiple",
              "ordered",
              "record"
            ],
            "description": "The QTI cardinality for values carried by this response variable. The closed 4-value XSD vocabulary is enforced at write time."
          },
          "correctResponse": {
            "type": [
              "object",
              "null"
            ],
            "description": "The JSONB representation of the QTI `correctResponse` payload for this declaration. The XML authority and baseType/cardinality-aware decoding remain hook-owned.",
            "additionalProperties": true
          },
          "mapping": {
            "type": [
              "object",
              "null"
            ],
            "description": "The JSONB representation of QTI mapping data, including map entries or default values when present. Response processing semantics remain hook-owned.",
            "additionalProperties": true
          }
        }
      },
      "CreateTestItemRefRequest": {
        "type": "object",
        "description": "Create-TestItemRef request body (readOnly/server-managed fields excluded).",
        "required": [
          "testIdentifier",
          "itemIdentifier",
          "ordinal",
          "sectionIdentifier"
        ],
        "additionalProperties": false,
        "properties": {
          "testIdentifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The QTI assessment test that owns this item placement. Same-tenant composite FK to `assessmentTest.identifier`.",
            "x-references": "assessmentTest.identifier",
            "x-onDelete": "soft-cascade"
          },
          "itemIdentifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The QTI assessment item placed in the test. Same-tenant composite FK to `assessmentItem.identifier`.",
            "x-references": "assessmentItem.identifier",
            "x-onDelete": "restrict"
          },
          "ordinal": {
            "type": "integer",
            "minimum": 1,
            "description": "The one-based presentation order of this item reference within its test structure."
          },
          "sectionIdentifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The QTI assessment section identifier that contains this item reference inside the test XML."
          }
        }
      },
      "UpdateTestItemRefRequest": {
        "type": "object",
        "description": "Update-TestItemRef request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "ordinal": {
            "type": "integer",
            "minimum": 1,
            "description": "The one-based presentation order of this item reference within its test structure."
          },
          "sectionIdentifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The QTI assessment section identifier that contains this item reference inside the test XML."
          }
        }
      },
      "Problem": {
        "type": "object",
        "description": "RFC 7807 problem details.",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "A URI identifying the problem type."
          },
          "title": {
            "type": "string",
            "description": "A short, human-readable summary of the problem."
          },
          "status": {
            "type": "integer",
            "description": "The HTTP status code."
          },
          "detail": {
            "type": "string",
            "description": "A human-readable explanation specific to this occurrence."
          },
          "instance": {
            "type": "string",
            "format": "uri",
            "description": "A URI identifying this occurrence."
          }
        },
        "required": [
          "title",
          "status"
        ]
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    }
  },
  "servers": [
    {
      "url": "https://qti.platform4.alphaschool.dev"
    }
  ]
}
