{
  "openapi": "3.1.0",
  "info": {
    "title": "Content",
    "description": "The Alpha Content API presents school-language views of QTI assessment artifacts with Alpha-owned fields for subject, grade, depth of knowledge, and expected XP. It includes test specifications and banks for blueprint and form structure, plus import/export commands with receipts. Restricted artifact kinds and archived items are excluded from default reads.",
    "version": "1.0"
  },
  "tags": [
    {
      "name": "Answer Key",
      "description": "The correct-response and scoring data for a content item, projected from the QTI response declaration (processingRule). Sensitive data: correct-value fields are gated by fieldRedaction — a reader without read:answer_key permission sees the answer slot structure but the correct-value fields are redacted, not a 403 on the whole endpoint."
    },
    {
      "name": "Answer Slot",
      "description": "The blank answer structure for a content item: a projection of the QTI response declaration that exposes the cardinality, base type, and response identifier. Restricts the QTI cardinality and baseType enums to their documented closed vocabularies. This is the shape of what a learner fills in — the correct answer and scoring data live in answerKey, and are deliberately NOT selected into this view (UAT-2 M4: correctResponse must never surface here, under any name)."
    },
    {
      "name": "Assessment Component",
      "description": "The recursive assessment structure in school language: a projection of the QTI component tree that renames to a governed role vocabulary and preserves the recursive self-reference for parent-child navigation. The synthesized role field maps the QTI element_name/type_name open text to the governed assessment_component_role enum. Components are import-authored; role is read-only."
    },
    {
      "name": "Assessment Test (Content view)",
      "description": "Projection of qti:assessmentTest carrying the Alpha typed assessment facts: is_mastery_gate is a typed boolean set at write time — not classified at read time from producer URL + subject + grade — plus the test_type enum and assessment_role. The enforceable gate machinery (gates, passing_criteria, on_fail, target_ref) lives on the Curriculum gating member; Content only carries the typed structural facts."
    },
    {
      "name": "Catalog Facet",
      "description": "Governed discovery-facet registry defining one facet dimension for content catalog tagging. Enforces allowed values and grain so consumers filter by governed facets."
    },
    {
      "name": "Catalog Facet Assignment",
      "description": "Facet value assigned to a content item as a sidecar tag (not recomputed at read time). UNIQUE(tenantId, contentId, facetKey, facetValue) prevents duplicate tagging. FK contentId into qti:artifact (two-leg); FK facetKey into catalogFacet."
    },
    {
      "name": "Content Curriculum Link",
      "description": "Coverage links between content items and curriculum nodes. curriculumNodeId is a hook-validated loose ref (not a DB FK) — the create/update hook validates against the imported curriculum repo when present; absent nodes are accepted because content may precede curriculum authoring."
    },
    {
      "name": "Content Item",
      "description": "The headline public catalog object: a projection of the QTI artifact union master that renames to school language, restricts the artifact-kind vocabulary to public Content kinds, and surfaces Alpha-owned typed columns (on qti.artifact) for subject, grade, DOK, expected XP, and content lifecycle status. Row visibility fail-closes on the restricted artifact_kind set and excludes archived items from default reads."
    },
    {
      "name": "Content Policy",
      "description": "Content-scoped configuration rows (policy-as-config). Named policy keys carry jsonb value payloads; consumers read at runtime instead of hardcoding constants. Read by downstream modules via hook-level cross-reads."
    },
    {
      "name": "Content Reference",
      "description": "Content-to-content edges modeled as a relationship row. Each row represents a typed directional link between two content items (qti:artifact rows) within the same tenant. Relationship kinds include bank membership with form ordering, media attachments, transcript/caption links, and alternative forms."
    },
    {
      "name": "Content Trust Evidence",
      "description": "Validation/conformance evidence recorded against a content item. Each row captures one trust check with typed status and jsonb payload. Read-exposed; mutation is internal only."
    },
    {
      "name": "Content Version",
      "description": "An immutable version snapshot of a content item, projected from the QTI artifact version master. Each version is write-once; the synthesized etag serves as a read-only concurrency token for cache validation and conditional requests on the content delivery surface. Versions are never updated after creation — the immutableFields discipline on the master cannot be bypassed through the projection."
    },
    {
      "name": "Export Job",
      "description": "A content export job receipt: tracks format, scope, processing status, and artifact reference for one exportCommonCartridge invocation. Status endpoint is the plain CRUD GET."
    },
    {
      "name": "Free Response Part",
      "description": "A free-response part of a question: the blank instrument's prompt, max points, ordinal position, and optional rubric reference. The student RESPONSE lives in results, never here. question-level model."
    },
    {
      "name": "Import Batch",
      "description": "A content import batch receipt: tracks source system, dedup hash, item/quarantine counts, and processing status for one importQtiPackage or importTimebackProduction invocation. Status endpoint is the plain CRUD GET."
    },
    {
      "name": "Media Asset",
      "description": "A media resource associated with content items, projected from the QTI package resource master. Surfaces Alpha-owned media classification columns living ON qti.package_resource (no companion extension table): mediaRole, mediaType, and deliveryPolicy. Media-role membership between a content item and its assets is navigated via contentReference rows (relationship_kind IN transcript_for, caption_for, thumbnail_for,...), not a denormalized column on this entity."
    },
    {
      "name": "Question Rubric",
      "description": "A grading rubric block for a blank question, stored once and referenced by free-response parts. Supports analytic (multi-criterion) and holistic (single-scale) rubric types."
    },
    {
      "name": "Test Bank",
      "description": "Bank identity for content_kind=test_bank. Gates reference the bank, never one frozen form. A bank carries a spec FK (its blueprint), a membership rule governing how forms join the bank, and a min_forms threshold."
    },
    {
      "name": "Test Specification",
      "description": "The validated table of specifications (blueprint) for content_kind=test_spec. A spec is first-class: it carries a passing_rule reference, min_forms requirement, and KC coverage grid. Every form in a bank is canonical against exactly one spec."
    }
  ],
  "paths": {
    "/content/v1/answer-key": {
      "get": {
        "operationId": "listAnswerKeys",
        "summary": "List answer keys",
        "description": "Lists answer keys visible to the caller. Correct-value fields are redacted for callers without read:answer_key permission.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Answer Key"
        ],
        "parameters": [
          {
            "name": "itemIdentifier",
            "in": "query",
            "required": false,
            "description": "Filter by owning assessment item identifier.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "itemIdentifier",
              "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/AnswerKey"
                      }
                    },
                    "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/answer-key/{itemIdentifier}/{responseIdentifier}": {
      "get": {
        "operationId": "getAnswerKey",
        "summary": "Get an answer key by item and response identifier",
        "description": "Gets one answer key. Correct-value fields are redacted for callers without read:answer_key permission — no 403, just field-level redaction.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Answer Key"
        ],
        "parameters": [
          {
            "name": "itemIdentifier",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "responseIdentifier",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnswerKey"
                }
              }
            }
          },
          "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 (answer_key_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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/answer-slot": {
      "get": {
        "operationId": "listAnswerSlots",
        "summary": "List answer slots for an item",
        "description": "Lists the blank answer slot structures visible through the projection. Filter by item to retrieve all response variables for one assessment item.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Answer Slot"
        ],
        "parameters": [
          {
            "name": "itemIdentifier",
            "in": "query",
            "required": false,
            "description": "Filter by owning assessment item identifier.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "itemIdentifier",
              "operator": "eq"
            }
          },
          {
            "name": "cardinality",
            "in": "query",
            "required": false,
            "description": "Filter by QTI cardinality.",
            "schema": {
              "type": "string",
              "enum": [
                "single",
                "multiple",
                "ordered",
                "record"
              ]
            },
            "x-filter": {
              "column": "cardinality",
              "operator": "eq"
            }
          },
          {
            "name": "baseType",
            "in": "query",
            "required": false,
            "description": "Filter by QTI base type.",
            "schema": {
              "type": "string",
              "enum": [
                "boolean",
                "directedPair",
                "duration",
                "file",
                "float",
                "identifier",
                "integer",
                "pair",
                "point",
                "string",
                "uri"
              ]
            },
            "x-filter": {
              "column": "baseType",
              "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/AnswerSlot"
                      }
                    },
                    "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/answer-slot/{itemIdentifier}/{responseIdentifier}": {
      "get": {
        "operationId": "getAnswerSlot",
        "summary": "Get an answer slot by item and response identifier",
        "description": "> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Answer Slot"
        ],
        "parameters": [
          {
            "name": "itemIdentifier",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "responseIdentifier",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnswerSlot"
                }
              }
            }
          },
          "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 (answer_slot_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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/assessment-component": {
      "get": {
        "operationId": "listAssessmentComponents",
        "summary": "List assessment components in the recursive tree",
        "description": "Lists components with optional filtering by parent or role. Use parentComponentId to navigate one level of the tree; use role to filter by governed vocabulary value.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Assessment Component"
        ],
        "parameters": [
          {
            "name": "parentComponentId",
            "in": "query",
            "required": false,
            "description": "Filter by parent component to retrieve direct children in the tree.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "parentComponentId",
              "operator": "eq"
            }
          },
          {
            "name": "role",
            "in": "query",
            "required": false,
            "description": "Filter by assessment component role.",
            "schema": {
              "type": "string",
              "enum": [
                "test",
                "section",
                "part",
                "question",
                "question_ref",
                "distractor",
                "rubric",
                "preauthored_feedback"
              ]
            },
            "x-filter": {
              "column": "role",
              "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/AssessmentComponent"
                      }
                    },
                    "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/assessment-component/{componentId}": {
      "get": {
        "operationId": "getAssessmentComponent",
        "summary": "Get an assessment component by id",
        "description": "> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Assessment Component"
        ],
        "parameters": [
          {
            "name": "componentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssessmentComponent"
                }
              }
            }
          },
          "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_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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/assessment-test-profile": {
      "get": {
        "operationId": "listAssessmentTestProfiles",
        "summary": "List assessment tests with Alpha typed assessment facts",
        "description": "Returns the Content view of assessment tests. is_mastery_gate / test_type / assessment_role are typed filterable columns set at write time.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Assessment Test (Content view)"
        ],
        "parameters": [
          {
            "name": "isMasteryGate",
            "in": "query",
            "required": false,
            "description": "Filter by the typed mastery-gate fact.",
            "schema": {
              "type": "boolean"
            },
            "x-filter": {
              "column": "isMasteryGate",
              "operator": "eq"
            }
          },
          {
            "name": "testType",
            "in": "query",
            "required": false,
            "description": "Filter by test type.",
            "schema": {
              "type": "string",
              "enum": [
                "end_of_course",
                "end_of_grade",
                "test_out",
                "placement",
                "diagnostic",
                "screener"
              ]
            },
            "x-filter": {
              "column": "testType",
              "operator": "eq"
            }
          },
          {
            "name": "assessmentRole",
            "in": "query",
            "required": false,
            "description": "Filter by assessment role.",
            "schema": {
              "type": "string",
              "enum": [
                "form",
                "spec",
                "bank"
              ]
            },
            "x-filter": {
              "column": "assessmentRole",
              "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/AssessmentTestProfile"
                      }
                    },
                    "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/assessment-test-profile/{identifier}": {
      "get": {
        "operationId": "getAssessmentTestProfile",
        "summary": "Get one assessment test by its QTI test identifier",
        "description": "> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Assessment Test (Content view)"
        ],
        "parameters": [
          {
            "name": "identifier",
            "in": "path",
            "required": true,
            "description": "The QTI test identifier (natural key).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssessmentTestProfile"
                }
              }
            }
          },
          "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_profile_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": "updateAssessmentTestProfile",
        "summary": "Set the typed assessment facts at write time",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Assessment Test (Content view)"
        ],
        "parameters": [
          {
            "name": "identifier",
            "in": "path",
            "required": true,
            "description": "The QTI test identifier (natural key).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAssessmentTestProfileRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssessmentTestProfile"
                }
              }
            }
          },
          "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_profile_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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/catalog-facet": {
      "get": {
        "operationId": "listCatalogFacets",
        "summary": "List catalog facets",
        "description": "Returns all governed catalog facets for the authenticated tenant.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Catalog Facet"
        ],
        "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/CatalogFacet"
                      }
                    },
                    "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": "createCatalogFacet",
        "summary": "Create a catalog facet",
        "description": "Registers a new governed facet in the tenant's catalog facet registry.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Catalog Facet"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCatalogFacetRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogFacet"
                }
              }
            }
          },
          "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": "Problem (catalog_facet_already_exists).",
            "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/catalog-facet/{facetKey}": {
      "get": {
        "operationId": "getCatalogFacet",
        "summary": "Get a catalog facet",
        "description": "Returns a single catalog facet by its facetKey.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Catalog Facet"
        ],
        "parameters": [
          {
            "name": "facetKey",
            "in": "path",
            "required": true,
            "description": "The facet key.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogFacet"
                }
              }
            }
          },
          "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 (catalog_facet_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": "updateCatalogFacet",
        "summary": "Update a catalog facet",
        "description": "Updates an existing catalog facet's allowed values, grain, or description.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Catalog Facet"
        ],
        "parameters": [
          {
            "name": "facetKey",
            "in": "path",
            "required": true,
            "description": "The facet key.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCatalogFacetRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogFacet"
                }
              }
            }
          },
          "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 (catalog_facet_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": "deleteCatalogFacet",
        "summary": "Delete a catalog facet",
        "description": "Removes a catalog facet from the registry. Fails if assignments still reference this facet.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Catalog Facet"
        ],
        "parameters": [
          {
            "name": "facetKey",
            "in": "path",
            "required": true,
            "description": "The facet key.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "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 (catalog_facet_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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/catalog-facet-assignment": {
      "get": {
        "operationId": "listCatalogFacetAssignments",
        "summary": "List catalog facet assignments",
        "description": "Returns facet assignments for the authenticated tenant. Supports filtering by contentId and facetKey.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Catalog Facet Assignment"
        ],
        "parameters": [
          {
            "name": "contentId",
            "in": "query",
            "required": false,
            "description": "Filter assignments by content item id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "contentId",
              "operator": "eq"
            }
          },
          {
            "name": "facetKey",
            "in": "query",
            "required": false,
            "description": "Filter assignments by facet key.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "facetKey",
              "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/CatalogFacetAssignment"
                      }
                    },
                    "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": "createCatalogFacetAssignment",
        "summary": "Create a catalog facet assignment (idempotent on the triple)",
        "description": "Assigns a facet value to a content item. The facetValue is validated against the referenced catalogFacet's type and allowed values. Idempotent on the natural triple (tenantId, contentId, facetKey, facetValue): a duplicate POST with a distinct assignmentId returns the original assignment identity (201) and leaves a single row — not a second insert and not a generic 409.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Catalog Facet Assignment"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "assignmentId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Caller-supplied assignment id for a fresh insert. Ignored on triple replay — the original assignmentId is returned."
                  },
                  "contentId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "The content item this facet value is assigned to."
                  },
                  "facetKey": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255,
                    "description": "The governed facet key."
                  },
                  "facetValue": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 1000,
                    "description": "The assigned facet value."
                  }
                },
                "required": [
                  "assignmentId",
                  "contentId",
                  "facetKey",
                  "facetValue"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogFacetAssignment"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/catalog-facet-assignment/{assignmentId}": {
      "get": {
        "operationId": "getCatalogFacetAssignment",
        "summary": "Get a catalog facet assignment",
        "description": "Returns a single facet assignment by its assignmentId.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Catalog Facet Assignment"
        ],
        "parameters": [
          {
            "name": "assignmentId",
            "in": "path",
            "required": true,
            "description": "The assignment id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogFacetAssignment"
                }
              }
            }
          },
          "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 (catalog_facet_assignment_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": "deleteCatalogFacetAssignment",
        "summary": "Delete a catalog facet assignment",
        "description": "Removes a facet assignment from a content item.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Catalog Facet Assignment"
        ],
        "parameters": [
          {
            "name": "assignmentId",
            "in": "path",
            "required": true,
            "description": "The assignment id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "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 (catalog_facet_assignment_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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/content-curriculum-link": {
      "get": {
        "operationId": "listContentCurriculumLinks",
        "summary": "List content-curriculum links",
        "description": "> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Content Curriculum Link"
        ],
        "parameters": [
          {
            "name": "contentId",
            "in": "query",
            "required": false,
            "description": "Filter links by content id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "contentId",
              "operator": "eq"
            }
          },
          {
            "name": "curriculumNodeId",
            "in": "query",
            "required": false,
            "description": "Filter links by curriculum node id.",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "curriculumNodeId",
              "operator": "eq"
            }
          },
          {
            "name": "linkKind",
            "in": "query",
            "required": false,
            "description": "Filter links by kind.",
            "schema": {
              "type": "string",
              "enum": [
                "teaches",
                "practices",
                "assesses",
                "supports",
                "extends"
              ]
            },
            "x-filter": {
              "column": "linkKind",
              "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/ContentCurriculumLink"
                      }
                    },
                    "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": "createContentCurriculumLink",
        "summary": "Create a content-curriculum link",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Content Curriculum Link"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateContentCurriculumLinkRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentCurriculumLink"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/content-curriculum-link/{linkId}": {
      "get": {
        "operationId": "getContentCurriculumLink",
        "summary": "Get a content-curriculum link by id",
        "description": "> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Content Curriculum Link"
        ],
        "parameters": [
          {
            "name": "linkId",
            "in": "path",
            "required": true,
            "description": "The link id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentCurriculumLink"
                }
              }
            }
          },
          "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_curriculum_link_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": "updateContentCurriculumLink",
        "summary": "Update a content-curriculum link",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Content Curriculum Link"
        ],
        "parameters": [
          {
            "name": "linkId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateContentCurriculumLinkRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentCurriculumLink"
                }
              }
            }
          },
          "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_curriculum_link_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": "deleteContentCurriculumLink",
        "summary": "Delete a content-curriculum link",
        "description": "> **Requires role:** `admin`",
        "tags": [
          "Content Curriculum Link"
        ],
        "parameters": [
          {
            "name": "linkId",
            "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/content-item": {
      "get": {
        "operationId": "listContentItems",
        "summary": "List content items in the tenant catalog",
        "description": "Returns content items visible through the projection view. Row visibility fail-closes: only artifact_kind IN (item, test, stimulus, manifest-resource) plus media rows are admitted, and status <> archived for default reads.\n\n> **Requires role:** `admin` · `author` · `runtime` · `sandboxVendor`",
        "tags": [
          "Content Item"
        ],
        "parameters": [
          {
            "name": "contentKind",
            "in": "query",
            "required": false,
            "description": "Filter by canonical content kind.",
            "schema": {
              "type": "string",
              "enum": [
                "question",
                "test",
                "test_spec",
                "test_bank",
                "article",
                "video",
                "audio",
                "image",
                "interactive",
                "media_asset",
                "external_link",
                "script",
                "stimulus"
              ]
            },
            "x-filter": {
              "column": "contentKind",
              "operator": "eq"
            }
          },
          {
            "name": "facet",
            "in": "query",
            "required": false,
            "description": "Catalog facet filter as `facet_key:value` (module-content queryModel). onListQuery resolves matching content ids in-tenant and rewrites to contentId IN (...), clearing this param before the repository query. Malformed syntax or unknown facet key/value → 400 (never silently ignored).",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_]+:.+$"
            },
            "x-filter": {
              "column": "title",
              "operator": "eq"
            }
          },
          {
            "name": "contentId",
            "in": "query",
            "required": false,
            "description": "Filter by one or more content ids. Also the rewrite target for facet= filters (hook sets contentId IN matching assignment content ids).",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "format": "uuid"
              }
            },
            "x-filter": {
              "column": "contentId",
              "operator": "in"
            }
          },
          {
            "name": "subjectId",
            "in": "query",
            "required": false,
            "description": "Filter by canonical subject id.",
            "schema": {
              "type": "string",
              "enum": [
                "math",
                "reading",
                "language",
                "science",
                "vocabulary",
                "writing"
              ]
            },
            "x-filter": {
              "column": "subjectId",
              "operator": "eq"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filter by lifecycle status. Default catalog read excludes archived; explicit status=archived overrides row visibility for audit reads.",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "published",
                "retired",
                "archived"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "targetGradeId",
            "in": "query",
            "required": false,
            "description": "Filter by target grade level.",
            "schema": {
              "type": "string",
              "enum": [
                "pre_k",
                "k",
                "1",
                "2",
                "3",
                "4",
                "5",
                "6",
                "7",
                "8",
                "9",
                "10",
                "11",
                "12",
                "postsecondary",
                "ungraded"
              ]
            },
            "x-filter": {
              "column": "targetGradeId",
              "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/ContentItem"
                      }
                    },
                    "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": "createContentItem",
        "summary": "Create a content item (writes the qti:artifact master through the inverse column map)",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Content Item"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateContentItemRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentItem"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/content-item/{id}": {
      "get": {
        "operationId": "getContentItem",
        "summary": "Get a content item by its content id",
        "description": "> **Requires role:** `admin` · `author` · `runtime` · `sandboxVendor`",
        "tags": [
          "Content Item"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The content item id (projected from qti:artifact surrogate id).",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentItem"
                }
              }
            }
          },
          "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_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"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateContentItem",
        "summary": "Update a content item (renamed/extends fields land on their master columns)",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Content Item"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateContentItemRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentItem"
                }
              }
            }
          },
          "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_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"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteContentItem",
        "summary": "Soft-delete a content item (soft-deletes the master row)",
        "description": "> **Requires role:** `admin`",
        "tags": [
          "Content Item"
        ],
        "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/content-item/{id}/effectiveness": {
      "get": {
        "operationId": "getContentEffectiveness",
        "summary": "Read the Results-owned content effectiveness rollup",
        "description": "command GET whose hook reads the Results-owned content_effectiveness rollup for this content item and returns {validatedByCount, failedByCount, effectivenessRate, effectivenessStatus, lastRecomputedAt}. Content exposes the read but never creates or writes the rollup. effectivenessRate = validated / (validated + failed), 4 decimal places; insufficient_data below the content.effectiveness.minimum_eligible_results policy minimum.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Content Item"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The content item id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "contentId": {
                      "type": "string",
                      "format": "uuid",
                      "description": "The content item this rollup describes."
                    },
                    "validatedByCount": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Count of settled results that validated this content."
                    },
                    "failedByCount": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Count of settled results that failed this content."
                    },
                    "effectivenessRate": {
                      "type": "number",
                      "description": "validated / (validated + failed), rounded to 4 decimal places. Null when there are no eligible results.",
                      "nullable": true
                    },
                    "effectivenessStatus": {
                      "type": "string",
                      "enum": [
                        "fresh",
                        "stale",
                        "pending",
                        "insufficient_data"
                      ],
                      "description": "Rollup freshness classification under the content.effectiveness.* policies."
                    },
                    "lastRecomputedAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "When the Results-owned rollup was last recomputed. Null when no rollup row exists.",
                      "nullable": true
                    }
                  },
                  "required": [
                    "contentId",
                    "validatedByCount",
                    "failedByCount",
                    "effectivenessRate",
                    "effectivenessStatus",
                    "lastRecomputedAt"
                  ]
                }
              }
            }
          },
          "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_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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/content-item/{id}/interactive-composition": {
      "get": {
        "operationId": "getInteractiveComposition",
        "summary": "Read the typed interactive article/video composition",
        "description": "Returns the ordered article segments or video cues that bind already-shown content to canonical question references.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Content Item"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "contentId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "versionId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "compositionType": {
                      "type": "string",
                      "enum": [
                        "interactive_article",
                        "interactive_video"
                      ]
                    },
                    "mediaAssetRef": {
                      "type": "object"
                    },
                    "durationSeconds": {
                      "type": "number",
                      "exclusiveMinimum": 0
                    },
                    "segments": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "cues": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "validationContract": {
                      "type": "object"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "contentId",
                    "compositionType",
                    "validationContract",
                    "updatedAt"
                  ]
                }
              }
            }
          },
          "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 (interactive_composition_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": "replaceInteractiveComposition",
        "summary": "Atomically replace the typed interactive composition",
        "description": "Upserts the authoritative ordered composition. Article segments and video cues are mutually exclusive; every binding must reference a question and assert testsPriorContent=true.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Content Item"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "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": {
                  "versionId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "compositionType": {
                    "type": "string",
                    "enum": [
                      "interactive_article",
                      "interactive_video"
                    ]
                  },
                  "mediaAssetRef": {
                    "type": "object"
                  },
                  "durationSeconds": {
                    "type": "number",
                    "exclusiveMinimum": 0
                  },
                  "segments": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    }
                  },
                  "cues": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    }
                  }
                },
                "required": [
                  "compositionType"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "contentId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "versionId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "compositionType": {
                      "type": "string",
                      "enum": [
                        "interactive_article",
                        "interactive_video"
                      ]
                    },
                    "mediaAssetRef": {
                      "type": "object"
                    },
                    "durationSeconds": {
                      "type": "number",
                      "exclusiveMinimum": 0
                    },
                    "segments": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "cues": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "validationContract": {
                      "type": "object"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "contentId",
                    "compositionType",
                    "validationContract",
                    "updatedAt"
                  ]
                }
              }
            },
            "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 (content_item_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": "Unprocessable Entity — this Idempotency-Key was already used with a different request body.",
            "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/content-policy": {
      "get": {
        "operationId": "listContentPolicies",
        "summary": "List content policies",
        "description": "Returns all content policy configuration rows for the authenticated tenant.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Content Policy"
        ],
        "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/ContentPolicy"
                      }
                    },
                    "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": "createContentPolicy",
        "summary": "Create a content policy",
        "description": "Creates a new content policy configuration row.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Content Policy"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateContentPolicyRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentPolicy"
                }
              }
            }
          },
          "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": "Problem (content_policy_already_exists).",
            "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/content-policy/{policyKey}": {
      "get": {
        "operationId": "getContentPolicy",
        "summary": "Get a content policy",
        "description": "Returns a single content policy by its policyKey.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Content Policy"
        ],
        "parameters": [
          {
            "name": "policyKey",
            "in": "path",
            "required": true,
            "description": "The policy key.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentPolicy"
                }
              }
            }
          },
          "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_policy_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": "updateContentPolicy",
        "summary": "Update a content policy",
        "description": "Updates the value and/or description of an existing content policy.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Content Policy"
        ],
        "parameters": [
          {
            "name": "policyKey",
            "in": "path",
            "required": true,
            "description": "The policy key.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateContentPolicyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentPolicy"
                }
              }
            }
          },
          "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_policy_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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/content-reference": {
      "get": {
        "operationId": "listContentReferences",
        "summary": "List content references for the tenant",
        "description": "Returns content-to-content reference edges. Supports filtering by fromContentId, toContentId, and relationshipKind.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Content Reference"
        ],
        "parameters": [
          {
            "name": "fromContentId",
            "in": "query",
            "required": false,
            "description": "Filter references by the source content item.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "fromContentId",
              "operator": "eq"
            }
          },
          {
            "name": "toContentId",
            "in": "query",
            "required": false,
            "description": "Filter references by the target content item.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "toContentId",
              "operator": "eq"
            }
          },
          {
            "name": "relationshipKind",
            "in": "query",
            "required": false,
            "description": "Filter by relationship kind.",
            "schema": {
              "type": "string",
              "enum": [
                "embeds",
                "transcript_for",
                "bank_member",
                "series_member",
                "alternative_form_of",
                "caption_for",
                "thumbnail_for",
                "worksheet_for",
                "source_file_for"
              ]
            },
            "x-filter": {
              "column": "relationshipKind",
              "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/ContentReference"
                      }
                    },
                    "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": "createContentReference",
        "summary": "Create a content reference",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Content Reference"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateContentReferenceRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentReference"
                }
              }
            }
          },
          "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": "Problem (content_reference_already_exists).",
            "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/content-reference/{referenceId}": {
      "get": {
        "operationId": "getContentReference",
        "summary": "Get a content reference by referenceId",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Content Reference"
        ],
        "parameters": [
          {
            "name": "referenceId",
            "in": "path",
            "required": true,
            "description": "The content reference identifier.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentReference"
                }
              }
            }
          },
          "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_reference_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": "updateContentReference",
        "summary": "Update a content reference",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Content Reference"
        ],
        "parameters": [
          {
            "name": "referenceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateContentReferenceRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentReference"
                }
              }
            }
          },
          "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_reference_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": "deleteContentReference",
        "summary": "Delete a content reference",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Content Reference"
        ],
        "parameters": [
          {
            "name": "referenceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "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_reference_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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/content-trust-evidence": {
      "get": {
        "operationId": "listContentTrustEvidence",
        "summary": "List content trust evidence",
        "description": "Returns trust evidence records for the authenticated tenant. Supports filtering by contentId and trustStatus.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Content Trust Evidence"
        ],
        "parameters": [
          {
            "name": "contentId",
            "in": "query",
            "required": false,
            "description": "Filter evidence by content item id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "contentId",
              "operator": "eq"
            }
          },
          {
            "name": "trustStatus",
            "in": "query",
            "required": false,
            "description": "Filter evidence by trust status.",
            "schema": {
              "type": "string",
              "enum": [
                "trusted",
                "degraded",
                "failed",
                "unknown"
              ]
            },
            "x-filter": {
              "column": "trustStatus",
              "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/ContentTrustEvidence"
                      }
                    },
                    "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/content-trust-evidence/{evidenceId}": {
      "get": {
        "operationId": "getContentTrustEvidence",
        "summary": "Get content trust evidence",
        "description": "Returns a single trust evidence record by its evidenceId.\n\n> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Content Trust Evidence"
        ],
        "parameters": [
          {
            "name": "evidenceId",
            "in": "path",
            "required": true,
            "description": "The evidence id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentTrustEvidence"
                }
              }
            }
          },
          "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_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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/content-version": {
      "post": {
        "operationId": "createContentVersion",
        "summary": "Create an immutable content version (writes the qti:artifactVersion master through the inverse column map)",
        "description": "Authoring/import door for version snapshots. Versions are write-once — there is no update operation; supersession is navigated via the parent item's latestVersionId.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Content Version"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateContentVersionRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentVersion"
                }
              }
            }
          },
          "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": "listContentVersions",
        "summary": "List content versions for an artifact",
        "description": "Returns immutable version snapshots visible through the projection. Versions are write-once and carry the synthesized etag for cache validation.\n\n> **Requires role:** `admin` · `author` · `runtime` · `sandboxVendor`",
        "tags": [
          "Content Version"
        ],
        "parameters": [
          {
            "name": "contentId",
            "in": "query",
            "required": false,
            "description": "Filter versions by parent content item id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "contentId",
              "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/ContentVersion"
                      }
                    },
                    "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/content-version/{versionId}": {
      "get": {
        "operationId": "getContentVersion",
        "summary": "Get a content version by its version id",
        "description": "> **Requires role:** `admin` · `author` · `runtime` · `sandboxVendor`",
        "tags": [
          "Content Version"
        ],
        "parameters": [
          {
            "name": "versionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContentVersion"
                }
              }
            }
          },
          "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_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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/export-job": {
      "get": {
        "operationId": "listExportJobs",
        "summary": "List export job receipts",
        "description": "Returns all export job receipts for the authenticated tenant, ordered by most recent first.\n\n> **Requires role:** `admin`",
        "tags": [
          "Export Job"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filter by job processing status.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "processing",
                "completed",
                "failed"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Filter by export format.",
            "schema": {
              "type": "string",
              "enum": [
                "common_cartridge_1_3"
              ]
            },
            "x-filter": {
              "column": "format",
              "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/ExportJob"
                      }
                    },
                    "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/export-job/{exportId}": {
      "get": {
        "operationId": "getExportJob",
        "summary": "Get an export job receipt (the status endpoint)",
        "description": "Returns a single export job receipt by its exportId. This is the receipt-is-an-entity status endpoint: the exportCommonCartridge command writes the receipt, and this plain CRUD GET serves the job status and download reference.\n\n> **Requires role:** `admin`",
        "tags": [
          "Export Job"
        ],
        "parameters": [
          {
            "name": "exportId",
            "in": "path",
            "required": true,
            "description": "The export job identifier.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExportJob"
                }
              }
            }
          },
          "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 (export_job_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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/export-job/{exportId}/download": {
      "get": {
        "operationId": "downloadExport",
        "summary": "Get the download reference for a completed export",
        "description": "Returns the artifact reference (downloadUri, artifactHash) for a completed export job. The client fetches bytes out-of-band from the object-storage URI. Returns 404 if the export is not yet completed or has failed.\n\n> **Requires role:** `admin`",
        "tags": [
          "Export Job"
        ],
        "parameters": [
          {
            "name": "exportId",
            "in": "path",
            "required": true,
            "description": "The export job identifier.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExportJob"
                }
              }
            }
          },
          "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 (export_job_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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/export-job/common-cartridge": {
      "post": {
        "operationId": "exportCommonCartridge",
        "summary": "Export content as a Common Cartridge 1.3 bundle (writes the receipt)",
        "description": "Assembles a Common Cartridge 1.3 manifest from the in-scope Content + Curriculum structure, writes an exportJob receipt, and returns it at 201. The produced artifact is stored at an object-storage URI on the receipt; clients fetch bytes out-of-band via that URI. Idempotency is optional: repeated calls produce a new export each time unless the client supplies an Idempotency-Key.\n\n> **Requires role:** `admin`",
        "tags": [
          "Export Job"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "The idempotency key (max 128 chars). Optional — when present, the call is replay-protected; 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": {
                  "format": {
                    "type": "string",
                    "enum": [
                      "common_cartridge_1_3"
                    ],
                    "description": "The target export format."
                  },
                  "scope": {
                    "type": "object",
                    "properties": {
                      "curriculumNodeIds": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "Curriculum node identifiers to bundle (curriculum-side string ids)."
                      },
                      "courseComponentId": {
                        "type": "string",
                        "format": "uuid",
                        "description": "A single course component to export."
                      }
                    },
                    "description": "The export scope: one of curriculumNodeIds or courseComponentId."
                  }
                },
                "required": [
                  "format",
                  "scope"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExportJob"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExportJob"
                }
              }
            },
            "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 (content.export_scope_invalid).",
            "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/free-response-part": {
      "get": {
        "operationId": "listFreeResponseParts",
        "summary": "List free-response parts",
        "description": "> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Free Response Part"
        ],
        "parameters": [
          {
            "name": "contentId",
            "in": "query",
            "required": false,
            "description": "Filter parts by question content id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "contentId",
              "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/FreeResponsePart"
                      }
                    },
                    "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": "createFreeResponsePart",
        "summary": "Create a free-response part for a question",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Free Response Part"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateFreeResponsePartRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FreeResponsePart"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/free-response-part/{partId}": {
      "get": {
        "operationId": "getFreeResponsePart",
        "summary": "Get a free-response part by id",
        "description": "> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Free Response Part"
        ],
        "parameters": [
          {
            "name": "partId",
            "in": "path",
            "required": true,
            "description": "The part id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FreeResponsePart"
                }
              }
            }
          },
          "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 (free_response_part_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": "updateFreeResponsePart",
        "summary": "Update a free-response part",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Free Response Part"
        ],
        "parameters": [
          {
            "name": "partId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateFreeResponsePartRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FreeResponsePart"
                }
              }
            }
          },
          "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 (free_response_part_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": "deleteFreeResponsePart",
        "summary": "Delete a free-response part",
        "description": "> **Requires role:** `admin`",
        "tags": [
          "Free Response Part"
        ],
        "parameters": [
          {
            "name": "partId",
            "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/import-batch": {
      "get": {
        "operationId": "listImportBatches",
        "summary": "List import batch receipts",
        "description": "Returns all import batch receipts for the authenticated tenant, ordered by most recent first.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Import Batch"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filter by batch processing status.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "processing",
                "completed",
                "failed",
                "quarantined"
              ]
            },
            "x-filter": {
              "column": "status",
              "operator": "eq"
            }
          },
          {
            "name": "sourceSystem",
            "in": "query",
            "required": false,
            "description": "Filter by the source system that produced the import.",
            "schema": {
              "type": "string",
              "enum": [
                "qti",
                "alpha_content",
                "external_content_import"
              ]
            },
            "x-filter": {
              "column": "sourceSystem",
              "operator": "eq"
            }
          },
          {
            "name": "packageHash",
            "in": "query",
            "required": false,
            "description": "Filter by the package dedup hash (domain-level dedup lookup).",
            "schema": {
              "type": "string"
            },
            "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/ImportBatch"
                      }
                    },
                    "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/import-batch/{batchId}": {
      "get": {
        "operationId": "getImportBatch",
        "summary": "Get an import batch receipt (the status endpoint)",
        "description": "Returns a single import batch receipt by its batchId. This is the receipt-is-an-entity status endpoint: the command import commands write the receipt, and this plain CRUD GET serves the batch status.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Import Batch"
        ],
        "parameters": [
          {
            "name": "batchId",
            "in": "path",
            "required": true,
            "description": "The import batch identifier.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportBatch"
                }
              }
            }
          },
          "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 (import_batch_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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/import-batch/qti-package": {
      "post": {
        "operationId": "importQtiPackage",
        "summary": "Import a QTI 3.0 package (writes the receipt)",
        "description": "Parses a QTI 3.0 package (via source_uri reference), materializes qti:artifact/artifactVersion/component/packageResource rows and Content extends columns, and writes an importBatch receipt. Returns the receipt at 201. Replay-protected by the required Idempotency-Key; domain-level dedup on (tenant, package_hash) stays hook-owned.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Import Batch"
        ],
        "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": {
                  "sourceUri": {
                    "type": "string",
                    "format": "uri",
                    "description": "Object-storage URI where the QTI package bytes are fetched from (JSON door using a URI reference rather than multipart upload)."
                  },
                  "packageHash": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 128,
                    "description": "SHA-256 hash of the package bytes. The dedup key."
                  }
                },
                "required": [
                  "sourceUri",
                  "packageHash"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportBatch"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportBatch"
                }
              }
            },
            "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 (content.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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/import-batch/{sourceAdapter}": {
      "post": {
        "operationId": "importTimebackProduction",
        "summary": "Import content via a source-generic adapter (writes the receipt)",
        "description": "Source-generic import adapter: normalizes source-shaped content rows to the canonical Content shape, performs subject/grade/kind alias fold at write time, quarantines rows failing schema validation, and writes an importBatch receipt. The sourceAdapter path param selects the named normalizer among registered adapters. Guardrail: QTI-backed assessment content (question, test) is rejected with a typed error pointing at the importQtiPackage door.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Import Batch"
        ],
        "parameters": [
          {
            "name": "sourceAdapter",
            "in": "path",
            "required": true,
            "description": "The named source adapter to use for normalization (e.g. 'timeback-production').",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "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": {
                  "records": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "description": "One source-shaped content row (schema validated by the hook against the adapter's contract)."
                    },
                    "minItems": 1,
                    "description": "Source-shaped content/activity-reference rows to normalize and materialize."
                  },
                  "packageHash": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 128,
                    "description": "SHA-256 hash of the import payload. The dedup key."
                  }
                },
                "required": [
                  "records",
                  "packageHash"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (idempotent replay — the stored first response; idempotency-replayed: true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportBatch"
                }
              }
            },
            "headers": {
              "idempotency-replayed": {
                "description": "true when this response is a stored idempotent replay (the hook did not run).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportBatch"
                }
              }
            },
            "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 (content.adapter_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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/media-asset": {
      "get": {
        "operationId": "listMediaAssets",
        "summary": "List media assets",
        "description": "Lists media assets visible through the projection. Filter by role or MIME type to navigate the asset catalog.\n\n> **Requires role:** `admin` · `author` · `runtime` · `sandboxVendor`",
        "tags": [
          "Media Asset"
        ],
        "parameters": [
          {
            "name": "mediaRole",
            "in": "query",
            "required": false,
            "description": "Filter by governed media role.",
            "schema": {
              "type": "string",
              "enum": [
                "primary",
                "supporting",
                "thumbnail",
                "caption",
                "transcript",
                "worksheet",
                "source_file"
              ]
            },
            "x-filter": {
              "column": "mediaRole",
              "operator": "eq"
            }
          },
          {
            "name": "mediaType",
            "in": "query",
            "required": false,
            "description": "Filter by MIME type (exact match).",
            "schema": {
              "type": "string"
            },
            "x-filter": {
              "column": "mediaType",
              "operator": "eq"
            }
          },
          {
            "name": "deliveryPolicy",
            "in": "query",
            "required": false,
            "description": "Filter by delivery policy.",
            "schema": {
              "type": "string",
              "enum": [
                "inline",
                "download",
                "stream",
                "external_link"
              ]
            },
            "x-filter": {
              "column": "deliveryPolicy",
              "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/MediaAsset"
                      }
                    },
                    "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/media-asset/{mediaAssetId}": {
      "get": {
        "operationId": "getMediaAsset",
        "summary": "Get a media asset by id",
        "description": "> **Requires role:** `admin` · `author` · `runtime` · `sandboxVendor`",
        "tags": [
          "Media Asset"
        ],
        "parameters": [
          {
            "name": "mediaAssetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediaAsset"
                }
              }
            }
          },
          "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 (media_asset_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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/question-rubric": {
      "get": {
        "operationId": "listQuestionRubrics",
        "summary": "List question rubrics",
        "description": "> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Question Rubric"
        ],
        "parameters": [
          {
            "name": "contentId",
            "in": "query",
            "required": false,
            "description": "Filter rubrics by question content id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "contentId",
              "operator": "eq"
            }
          },
          {
            "name": "rubricType",
            "in": "query",
            "required": false,
            "description": "Filter rubrics by rubric type.",
            "schema": {
              "type": "string",
              "enum": [
                "analytic",
                "holistic"
              ]
            },
            "x-filter": {
              "column": "rubricType",
              "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/QuestionRubric"
                      }
                    },
                    "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": "createQuestionRubric",
        "summary": "Create a question rubric for a question",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Question Rubric"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateQuestionRubricRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuestionRubric"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/question-rubric/{rubricId}": {
      "get": {
        "operationId": "getQuestionRubric",
        "summary": "Get a question rubric by id",
        "description": "> **Requires role:** `admin` · `author` · `runtime`",
        "tags": [
          "Question Rubric"
        ],
        "parameters": [
          {
            "name": "rubricId",
            "in": "path",
            "required": true,
            "description": "The rubric id.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuestionRubric"
                }
              }
            }
          },
          "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 (question_rubric_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": "updateQuestionRubric",
        "summary": "Update a question rubric",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Question Rubric"
        ],
        "parameters": [
          {
            "name": "rubricId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateQuestionRubricRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuestionRubric"
                }
              }
            }
          },
          "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 (question_rubric_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": "deleteQuestionRubric",
        "summary": "Delete a question rubric",
        "description": "> **Requires role:** `admin`",
        "tags": [
          "Question Rubric"
        ],
        "parameters": [
          {
            "name": "rubricId",
            "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/test-bank": {
      "get": {
        "operationId": "listTestBanks",
        "summary": "List test banks for the tenant",
        "description": "Returns all test banks visible to the authenticated tenant.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Test Bank"
        ],
        "parameters": [
          {
            "name": "specId",
            "in": "query",
            "required": false,
            "description": "Filter banks by their spec FK.",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "x-filter": {
              "column": "specId",
              "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/TestBank"
                      }
                    },
                    "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": "createTestBank",
        "summary": "Create a test bank",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Test Bank"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTestBankRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestBank"
                }
              }
            }
          },
          "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": "Problem (test_bank_already_exists).",
            "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/test-bank/{bankId}": {
      "get": {
        "operationId": "getTestBank",
        "summary": "Get a test bank by bankId",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Test Bank"
        ],
        "parameters": [
          {
            "name": "bankId",
            "in": "path",
            "required": true,
            "description": "The test bank identifier.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestBank"
                }
              }
            }
          },
          "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_bank_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": "updateTestBank",
        "summary": "Update a test bank",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Test Bank"
        ],
        "parameters": [
          {
            "name": "bankId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateTestBankRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestBank"
                }
              }
            }
          },
          "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_bank_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": "deleteTestBank",
        "summary": "Soft-delete a test bank",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Test Bank"
        ],
        "parameters": [
          {
            "name": "bankId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "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_bank_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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/test-spec": {
      "get": {
        "operationId": "listTestSpecs",
        "summary": "List test specifications for the tenant",
        "description": "Returns all test specifications (blueprints) visible to the authenticated tenant.\n\n> **Requires role:** `admin` · `author`",
        "tags": [
          "Test Specification"
        ],
        "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/TestSpec"
                      }
                    },
                    "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": "createTestSpec",
        "summary": "Create a test specification",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Test Specification"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTestSpecRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestSpec"
                }
              }
            }
          },
          "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": "Problem (test_spec_already_exists).",
            "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"
                }
              }
            }
          }
        }
      }
    },
    "/content/v1/test-spec/{specId}": {
      "get": {
        "operationId": "getTestSpec",
        "summary": "Get a test specification by specId",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Test Specification"
        ],
        "parameters": [
          {
            "name": "specId",
            "in": "path",
            "required": true,
            "description": "The test spec identifier.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestSpec"
                }
              }
            }
          },
          "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_spec_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": "updateTestSpec",
        "summary": "Update a test specification",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Test Specification"
        ],
        "parameters": [
          {
            "name": "specId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateTestSpecRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestSpec"
                }
              }
            }
          },
          "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_spec_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": "deleteTestSpec",
        "summary": "Soft-delete a test specification",
        "description": "> **Requires role:** `admin` · `author`",
        "tags": [
          "Test Specification"
        ],
        "parameters": [
          {
            "name": "specId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No Content.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "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_spec_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": {
      "AnswerKey": {
        "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 answer key. Part of the composite natural key."
          },
          "responseIdentifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The QTI response variable identifier within the owning item. Part of the composite natural key."
          },
          "correctResponse": {
            "type": "object",
            "description": "The JSONB representation of the correct response for this declaration. Contains the value(s) that constitute a correct answer. Sensitive: redacted for callers without read:answer_key permission.",
            "additionalProperties": true
          },
          "matchTable": {
            "type": "object",
            "description": "The JSONB match/map table used for scoring this response. Contains value-to-score mapping entries, default values, and upper/lower bounds. Sensitive: redacted for callers without read:answer_key permission.",
            "additionalProperties": true
          },
          "areaMapping": {
            "type": "object",
            "description": "Synthesized area mapping for graphical/spatial response scoring. Only populated when the base type involves spatial coordinates (point, pair, directedPair). Read-only.",
            "additionalProperties": true,
            "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": [
          "itemIdentifier",
          "responseIdentifier",
          "createdAt",
          "updatedAt"
        ]
      },
      "AnswerSlot": {
        "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 answer slot. Part of the composite natural key."
          },
          "responseIdentifier": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_.-]*$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The QTI response variable identifier within the owning item. Part of the composite natural key."
          },
          "cardinality": {
            "type": "string",
            "enum": [
              "single",
              "multiple",
              "ordered",
              "record"
            ],
            "description": "The QTI cardinality for this response variable, restricted to the closed 4-value XSD vocabulary. Determines whether the learner provides one value, many, an ordered sequence, or a named-field record."
          },
          "baseType": {
            "type": "string",
            "enum": [
              "boolean",
              "directedPair",
              "duration",
              "file",
              "float",
              "identifier",
              "integer",
              "pair",
              "point",
              "string",
              "uri"
            ],
            "description": "The QTI base type for values carried by this response variable, restricted to the closed 11-value XSD vocabulary."
          },
          "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",
          "cardinality",
          "baseType",
          "createdAt",
          "updatedAt"
        ]
      },
      "AssessmentComponent": {
        "type": "object",
        "properties": {
          "componentId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable component identifier projected from the QTI component surrogate id.",
            "readOnly": true
          },
          "parentComponentId": {
            "type": "string",
            "format": "uuid",
            "description": "Self-referencing FK to the parent component in the assessment tree. Preserves the recursive structure from the QTI component master. NULL for root-level components (tests). The FK targets the QTI master row that this projection overlays, not another projected row."
          },
          "role": {
            "type": "string",
            "enum": [
              "test",
              "section",
              "part",
              "question",
              "question_ref",
              "distractor",
              "rubric",
              "preauthored_feedback"
            ],
            "description": "Synthesized read-only role mapping from QTI element_name/type_name to the governed assessment_component_role vocabulary. Default to synthesize (read-only) since the element-to-role map may not be fully bijective across all QTI element types.",
            "readOnly": true
          },
          "ordinal": {
            "type": "integer",
            "minimum": 0,
            "description": "Position of this component among its siblings within the parent. Preserves document order from the QTI source 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": [
          "ordinal",
          "createdAt",
          "updatedAt"
        ]
      },
      "AssessmentTestProfile": {
        "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 (NCName), unique within the tenant. The natural key of the base assessment test."
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "The test title used by authors and assessment workflows."
          },
          "isMasteryGate": {
            "type": "boolean",
            "description": "Typed structural fact: whether this test is a mastery gate. Set at write time by the author/import adapter; never inferred at read time from producer URL, subject, or grade. The enforceable gate machinery lives on the Curriculum gating member."
          },
          "testType": {
            "type": "string",
            "enum": [
              "end_of_course",
              "end_of_grade",
              "test_out",
              "placement",
              "diagnostic",
              "screener"
            ],
            "description": "The Alpha test-type vocabulary."
          },
          "assessmentRole": {
            "type": "string",
            "enum": [
              "form",
              "spec",
              "bank"
            ],
            "description": "The assessment role of this test object: a concrete form, the blueprint spec overlay, or the bank overlay."
          },
          "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",
          "createdAt",
          "updatedAt"
        ]
      },
      "CatalogFacet": {
        "type": "object",
        "properties": {
          "facetKey": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The unique facet identifier within the tenant — the natural key. Immutable once created; consumers reference this key in assignments and filters."
          },
          "valueType": {
            "type": "string",
            "enum": [
              "string",
              "number",
              "boolean",
              "enum"
            ],
            "description": "The data type of values this facet accepts. Governs validation of facet assignments: 'enum' requires values drawn from allowed_values; 'string'/'number'/'boolean' enforce type shape."
          },
          "allowedValues": {
            "type": "object",
            "description": "The governed value set for this facet (jsonb). For value_type 'enum', this is the closed set of legal values. For other types, may carry validation bounds or be null. Structure is facet-specific; the runtime hook validates assignments against this payload.",
            "additionalProperties": true
          },
          "grain": {
            "type": "string",
            "enum": [
              "item",
              "version",
              "component",
              "media_asset"
            ],
            "description": "The granularity level at which this facet is assigned: 'item' (one value per content item), 'version' (per content version), 'component' (per assessment component), or 'media_asset' (per media asset). Determines which content entity the facet assignment references."
          },
          "description": {
            "type": "string",
            "maxLength": 2000,
            "description": "Human-readable description of what this facet represents and how it should be used by content authors."
          },
          "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": [
          "facetKey",
          "valueType",
          "grain",
          "updatedAt"
        ]
      },
      "CatalogFacetAssignment": {
        "type": "object",
        "properties": {
          "assignmentId": {
            "type": "string",
            "format": "uuid",
            "description": "Surrogate assignment identifier — the natural key for this assignment row."
          },
          "contentId": {
            "type": "string",
            "format": "uuid",
            "description": "The content item this facet value is assigned to. Two-leg composite FK into qti:artifact (tenantId, contentId) — enforced by hook."
          },
          "facetKey": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The governed facet this assignment instantiates. Must reference an existing catalogFacet entry in the same tenant.",
            "x-references": "catalogFacet.facetKey",
            "x-onDelete": "restrict"
          },
          "facetValue": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1000,
            "description": "The assigned facet value. Validated at write time against the referenced catalogFacet's valueType and allowedValues by a hook."
          },
          "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": [
          "assignmentId",
          "contentId",
          "facetKey",
          "facetValue",
          "updatedAt"
        ]
      },
      "ContentCurriculumLink": {
        "type": "object",
        "properties": {
          "linkId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable link identifier. The natural key (with tenantId) for this curriculum link."
          },
          "contentId": {
            "type": "string",
            "format": "uuid",
            "description": "The content item (qti:artifact) this link originates from. Two-leg composite FK (tenantId, contentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "curriculumNodeId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The curriculum node this content covers, as the curriculum-side string identifier (e.g. 'case:math:7.ee.b.4' or a curriculum courseComponent uuid). HOOK-VALIDATED LOOSE REF per — NOT a DB FK. The create/update hook validates against the imported curriculum repo when present; absent nodes are accepted (content may precede curriculum authoring)."
          },
          "linkKind": {
            "type": "string",
            "enum": [
              "teaches",
              "practices",
              "assesses",
              "supports",
              "extends"
            ],
            "description": "The pedagogical relationship between this content and the curriculum node."
          },
          "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": [
          "linkId",
          "contentId",
          "curriculumNodeId",
          "linkKind",
          "createdAt",
          "updatedAt"
        ]
      },
      "ContentItem": {
        "type": "object",
        "properties": {
          "contentId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable content identifier projected from the QTI artifact surrogate id. The public content catalog key.",
            "readOnly": true
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "The content item title used by authors and catalog workflows to browse, select, and reuse this item."
          },
          "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 content item as a BCP 47 language tag."
          },
          "sourceIdentifier": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The original QTI identifier from the source package. Preserved for import provenance and cross-system traceability."
          },
          "latestVersionId": {
            "type": "string",
            "format": "uuid",
            "description": "The id of the most recent content version, pointing into qti:artifactVersion. Updated on each successful version write."
          },
          "artifactKind": {
            "type": "string",
            "enum": [
              "item",
              "test",
              "stimulus",
              "manifest-resource"
            ],
            "description": "The base QTI artifact kind, restricted to the public Content subset. Drives row-visibility (WHERE clause): only these artifact kinds are visible through the content projection. The non-bijective Alpha contentKind is the canonical typed kind set at write/import."
          },
          "contentKind": {
            "type": "string",
            "enum": [
              "question",
              "test",
              "test_spec",
              "test_bank",
              "article",
              "video",
              "audio",
              "image",
              "interactive",
              "media_asset",
              "external_link",
              "script",
              "stimulus"
            ],
            "description": "The canonical Alpha content kind, set at write/import time. Pass-through of the typed column on qti.artifact. Write requiredness is enforced by Content hooks (base column is nullable)."
          },
          "subtype": {
            "type": "string",
            "enum": [
              "diagram",
              "decodable",
              "script"
            ],
            "description": "Governed content subtype for specialized content variants."
          },
          "sourceSystem": {
            "type": "string",
            "enum": [
              "qti",
              "alpha_content",
              "external_content_import"
            ],
            "description": "The originating system that produced this content item, set at import time by the source adapter."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published",
              "retired",
              "archived"
            ],
            "description": "Content lifecycle status. Archived items are excluded from default catalog reads (row-visibility restrict). Uses retire/archive instead of hard-delete for the retention rule."
          },
          "subjectId": {
            "type": "string",
            "enum": [
              "math",
              "reading",
              "language",
              "science",
              "vocabulary",
              "writing"
            ],
            "description": "Canonical subject identifier from the closed 6-value subject set. Set at write/import via alias fold; public read filters reject display aliases."
          },
          "targetGradeId": {
            "type": "string",
            "enum": [
              "pre_k",
              "k",
              "1",
              "2",
              "3",
              "4",
              "5",
              "6",
              "7",
              "8",
              "9",
              "10",
              "11",
              "12",
              "postsecondary",
              "ungraded"
            ],
            "description": "Target grade level from the alpha_grade_id vocabulary. Set at write; parse-from-name banned."
          },
          "dok": {
            "type": "string",
            "enum": [
              "dok1",
              "dok2",
              "dok3",
              "dok4"
            ],
            "description": "Webb Depth of Knowledge level, per item, distinct from difficulty. Locked vocabulary."
          },
          "expectedXp": {
            "type": "integer",
            "minimum": 0,
            "description": "Student-independent expected XP config field. NOT awarded XP — the XP ledger is Results-owned. The expected_xp_band is a catalog facet assignment derived from this value under policy config."
          },
          "subjectFamily": {
            "type": "string",
            "description": "proxy classification (map vs proxy) as metadata. Optional; only when the content is MAP-related."
          },
          "externalUrl": {
            "type": "string",
            "format": "uri",
            "pattern": "^https?://",
            "description": "Canonical http(s) destination for external-link content."
          },
          "displayUrl": {
            "type": "string",
            "maxLength": 512,
            "description": "Safe author-facing display label for the external destination."
          },
          "openPolicy": {
            "type": "string",
            "enum": [
              "same_tab",
              "new_tab",
              "embedded_iframe_allowed",
              "external_app_handoff"
            ],
            "description": "Governed client navigation policy for external-link content.",
            "default": "new_tab"
          },
          "externalLinkLastValidatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Most recent external destination validation timestamp."
          },
          "phonicsSet": {
            "type": "object",
            "description": "Decodable phonics constraint set (extends.phonics_set jsonb on the QTI union master; API camelCase phonicsSet). Optional; Content hooks require subtype=decodable when present and reject phonicsSet on other subtypes.",
            "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": [
          "contentId",
          "title",
          "language",
          "sourceIdentifier",
          "createdAt",
          "updatedAt"
        ]
      },
      "ContentPolicy": {
        "type": "object",
        "properties": {
          "policyKey": {
            "type": "string",
            "pattern": "^content\\..+$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The namespaced policy key (e.g. 'content.expected_xp_band', 'content.passing_rule_default'). Immutable once created — the key is the natural identifier. All content policy keys are prefixed 'content.' by convention."
          },
          "value": {
            "type": "object",
            "description": "The policy value payload (jsonb). Structure is policy-specific: for expected_xp_band this holds the band cutoffs ({bands: [{label: '0_to_10', min: 0, max: 10},...]}); for passing_rule_default this holds the default passing threshold and rule type.",
            "additionalProperties": true
          },
          "description": {
            "type": "string",
            "maxLength": 2000,
            "description": "Human-readable description of what this policy controls and how consumers should interpret the value payload."
          },
          "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": [
          "policyKey",
          "value",
          "updatedAt"
        ]
      },
      "ContentReference": {
        "type": "object",
        "properties": {
          "referenceId": {
            "type": "string",
            "format": "uuid",
            "description": "The content reference identifier. Together with tenantId this is the composite-natural primary key."
          },
          "fromContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The source content item of this edge. Two-leg composite FK (tenantId, fromContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "toContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The target content item of this edge. Two-leg composite FK (tenantId, toContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "relationshipKind": {
            "type": "string",
            "enum": [
              "embeds",
              "transcript_for",
              "bank_member",
              "series_member",
              "alternative_form_of",
              "caption_for",
              "thumbnail_for",
              "worksheet_for",
              "source_file_for"
            ],
            "description": "The typed relationship between the from and to content items. 'bank_member' rows link a form to its bank (from=bank, to=form) and carry formIndex. 'series_member' rows link a series head to a member (from=series, to=member) and carry position (non-negative integer), distinct from formIndex. Other kinds represent media/asset/structural relationships."
          },
          "formIndex": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based ordering index for bank_member relationships. Only populated when relationshipKind='bank_member'; null otherwise. Drives the form selection order for curriculum's next-form gate and the listTestBankForms sort. Conditional requiredness enforced by write hook / variantSchema."
          },
          "position": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based sequence position for series_member relationships (article-series, image-series, storyboard-series, etc.). Only populated when relationshipKind='series_member'; null otherwise. Distinct from bank_member formIndex — never aliased. Conditional requiredness enforced by write hook / variantSchema."
          },
          "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": [
          "referenceId",
          "fromContentId",
          "toContentId",
          "relationshipKind",
          "updatedAt"
        ]
      },
      "ContentTrustEvidence": {
        "type": "object",
        "properties": {
          "evidenceId": {
            "type": "string",
            "format": "uuid",
            "description": "Surrogate evidence identifier — the natural key for this evidence row."
          },
          "contentId": {
            "type": "string",
            "format": "uuid",
            "description": "The content item this evidence pertains to. Two-leg composite FK into qti:artifact (tenantId, contentId) — enforced by hook."
          },
          "trustStatus": {
            "type": "string",
            "enum": [
              "trusted",
              "degraded",
              "failed",
              "unknown"
            ],
            "description": "The trust determination for this evidence check: 'trusted' (passes all checks), 'degraded' (passes with warnings), 'failed' (does not meet conformance), 'unknown' (check could not complete or has not run)."
          },
          "evidenceType": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The type of validation or conformance check that produced this evidence (e.g. 'qti_schema_validation', 'accessibility_wcag_2_1', 'content_review_approval', 'metadata_completeness')."
          },
          "evidencePayload": {
            "type": "object",
            "description": "The full evidence details as a jsonb payload. Structure varies by evidence_type: may include validation errors, conformance report URIs, reviewer comments, check tool version, or scoring details.",
            "additionalProperties": true
          },
          "recordedAt": {
            "type": "string",
            "format": "date-time",
            "description": "The timestamp when this evidence was recorded by the validation pipeline. Server-authoritative; set at internal write time."
          },
          "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": [
          "evidenceId",
          "contentId",
          "trustStatus",
          "evidenceType",
          "recordedAt",
          "updatedAt"
        ]
      },
      "ContentVersion": {
        "type": "object",
        "properties": {
          "versionId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable version identifier projected from the QTI artifact version surrogate id. The public version key.",
            "readOnly": true
          },
          "versionNumber": {
            "type": "integer",
            "minimum": 1,
            "description": "Monotonically increasing version number within the parent artifact. Renamed for the content delivery surface."
          },
          "etag": {
            "type": "string",
            "maxLength": 32,
            "description": "Synthesized ETag for cache validation and optimistic concurrency — md5 of the XML content hash concatenated with the version number. Read-only; rejected on write.",
            "readOnly": true
          },
          "createdBy": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The authenticated principal who authored this version. Preserved for authorship attribution on the content delivery surface."
          },
          "htmlBody": {
            "type": "string",
            "description": "The sanctioned instructional HTML body (tb-instructional-content markup vocabulary) derived from the QTI delivery body. The public read surface delivers this markup; raw XML stays QTI-owned."
          },
          "contentId": {
            "type": "string",
            "format": "uuid",
            "description": "The parent content item (artifact) this version belongs to. Used to scope version lists by content item."
          },
          "contentHash": {
            "type": "string",
            "minLength": 32,
            "maxLength": 64,
            "description": "The content hash of this version's payload — the bare 64-hex sha256 digest (the base xmlHash column is 32..64 chars). Doubles as the dedup key for import-materialized versions."
          },
          "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",
          "createdBy",
          "contentHash",
          "createdAt",
          "updatedAt"
        ]
      },
      "ExportJob": {
        "type": "object",
        "properties": {
          "exportId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable unique identifier for this export job. The natural id forming the composite PK with tenantId."
          },
          "format": {
            "type": "string",
            "enum": [
              "common_cartridge_1_3"
            ],
            "description": "The export format. Currently only Common Cartridge 1.3 is supported."
          },
          "scope": {
            "type": "object",
            "properties": {
              "curriculumNodeIds": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "The curriculum node identifiers (curriculum-side string ids, e.g. 'case:math:5.nf.a.1') whose referenced content is included in the export bundle."
              },
              "courseComponentId": {
                "type": "string",
                "format": "uuid",
                "description": "A single course component identifier whose content tree is exported."
              }
            },
            "description": "The export scope: which curriculum nodes or course component to bundle. Exactly one of curriculumNodeIds or courseComponentId is provided.",
            "x-storage": "jsonb"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "completed",
              "failed"
            ],
            "description": "Processing status of this export job. The export command writes pending; the hook transitions to completed or failed on outcome."
          },
          "artifactHash": {
            "type": "string",
            "maxLength": 128,
            "description": "SHA-256 hash of the produced Common Cartridge ZIP artifact. Null until the export completes successfully.",
            "nullable": true
          },
          "downloadUri": {
            "type": "string",
            "format": "uri",
            "description": "Object-storage URI for the produced CC bundle. Clients fetch bytes out-of-band via this reference. Null until the export completes successfully.",
            "nullable": true
          },
          "startedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the export command began processing this job."
          },
          "completedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the export job reached a terminal status (completed or failed). Null while pending or processing.",
            "nullable": 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": [
          "exportId",
          "format",
          "scope",
          "status",
          "startedAt",
          "createdAt",
          "updatedAt"
        ]
      },
      "FreeResponsePart": {
        "type": "object",
        "properties": {
          "partId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable part identifier. The natural key (with tenantId) for this free-response part."
          },
          "contentId": {
            "type": "string",
            "format": "uuid",
            "description": "The question (qti:artifact) this free-response part belongs to. Two-leg composite FK (tenantId, contentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "prompt": {
            "type": "string",
            "minLength": 1,
            "description": "The free-response prompt text presented to the student."
          },
          "maxPoints": {
            "type": "integer",
            "minimum": 0,
            "description": "Maximum achievable points for this part."
          },
          "rubricId": {
            "type": "string",
            "format": "uuid",
            "description": "Optional reference to a question rubric used for grading this part. Nullable intra-module FK into questionRubric.",
            "x-references": "questionRubric.rubricId",
            "x-onDelete": "restrict"
          },
          "ordinal": {
            "type": "integer",
            "minimum": 0,
            "description": "Zero-based display/evaluation order of this part within the question."
          },
          "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": [
          "partId",
          "contentId",
          "prompt",
          "maxPoints",
          "ordinal",
          "createdAt",
          "updatedAt"
        ]
      },
      "ImportBatch": {
        "type": "object",
        "properties": {
          "batchId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable unique identifier for this import batch. The natural id forming the composite PK with tenantId."
          },
          "sourceSystem": {
            "type": "string",
            "enum": [
              "qti",
              "alpha_content",
              "external_content_import"
            ],
            "description": "The originating system that produced this import batch. Determines which import door (importQtiPackage vs importTimebackProduction) wrote the receipt."
          },
          "packageHash": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "SHA-256 hash of the imported package bytes. Used as the domain-level dedup key (same tenant + same hash = same content). The hook owns second-layer dedup against this field."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "completed",
              "failed",
              "quarantined"
            ],
            "description": "Processing status of this import batch. The import command writes pending/processing; the hook transitions to completed, failed, or quarantined on outcome."
          },
          "itemCount": {
            "type": "integer",
            "minimum": 0,
            "description": "Total number of content items in the import package."
          },
          "quarantineCount": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of items that failed schema validation or alias-fold and were quarantined rather than materialized."
          },
          "errorSummary": {
            "type": "string",
            "maxLength": 4000,
            "description": "Human-readable summary of errors encountered during processing. Null when the batch completed without errors.",
            "nullable": true
          },
          "startedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the import command began processing this batch."
          },
          "completedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the import batch reached a terminal status (completed, failed, or quarantined). Null while pending or processing.",
            "nullable": 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": [
          "batchId",
          "sourceSystem",
          "packageHash",
          "status",
          "itemCount",
          "quarantineCount",
          "startedAt",
          "createdAt",
          "updatedAt"
        ]
      },
      "InteractiveComposition": {
        "type": "object",
        "properties": {
          "contentId": {
            "type": "string",
            "format": "uuid",
            "description": "The interactive article/video content item this composition belongs to.",
            "x-references": "qti:artifact.id",
            "x-onDelete": "cascade"
          },
          "versionId": {
            "type": "string",
            "format": "uuid",
            "description": "Optional immutable content version the composition is pinned to."
          },
          "compositionType": {
            "type": "string",
            "enum": [
              "interactive_article",
              "interactive_video"
            ],
            "description": "Selects the article segments or video cues variant."
          },
          "mediaAssetRef": {
            "type": "object",
            "description": "Required media reference for an interactive video; contains mediaId."
          },
          "durationSeconds": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Positive video duration. Cue timestamps must be below this value."
          },
          "segments": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Ordered article segment/question bindings."
          },
          "cues": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Ordered video cue/question bindings."
          },
          "validationContract": {
            "type": "object",
            "description": "Server-owned declaration of the invariants checked when the composition was stored.",
            "readOnly": true
          }
        },
        "required": [
          "contentId",
          "compositionType"
        ]
      },
      "MediaAsset": {
        "type": "object",
        "properties": {
          "mediaAssetId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable media asset identifier projected from the QTI package resource surrogate id.",
            "readOnly": true
          },
          "resourceIdentifier": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1024,
            "description": "The manifest resource identifier from the QTI package. Stable across re-imports and used for cross-system traceability of the media file."
          },
          "mediaRole": {
            "type": "string",
            "enum": [
              "primary",
              "supporting",
              "thumbnail",
              "caption",
              "transcript",
              "worksheet",
              "source_file"
            ],
            "description": "The governed media role within a content item's asset collection. Determines how the asset is used in content delivery: primary instructional media, accessibility caption, print worksheet, etc."
          },
          "mediaType": {
            "type": "string",
            "pattern": "^[a-z]+/[a-z0-9.+-]+$",
            "minLength": 3,
            "maxLength": 255,
            "description": "The authoritative MIME type of this media asset (e.g. image/png, video/mp4, text/vtt). Set at import with format validation."
          },
          "deliveryPolicy": {
            "type": "string",
            "enum": [
              "inline",
              "download",
              "stream",
              "external_link"
            ],
            "description": "How this media asset should be delivered to the learner: rendered inline in content markup, offered as a file download, streamed progressively (audio/video), or linked externally."
          },
          "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": [
          "mediaAssetId",
          "resourceIdentifier",
          "createdAt",
          "updatedAt"
        ]
      },
      "QuestionRubric": {
        "type": "object",
        "properties": {
          "rubricId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable rubric identifier. The natural key (with tenantId) for this rubric block."
          },
          "contentId": {
            "type": "string",
            "format": "uuid",
            "description": "The question (qti:artifact) this rubric belongs to. Two-leg composite FK (tenantId, contentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "rubricType": {
            "type": "string",
            "enum": [
              "analytic",
              "holistic"
            ],
            "description": "The rubric scoring model: analytic (multi-criterion with independent levels) or holistic (single overall scale)."
          },
          "maxPoints": {
            "type": "integer",
            "minimum": 1,
            "description": "Maximum achievable points on this rubric. Must be at least 1."
          },
          "criteria": {
            "type": "object",
            "description": "The rubric criteria and performance levels. For analytic rubrics: an array of criterion objects each with levels. For holistic: a single scale with levels. Structure varies by rubric_type; validated by the write hook.",
            "x-storage": "jsonb"
          },
          "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": [
          "rubricId",
          "contentId",
          "rubricType",
          "maxPoints",
          "criteria",
          "createdAt",
          "updatedAt"
        ]
      },
      "TestBank": {
        "type": "object",
        "properties": {
          "bankId": {
            "type": "string",
            "format": "uuid",
            "description": "The test bank identifier. Together with tenantId this is the composite-natural primary key."
          },
          "specId": {
            "type": "string",
            "format": "uuid",
            "description": "FK to the test specification (blueprint) that governs this bank. Same-tenant composite FK (tenantId, specId) -> testSpec(tenantId, specId). A bank is always governed by exactly one spec; deleting the spec while banks reference it is prohibited.",
            "x-references": "testSpec.specId",
            "x-onDelete": "restrict"
          },
          "membershipRule": {
            "type": "string",
            "enum": [
              "manual",
              "auto_from_spec",
              "auto_from_tag"
            ],
            "description": "The rule governing how forms are admitted to this bank. 'manual' requires explicit bank_member contentReference rows; 'auto_from_spec' admits forms matching the spec's KC coverage grid; 'auto_from_tag' admits forms by catalog facet assignment."
          },
          "minForms": {
            "type": "integer",
            "minimum": 1,
            "description": "The minimum number of forms this bank must contain before it is considered usable for gating. Drives the bank_exhausted 409 when curriculum's next-form selector finds fewer available unseen forms than this threshold."
          },
          "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": [
          "bankId",
          "specId",
          "membershipRule",
          "minForms",
          "updatedAt"
        ]
      },
      "TestSpec": {
        "type": "object",
        "properties": {
          "specId": {
            "type": "string",
            "format": "uuid",
            "description": "The test specification identifier. Together with tenantId this is the composite-natural primary key."
          },
          "passingRule": {
            "type": "string",
            "pattern": "^content\\..+$",
            "minLength": 1,
            "maxLength": 255,
            "description": "Reference to the contentPolicy row (policyKey) that defines the passing cutoff for this spec. The 89.5 hardcode is replaced by a policy config reference — never inline.",
            "x-references": "contentPolicy.policyKey",
            "x-onDelete": "restrict"
          },
          "minForms": {
            "type": "integer",
            "minimum": 1,
            "description": "The minimum number of distinct forms the bank must contain before this spec is considered complete. Drives the bank exhaustion 409 in curriculum's next-form gate."
          },
          "kcCoverage": {
            "type": "object",
            "description": "The DOK coverage grid: a JSONB structure mapping knowledge-component identifiers to required DOK level coverage targets per blueprint cell. Shape is implementation-defined per the spec author. Validated by write hook against the spec's declared KC vocabulary.",
            "additionalProperties": true
          },
          "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": [
          "specId",
          "passingRule",
          "minForms",
          "kcCoverage",
          "updatedAt"
        ]
      },
      "UpdateAssessmentTestProfileRequest": {
        "type": "object",
        "description": "Update-AssessmentTestProfile 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."
          },
          "isMasteryGate": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Typed structural fact: whether this test is a mastery gate. Set at write time by the author/import adapter; never inferred at read time from producer URL, subject, or grade. The enforceable gate machinery lives on the Curriculum gating member."
          },
          "testType": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "end_of_course",
              "end_of_grade",
              "test_out",
              "placement",
              "diagnostic",
              "screener",
              null
            ],
            "description": "The Alpha test-type vocabulary."
          },
          "assessmentRole": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "form",
              "spec",
              "bank",
              null
            ],
            "description": "The assessment role of this test object: a concrete form, the blueprint spec overlay, or the bank overlay."
          }
        }
      },
      "CreateCatalogFacetRequest": {
        "type": "object",
        "description": "Create-CatalogFacet request body (readOnly/server-managed fields excluded).",
        "required": [
          "facetKey",
          "valueType",
          "grain"
        ],
        "additionalProperties": false,
        "properties": {
          "facetKey": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The unique facet identifier within the tenant — the natural key. Immutable once created; consumers reference this key in assignments and filters."
          },
          "valueType": {
            "type": "string",
            "enum": [
              "string",
              "number",
              "boolean",
              "enum"
            ],
            "description": "The data type of values this facet accepts. Governs validation of facet assignments: 'enum' requires values drawn from allowed_values; 'string'/'number'/'boolean' enforce type shape."
          },
          "allowedValues": {
            "type": "object",
            "description": "The governed value set for this facet (jsonb). For value_type 'enum', this is the closed set of legal values. For other types, may carry validation bounds or be null. Structure is facet-specific; the runtime hook validates assignments against this payload.",
            "additionalProperties": true
          },
          "grain": {
            "type": "string",
            "enum": [
              "item",
              "version",
              "component",
              "media_asset"
            ],
            "description": "The granularity level at which this facet is assigned: 'item' (one value per content item), 'version' (per content version), 'component' (per assessment component), or 'media_asset' (per media asset). Determines which content entity the facet assignment references."
          },
          "description": {
            "type": "string",
            "maxLength": 2000,
            "description": "Human-readable description of what this facet represents and how it should be used by content authors."
          }
        }
      },
      "UpdateCatalogFacetRequest": {
        "type": "object",
        "description": "Update-CatalogFacet request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "valueType": {
            "type": "string",
            "enum": [
              "string",
              "number",
              "boolean",
              "enum"
            ],
            "description": "The data type of values this facet accepts. Governs validation of facet assignments: 'enum' requires values drawn from allowed_values; 'string'/'number'/'boolean' enforce type shape."
          },
          "allowedValues": {
            "type": [
              "object",
              "null"
            ],
            "description": "The governed value set for this facet (jsonb). For value_type 'enum', this is the closed set of legal values. For other types, may carry validation bounds or be null. Structure is facet-specific; the runtime hook validates assignments against this payload.",
            "additionalProperties": true
          },
          "grain": {
            "type": "string",
            "enum": [
              "item",
              "version",
              "component",
              "media_asset"
            ],
            "description": "The granularity level at which this facet is assigned: 'item' (one value per content item), 'version' (per content version), 'component' (per assessment component), or 'media_asset' (per media asset). Determines which content entity the facet assignment references."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2000,
            "description": "Human-readable description of what this facet represents and how it should be used by content authors."
          }
        }
      },
      "CreateContentCurriculumLinkRequest": {
        "type": "object",
        "description": "Create-ContentCurriculumLink request body (readOnly/server-managed fields excluded).",
        "required": [
          "linkId",
          "contentId",
          "curriculumNodeId",
          "linkKind"
        ],
        "additionalProperties": false,
        "properties": {
          "linkId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable link identifier. The natural key (with tenantId) for this curriculum link."
          },
          "contentId": {
            "type": "string",
            "format": "uuid",
            "description": "The content item (qti:artifact) this link originates from. Two-leg composite FK (tenantId, contentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "curriculumNodeId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The curriculum node this content covers, as the curriculum-side string identifier (e.g. 'case:math:7.ee.b.4' or a curriculum courseComponent uuid). HOOK-VALIDATED LOOSE REF per — NOT a DB FK. The create/update hook validates against the imported curriculum repo when present; absent nodes are accepted (content may precede curriculum authoring)."
          },
          "linkKind": {
            "type": "string",
            "enum": [
              "teaches",
              "practices",
              "assesses",
              "supports",
              "extends"
            ],
            "description": "The pedagogical relationship between this content and the curriculum node."
          }
        }
      },
      "UpdateContentCurriculumLinkRequest": {
        "type": "object",
        "description": "Update-ContentCurriculumLink request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {}
      },
      "CreateContentItemRequest": {
        "type": "object",
        "description": "Create-ContentItem request body (readOnly/server-managed fields excluded).",
        "required": [
          "title",
          "language",
          "sourceIdentifier"
        ],
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "description": "The content item title used by authors and catalog workflows to browse, select, and reuse this item."
          },
          "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 content item as a BCP 47 language tag."
          },
          "sourceIdentifier": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The original QTI identifier from the source package. Preserved for import provenance and cross-system traceability."
          },
          "latestVersionId": {
            "type": "string",
            "format": "uuid",
            "description": "The id of the most recent content version, pointing into qti:artifactVersion. Updated on each successful version write."
          },
          "artifactKind": {
            "type": "string",
            "enum": [
              "item",
              "test",
              "stimulus",
              "manifest-resource"
            ],
            "description": "The base QTI artifact kind, restricted to the public Content subset. Drives row-visibility (WHERE clause): only these artifact kinds are visible through the content projection. The non-bijective Alpha contentKind is the canonical typed kind set at write/import."
          },
          "contentKind": {
            "type": "string",
            "enum": [
              "question",
              "test",
              "test_spec",
              "test_bank",
              "article",
              "video",
              "audio",
              "image",
              "interactive",
              "media_asset",
              "external_link",
              "script",
              "stimulus"
            ],
            "description": "The canonical Alpha content kind, set at write/import time. Pass-through of the typed column on qti.artifact. Write requiredness is enforced by Content hooks (base column is nullable)."
          },
          "subtype": {
            "type": "string",
            "enum": [
              "diagram",
              "decodable",
              "script"
            ],
            "description": "Governed content subtype for specialized content variants."
          },
          "sourceSystem": {
            "type": "string",
            "enum": [
              "qti",
              "alpha_content",
              "external_content_import"
            ],
            "description": "The originating system that produced this content item, set at import time by the source adapter."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published",
              "retired",
              "archived"
            ],
            "description": "Content lifecycle status. Archived items are excluded from default catalog reads (row-visibility restrict). Uses retire/archive instead of hard-delete for the retention rule."
          },
          "subjectId": {
            "type": "string",
            "enum": [
              "math",
              "reading",
              "language",
              "science",
              "vocabulary",
              "writing"
            ],
            "description": "Canonical subject identifier from the closed 6-value subject set. Set at write/import via alias fold; public read filters reject display aliases."
          },
          "targetGradeId": {
            "type": "string",
            "enum": [
              "pre_k",
              "k",
              "1",
              "2",
              "3",
              "4",
              "5",
              "6",
              "7",
              "8",
              "9",
              "10",
              "11",
              "12",
              "postsecondary",
              "ungraded"
            ],
            "description": "Target grade level from the alpha_grade_id vocabulary. Set at write; parse-from-name banned."
          },
          "dok": {
            "type": "string",
            "enum": [
              "dok1",
              "dok2",
              "dok3",
              "dok4"
            ],
            "description": "Webb Depth of Knowledge level, per item, distinct from difficulty. Locked vocabulary."
          },
          "expectedXp": {
            "type": "integer",
            "minimum": 0,
            "description": "Student-independent expected XP config field. NOT awarded XP — the XP ledger is Results-owned. The expected_xp_band is a catalog facet assignment derived from this value under policy config."
          },
          "subjectFamily": {
            "type": "string",
            "description": "proxy classification (map vs proxy) as metadata. Optional; only when the content is MAP-related."
          },
          "externalUrl": {
            "type": "string",
            "format": "uri",
            "pattern": "^https?://",
            "description": "Canonical http(s) destination for external-link content."
          },
          "displayUrl": {
            "type": "string",
            "maxLength": 512,
            "description": "Safe author-facing display label for the external destination."
          },
          "openPolicy": {
            "type": "string",
            "enum": [
              "same_tab",
              "new_tab",
              "embedded_iframe_allowed",
              "external_app_handoff"
            ],
            "description": "Governed client navigation policy for external-link content.",
            "default": "new_tab"
          },
          "externalLinkLastValidatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Most recent external destination validation timestamp."
          },
          "phonicsSet": {
            "type": "object",
            "description": "Decodable phonics constraint set (extends.phonics_set jsonb on the QTI union master; API camelCase phonicsSet). Optional; Content hooks require subtype=decodable when present and reject phonicsSet on other subtypes.",
            "additionalProperties": true
          }
        }
      },
      "UpdateContentItemRequest": {
        "type": "object",
        "description": "Update-ContentItem 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 content item title used by authors and catalog workflows to browse, select, and reuse this item."
          },
          "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 content item as a BCP 47 language tag."
          },
          "latestVersionId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The id of the most recent content version, pointing into qti:artifactVersion. Updated on each successful version write."
          },
          "contentKind": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "question",
              "test",
              "test_spec",
              "test_bank",
              "article",
              "video",
              "audio",
              "image",
              "interactive",
              "media_asset",
              "external_link",
              "script",
              "stimulus",
              null
            ],
            "description": "The canonical Alpha content kind, set at write/import time. Pass-through of the typed column on qti.artifact. Write requiredness is enforced by Content hooks (base column is nullable)."
          },
          "subtype": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "diagram",
              "decodable",
              "script",
              null
            ],
            "description": "Governed content subtype for specialized content variants."
          },
          "sourceSystem": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "qti",
              "alpha_content",
              "external_content_import",
              null
            ],
            "description": "The originating system that produced this content item, set at import time by the source adapter."
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "draft",
              "published",
              "retired",
              "archived",
              null
            ],
            "description": "Content lifecycle status. Archived items are excluded from default catalog reads (row-visibility restrict). Uses retire/archive instead of hard-delete for the retention rule."
          },
          "subjectId": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "math",
              "reading",
              "language",
              "science",
              "vocabulary",
              "writing",
              null
            ],
            "description": "Canonical subject identifier from the closed 6-value subject set. Set at write/import via alias fold; public read filters reject display aliases."
          },
          "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 level from the alpha_grade_id vocabulary. Set at write; parse-from-name banned."
          },
          "dok": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "dok1",
              "dok2",
              "dok3",
              "dok4",
              null
            ],
            "description": "Webb Depth of Knowledge level, per item, distinct from difficulty. Locked vocabulary."
          },
          "expectedXp": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Student-independent expected XP config field. NOT awarded XP — the XP ledger is Results-owned. The expected_xp_band is a catalog facet assignment derived from this value under policy config."
          },
          "subjectFamily": {
            "type": [
              "string",
              "null"
            ],
            "description": "proxy classification (map vs proxy) as metadata. Optional; only when the content is MAP-related."
          },
          "externalUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "pattern": "^https?://",
            "description": "Canonical http(s) destination for external-link content."
          },
          "displayUrl": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 512,
            "description": "Safe author-facing display label for the external destination."
          },
          "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.",
            "default": "new_tab"
          },
          "externalLinkLastValidatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Most recent external destination validation timestamp."
          },
          "phonicsSet": {
            "type": [
              "object",
              "null"
            ],
            "description": "Decodable phonics constraint set (extends.phonics_set jsonb on the QTI union master; API camelCase phonicsSet). Optional; Content hooks require subtype=decodable when present and reject phonicsSet on other subtypes.",
            "additionalProperties": true
          }
        }
      },
      "CreateContentPolicyRequest": {
        "type": "object",
        "description": "Create-ContentPolicy request body (readOnly/server-managed fields excluded).",
        "required": [
          "policyKey",
          "value"
        ],
        "additionalProperties": false,
        "properties": {
          "policyKey": {
            "type": "string",
            "pattern": "^content\\..+$",
            "minLength": 1,
            "maxLength": 255,
            "description": "The namespaced policy key (e.g. 'content.expected_xp_band', 'content.passing_rule_default'). Immutable once created — the key is the natural identifier. All content policy keys are prefixed 'content.' by convention."
          },
          "value": {
            "type": "object",
            "description": "The policy value payload (jsonb). Structure is policy-specific: for expected_xp_band this holds the band cutoffs ({bands: [{label: '0_to_10', min: 0, max: 10},...]}); for passing_rule_default this holds the default passing threshold and rule type.",
            "additionalProperties": true
          },
          "description": {
            "type": "string",
            "maxLength": 2000,
            "description": "Human-readable description of what this policy controls and how consumers should interpret the value payload."
          }
        }
      },
      "UpdateContentPolicyRequest": {
        "type": "object",
        "description": "Update-ContentPolicy request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "value": {
            "type": "object",
            "description": "The policy value payload (jsonb). Structure is policy-specific: for expected_xp_band this holds the band cutoffs ({bands: [{label: '0_to_10', min: 0, max: 10},...]}); for passing_rule_default this holds the default passing threshold and rule type.",
            "additionalProperties": true
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2000,
            "description": "Human-readable description of what this policy controls and how consumers should interpret the value payload."
          }
        }
      },
      "CreateContentReferenceRequestEmbeds": {
        "type": "object",
        "description": "Create-ContentReference request body for relationshipKind \"embeds\" (variant-required fields enforced).",
        "required": [
          "referenceId",
          "fromContentId",
          "toContentId",
          "relationshipKind"
        ],
        "additionalProperties": false,
        "properties": {
          "referenceId": {
            "type": "string",
            "format": "uuid",
            "description": "The content reference identifier. Together with tenantId this is the composite-natural primary key."
          },
          "fromContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The source content item of this edge. Two-leg composite FK (tenantId, fromContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "toContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The target content item of this edge. Two-leg composite FK (tenantId, toContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "relationshipKind": {
            "type": "string",
            "enum": [
              "embeds"
            ],
            "description": "The typed relationship between the from and to content items. 'bank_member' rows link a form to its bank (from=bank, to=form) and carry formIndex. 'series_member' rows link a series head to a member (from=series, to=member) and carry position (non-negative integer), distinct from formIndex. Other kinds represent media/asset/structural relationships."
          },
          "formIndex": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based ordering index for bank_member relationships. Only populated when relationshipKind='bank_member'; null otherwise. Drives the form selection order for curriculum's next-form gate and the listTestBankForms sort. Conditional requiredness enforced by write hook / variantSchema."
          },
          "position": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based sequence position for series_member relationships (article-series, image-series, storyboard-series, etc.). Only populated when relationshipKind='series_member'; null otherwise. Distinct from bank_member formIndex — never aliased. Conditional requiredness enforced by write hook / variantSchema."
          }
        }
      },
      "CreateContentReferenceRequestTranscriptFor": {
        "type": "object",
        "description": "Create-ContentReference request body for relationshipKind \"transcript_for\" (variant-required fields enforced).",
        "required": [
          "referenceId",
          "fromContentId",
          "toContentId",
          "relationshipKind"
        ],
        "additionalProperties": false,
        "properties": {
          "referenceId": {
            "type": "string",
            "format": "uuid",
            "description": "The content reference identifier. Together with tenantId this is the composite-natural primary key."
          },
          "fromContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The source content item of this edge. Two-leg composite FK (tenantId, fromContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "toContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The target content item of this edge. Two-leg composite FK (tenantId, toContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "relationshipKind": {
            "type": "string",
            "enum": [
              "transcript_for"
            ],
            "description": "The typed relationship between the from and to content items. 'bank_member' rows link a form to its bank (from=bank, to=form) and carry formIndex. 'series_member' rows link a series head to a member (from=series, to=member) and carry position (non-negative integer), distinct from formIndex. Other kinds represent media/asset/structural relationships."
          },
          "formIndex": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based ordering index for bank_member relationships. Only populated when relationshipKind='bank_member'; null otherwise. Drives the form selection order for curriculum's next-form gate and the listTestBankForms sort. Conditional requiredness enforced by write hook / variantSchema."
          },
          "position": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based sequence position for series_member relationships (article-series, image-series, storyboard-series, etc.). Only populated when relationshipKind='series_member'; null otherwise. Distinct from bank_member formIndex — never aliased. Conditional requiredness enforced by write hook / variantSchema."
          }
        }
      },
      "CreateContentReferenceRequestBankMember": {
        "type": "object",
        "description": "Create-ContentReference request body for relationshipKind \"bank_member\" (variant-required fields enforced).",
        "required": [
          "referenceId",
          "fromContentId",
          "toContentId",
          "relationshipKind",
          "formIndex"
        ],
        "additionalProperties": false,
        "properties": {
          "referenceId": {
            "type": "string",
            "format": "uuid",
            "description": "The content reference identifier. Together with tenantId this is the composite-natural primary key."
          },
          "fromContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The source content item of this edge. Two-leg composite FK (tenantId, fromContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "toContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The target content item of this edge. Two-leg composite FK (tenantId, toContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "relationshipKind": {
            "type": "string",
            "enum": [
              "bank_member"
            ],
            "description": "The typed relationship between the from and to content items. 'bank_member' rows link a form to its bank (from=bank, to=form) and carry formIndex. 'series_member' rows link a series head to a member (from=series, to=member) and carry position (non-negative integer), distinct from formIndex. Other kinds represent media/asset/structural relationships."
          },
          "formIndex": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based ordering index for bank_member relationships. Only populated when relationshipKind='bank_member'; null otherwise. Drives the form selection order for curriculum's next-form gate and the listTestBankForms sort. Conditional requiredness enforced by write hook / variantSchema."
          },
          "position": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based sequence position for series_member relationships (article-series, image-series, storyboard-series, etc.). Only populated when relationshipKind='series_member'; null otherwise. Distinct from bank_member formIndex — never aliased. Conditional requiredness enforced by write hook / variantSchema."
          }
        }
      },
      "CreateContentReferenceRequestSeriesMember": {
        "type": "object",
        "description": "Create-ContentReference request body for relationshipKind \"series_member\" (variant-required fields enforced).",
        "required": [
          "referenceId",
          "fromContentId",
          "toContentId",
          "relationshipKind",
          "position"
        ],
        "additionalProperties": false,
        "properties": {
          "referenceId": {
            "type": "string",
            "format": "uuid",
            "description": "The content reference identifier. Together with tenantId this is the composite-natural primary key."
          },
          "fromContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The source content item of this edge. Two-leg composite FK (tenantId, fromContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "toContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The target content item of this edge. Two-leg composite FK (tenantId, toContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "relationshipKind": {
            "type": "string",
            "enum": [
              "series_member"
            ],
            "description": "The typed relationship between the from and to content items. 'bank_member' rows link a form to its bank (from=bank, to=form) and carry formIndex. 'series_member' rows link a series head to a member (from=series, to=member) and carry position (non-negative integer), distinct from formIndex. Other kinds represent media/asset/structural relationships."
          },
          "formIndex": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based ordering index for bank_member relationships. Only populated when relationshipKind='bank_member'; null otherwise. Drives the form selection order for curriculum's next-form gate and the listTestBankForms sort. Conditional requiredness enforced by write hook / variantSchema."
          },
          "position": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based sequence position for series_member relationships (article-series, image-series, storyboard-series, etc.). Only populated when relationshipKind='series_member'; null otherwise. Distinct from bank_member formIndex — never aliased. Conditional requiredness enforced by write hook / variantSchema."
          }
        }
      },
      "CreateContentReferenceRequestAlternativeFormOf": {
        "type": "object",
        "description": "Create-ContentReference request body for relationshipKind \"alternative_form_of\" (variant-required fields enforced).",
        "required": [
          "referenceId",
          "fromContentId",
          "toContentId",
          "relationshipKind"
        ],
        "additionalProperties": false,
        "properties": {
          "referenceId": {
            "type": "string",
            "format": "uuid",
            "description": "The content reference identifier. Together with tenantId this is the composite-natural primary key."
          },
          "fromContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The source content item of this edge. Two-leg composite FK (tenantId, fromContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "toContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The target content item of this edge. Two-leg composite FK (tenantId, toContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "relationshipKind": {
            "type": "string",
            "enum": [
              "alternative_form_of"
            ],
            "description": "The typed relationship between the from and to content items. 'bank_member' rows link a form to its bank (from=bank, to=form) and carry formIndex. 'series_member' rows link a series head to a member (from=series, to=member) and carry position (non-negative integer), distinct from formIndex. Other kinds represent media/asset/structural relationships."
          },
          "formIndex": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based ordering index for bank_member relationships. Only populated when relationshipKind='bank_member'; null otherwise. Drives the form selection order for curriculum's next-form gate and the listTestBankForms sort. Conditional requiredness enforced by write hook / variantSchema."
          },
          "position": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based sequence position for series_member relationships (article-series, image-series, storyboard-series, etc.). Only populated when relationshipKind='series_member'; null otherwise. Distinct from bank_member formIndex — never aliased. Conditional requiredness enforced by write hook / variantSchema."
          }
        }
      },
      "CreateContentReferenceRequestCaptionFor": {
        "type": "object",
        "description": "Create-ContentReference request body for relationshipKind \"caption_for\" (variant-required fields enforced).",
        "required": [
          "referenceId",
          "fromContentId",
          "toContentId",
          "relationshipKind"
        ],
        "additionalProperties": false,
        "properties": {
          "referenceId": {
            "type": "string",
            "format": "uuid",
            "description": "The content reference identifier. Together with tenantId this is the composite-natural primary key."
          },
          "fromContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The source content item of this edge. Two-leg composite FK (tenantId, fromContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "toContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The target content item of this edge. Two-leg composite FK (tenantId, toContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "relationshipKind": {
            "type": "string",
            "enum": [
              "caption_for"
            ],
            "description": "The typed relationship between the from and to content items. 'bank_member' rows link a form to its bank (from=bank, to=form) and carry formIndex. 'series_member' rows link a series head to a member (from=series, to=member) and carry position (non-negative integer), distinct from formIndex. Other kinds represent media/asset/structural relationships."
          },
          "formIndex": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based ordering index for bank_member relationships. Only populated when relationshipKind='bank_member'; null otherwise. Drives the form selection order for curriculum's next-form gate and the listTestBankForms sort. Conditional requiredness enforced by write hook / variantSchema."
          },
          "position": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based sequence position for series_member relationships (article-series, image-series, storyboard-series, etc.). Only populated when relationshipKind='series_member'; null otherwise. Distinct from bank_member formIndex — never aliased. Conditional requiredness enforced by write hook / variantSchema."
          }
        }
      },
      "CreateContentReferenceRequestThumbnailFor": {
        "type": "object",
        "description": "Create-ContentReference request body for relationshipKind \"thumbnail_for\" (variant-required fields enforced).",
        "required": [
          "referenceId",
          "fromContentId",
          "toContentId",
          "relationshipKind"
        ],
        "additionalProperties": false,
        "properties": {
          "referenceId": {
            "type": "string",
            "format": "uuid",
            "description": "The content reference identifier. Together with tenantId this is the composite-natural primary key."
          },
          "fromContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The source content item of this edge. Two-leg composite FK (tenantId, fromContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "toContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The target content item of this edge. Two-leg composite FK (tenantId, toContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "relationshipKind": {
            "type": "string",
            "enum": [
              "thumbnail_for"
            ],
            "description": "The typed relationship between the from and to content items. 'bank_member' rows link a form to its bank (from=bank, to=form) and carry formIndex. 'series_member' rows link a series head to a member (from=series, to=member) and carry position (non-negative integer), distinct from formIndex. Other kinds represent media/asset/structural relationships."
          },
          "formIndex": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based ordering index for bank_member relationships. Only populated when relationshipKind='bank_member'; null otherwise. Drives the form selection order for curriculum's next-form gate and the listTestBankForms sort. Conditional requiredness enforced by write hook / variantSchema."
          },
          "position": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based sequence position for series_member relationships (article-series, image-series, storyboard-series, etc.). Only populated when relationshipKind='series_member'; null otherwise. Distinct from bank_member formIndex — never aliased. Conditional requiredness enforced by write hook / variantSchema."
          }
        }
      },
      "CreateContentReferenceRequestWorksheetFor": {
        "type": "object",
        "description": "Create-ContentReference request body for relationshipKind \"worksheet_for\" (variant-required fields enforced).",
        "required": [
          "referenceId",
          "fromContentId",
          "toContentId",
          "relationshipKind"
        ],
        "additionalProperties": false,
        "properties": {
          "referenceId": {
            "type": "string",
            "format": "uuid",
            "description": "The content reference identifier. Together with tenantId this is the composite-natural primary key."
          },
          "fromContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The source content item of this edge. Two-leg composite FK (tenantId, fromContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "toContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The target content item of this edge. Two-leg composite FK (tenantId, toContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "relationshipKind": {
            "type": "string",
            "enum": [
              "worksheet_for"
            ],
            "description": "The typed relationship between the from and to content items. 'bank_member' rows link a form to its bank (from=bank, to=form) and carry formIndex. 'series_member' rows link a series head to a member (from=series, to=member) and carry position (non-negative integer), distinct from formIndex. Other kinds represent media/asset/structural relationships."
          },
          "formIndex": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based ordering index for bank_member relationships. Only populated when relationshipKind='bank_member'; null otherwise. Drives the form selection order for curriculum's next-form gate and the listTestBankForms sort. Conditional requiredness enforced by write hook / variantSchema."
          },
          "position": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based sequence position for series_member relationships (article-series, image-series, storyboard-series, etc.). Only populated when relationshipKind='series_member'; null otherwise. Distinct from bank_member formIndex — never aliased. Conditional requiredness enforced by write hook / variantSchema."
          }
        }
      },
      "CreateContentReferenceRequestSourceFileFor": {
        "type": "object",
        "description": "Create-ContentReference request body for relationshipKind \"source_file_for\" (variant-required fields enforced).",
        "required": [
          "referenceId",
          "fromContentId",
          "toContentId",
          "relationshipKind"
        ],
        "additionalProperties": false,
        "properties": {
          "referenceId": {
            "type": "string",
            "format": "uuid",
            "description": "The content reference identifier. Together with tenantId this is the composite-natural primary key."
          },
          "fromContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The source content item of this edge. Two-leg composite FK (tenantId, fromContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "toContentId": {
            "type": "string",
            "format": "uuid",
            "description": "The target content item of this edge. Two-leg composite FK (tenantId, toContentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "relationshipKind": {
            "type": "string",
            "enum": [
              "source_file_for"
            ],
            "description": "The typed relationship between the from and to content items. 'bank_member' rows link a form to its bank (from=bank, to=form) and carry formIndex. 'series_member' rows link a series head to a member (from=series, to=member) and carry position (non-negative integer), distinct from formIndex. Other kinds represent media/asset/structural relationships."
          },
          "formIndex": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based ordering index for bank_member relationships. Only populated when relationshipKind='bank_member'; null otherwise. Drives the form selection order for curriculum's next-form gate and the listTestBankForms sort. Conditional requiredness enforced by write hook / variantSchema."
          },
          "position": {
            "type": "integer",
            "minimum": 0,
            "description": "The zero-based sequence position for series_member relationships (article-series, image-series, storyboard-series, etc.). Only populated when relationshipKind='series_member'; null otherwise. Distinct from bank_member formIndex — never aliased. Conditional requiredness enforced by write hook / variantSchema."
          }
        }
      },
      "CreateContentReferenceRequest": {
        "description": "Create-ContentReference request body — a discriminated union on relationshipKind; required fields vary by variant.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/CreateContentReferenceRequestEmbeds"
          },
          {
            "$ref": "#/components/schemas/CreateContentReferenceRequestTranscriptFor"
          },
          {
            "$ref": "#/components/schemas/CreateContentReferenceRequestBankMember"
          },
          {
            "$ref": "#/components/schemas/CreateContentReferenceRequestSeriesMember"
          },
          {
            "$ref": "#/components/schemas/CreateContentReferenceRequestAlternativeFormOf"
          },
          {
            "$ref": "#/components/schemas/CreateContentReferenceRequestCaptionFor"
          },
          {
            "$ref": "#/components/schemas/CreateContentReferenceRequestThumbnailFor"
          },
          {
            "$ref": "#/components/schemas/CreateContentReferenceRequestWorksheetFor"
          },
          {
            "$ref": "#/components/schemas/CreateContentReferenceRequestSourceFileFor"
          }
        ],
        "discriminator": {
          "propertyName": "relationshipKind",
          "mapping": {
            "embeds": "#/components/schemas/CreateContentReferenceRequestEmbeds",
            "transcript_for": "#/components/schemas/CreateContentReferenceRequestTranscriptFor",
            "bank_member": "#/components/schemas/CreateContentReferenceRequestBankMember",
            "series_member": "#/components/schemas/CreateContentReferenceRequestSeriesMember",
            "alternative_form_of": "#/components/schemas/CreateContentReferenceRequestAlternativeFormOf",
            "caption_for": "#/components/schemas/CreateContentReferenceRequestCaptionFor",
            "thumbnail_for": "#/components/schemas/CreateContentReferenceRequestThumbnailFor",
            "worksheet_for": "#/components/schemas/CreateContentReferenceRequestWorksheetFor",
            "source_file_for": "#/components/schemas/CreateContentReferenceRequestSourceFileFor"
          }
        }
      },
      "UpdateContentReferenceRequest": {
        "type": "object",
        "description": "Update-ContentReference request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "formIndex": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "The zero-based ordering index for bank_member relationships. Only populated when relationshipKind='bank_member'; null otherwise. Drives the form selection order for curriculum's next-form gate and the listTestBankForms sort. Conditional requiredness enforced by write hook / variantSchema."
          },
          "position": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "The zero-based sequence position for series_member relationships (article-series, image-series, storyboard-series, etc.). Only populated when relationshipKind='series_member'; null otherwise. Distinct from bank_member formIndex — never aliased. Conditional requiredness enforced by write hook / variantSchema."
          }
        }
      },
      "CreateContentVersionRequest": {
        "type": "object",
        "description": "Create-ContentVersion request body (readOnly/server-managed fields excluded).",
        "required": [
          "versionNumber",
          "createdBy",
          "contentHash"
        ],
        "additionalProperties": false,
        "properties": {
          "versionNumber": {
            "type": "integer",
            "minimum": 1,
            "description": "Monotonically increasing version number within the parent artifact. Renamed for the content delivery surface."
          },
          "createdBy": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "The authenticated principal who authored this version. Preserved for authorship attribution on the content delivery surface."
          },
          "htmlBody": {
            "type": "string",
            "description": "The sanctioned instructional HTML body (tb-instructional-content markup vocabulary) derived from the QTI delivery body. The public read surface delivers this markup; raw XML stays QTI-owned."
          },
          "contentId": {
            "type": "string",
            "format": "uuid",
            "description": "The parent content item (artifact) this version belongs to. Used to scope version lists by content item."
          },
          "contentHash": {
            "type": "string",
            "minLength": 32,
            "maxLength": 64,
            "description": "The content hash of this version's payload — the bare 64-hex sha256 digest (the base xmlHash column is 32..64 chars). Doubles as the dedup key for import-materialized versions."
          }
        }
      },
      "CreateFreeResponsePartRequest": {
        "type": "object",
        "description": "Create-FreeResponsePart request body (readOnly/server-managed fields excluded).",
        "required": [
          "partId",
          "contentId",
          "prompt",
          "maxPoints",
          "ordinal"
        ],
        "additionalProperties": false,
        "properties": {
          "partId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable part identifier. The natural key (with tenantId) for this free-response part."
          },
          "contentId": {
            "type": "string",
            "format": "uuid",
            "description": "The question (qti:artifact) this free-response part belongs to. Two-leg composite FK (tenantId, contentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "prompt": {
            "type": "string",
            "minLength": 1,
            "description": "The free-response prompt text presented to the student."
          },
          "maxPoints": {
            "type": "integer",
            "minimum": 0,
            "description": "Maximum achievable points for this part."
          },
          "rubricId": {
            "type": "string",
            "format": "uuid",
            "description": "Optional reference to a question rubric used for grading this part. Nullable intra-module FK into questionRubric.",
            "x-references": "questionRubric.rubricId",
            "x-onDelete": "restrict"
          },
          "ordinal": {
            "type": "integer",
            "minimum": 0,
            "description": "Zero-based display/evaluation order of this part within the question."
          }
        }
      },
      "UpdateFreeResponsePartRequest": {
        "type": "object",
        "description": "Update-FreeResponsePart request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "prompt": {
            "type": "string",
            "minLength": 1,
            "description": "The free-response prompt text presented to the student."
          },
          "maxPoints": {
            "type": "integer",
            "minimum": 0,
            "description": "Maximum achievable points for this part."
          },
          "rubricId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Optional reference to a question rubric used for grading this part. Nullable intra-module FK into questionRubric.",
            "x-references": "questionRubric.rubricId",
            "x-onDelete": "restrict"
          },
          "ordinal": {
            "type": "integer",
            "minimum": 0,
            "description": "Zero-based display/evaluation order of this part within the question."
          }
        }
      },
      "CreateQuestionRubricRequest": {
        "type": "object",
        "description": "Create-QuestionRubric request body (readOnly/server-managed fields excluded).",
        "required": [
          "rubricId",
          "contentId",
          "rubricType",
          "maxPoints",
          "criteria"
        ],
        "additionalProperties": false,
        "properties": {
          "rubricId": {
            "type": "string",
            "format": "uuid",
            "description": "Stable rubric identifier. The natural key (with tenantId) for this rubric block."
          },
          "contentId": {
            "type": "string",
            "format": "uuid",
            "description": "The question (qti:artifact) this rubric belongs to. Two-leg composite FK (tenantId, contentId) -> qti.artifact(tenantId, id). FKs into the QTI union master, not through the content projection. Hook-enforced (see x-validations)."
          },
          "rubricType": {
            "type": "string",
            "enum": [
              "analytic",
              "holistic"
            ],
            "description": "The rubric scoring model: analytic (multi-criterion with independent levels) or holistic (single overall scale)."
          },
          "maxPoints": {
            "type": "integer",
            "minimum": 1,
            "description": "Maximum achievable points on this rubric. Must be at least 1."
          },
          "criteria": {
            "type": "object",
            "description": "The rubric criteria and performance levels. For analytic rubrics: an array of criterion objects each with levels. For holistic: a single scale with levels. Structure varies by rubric_type; validated by the write hook.",
            "x-storage": "jsonb"
          }
        }
      },
      "UpdateQuestionRubricRequest": {
        "type": "object",
        "description": "Update-QuestionRubric request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "rubricType": {
            "type": "string",
            "enum": [
              "analytic",
              "holistic"
            ],
            "description": "The rubric scoring model: analytic (multi-criterion with independent levels) or holistic (single overall scale)."
          },
          "maxPoints": {
            "type": "integer",
            "minimum": 1,
            "description": "Maximum achievable points on this rubric. Must be at least 1."
          },
          "criteria": {
            "type": "object",
            "description": "The rubric criteria and performance levels. For analytic rubrics: an array of criterion objects each with levels. For holistic: a single scale with levels. Structure varies by rubric_type; validated by the write hook.",
            "x-storage": "jsonb"
          }
        }
      },
      "CreateTestBankRequest": {
        "type": "object",
        "description": "Create-TestBank request body (readOnly/server-managed fields excluded).",
        "required": [
          "bankId",
          "specId",
          "membershipRule",
          "minForms"
        ],
        "additionalProperties": false,
        "properties": {
          "bankId": {
            "type": "string",
            "format": "uuid",
            "description": "The test bank identifier. Together with tenantId this is the composite-natural primary key."
          },
          "specId": {
            "type": "string",
            "format": "uuid",
            "description": "FK to the test specification (blueprint) that governs this bank. Same-tenant composite FK (tenantId, specId) -> testSpec(tenantId, specId). A bank is always governed by exactly one spec; deleting the spec while banks reference it is prohibited.",
            "x-references": "testSpec.specId",
            "x-onDelete": "restrict"
          },
          "membershipRule": {
            "type": "string",
            "enum": [
              "manual",
              "auto_from_spec",
              "auto_from_tag"
            ],
            "description": "The rule governing how forms are admitted to this bank. 'manual' requires explicit bank_member contentReference rows; 'auto_from_spec' admits forms matching the spec's KC coverage grid; 'auto_from_tag' admits forms by catalog facet assignment."
          },
          "minForms": {
            "type": "integer",
            "minimum": 1,
            "description": "The minimum number of forms this bank must contain before it is considered usable for gating. Drives the bank_exhausted 409 when curriculum's next-form selector finds fewer available unseen forms than this threshold."
          }
        }
      },
      "UpdateTestBankRequest": {
        "type": "object",
        "description": "Update-TestBank request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "membershipRule": {
            "type": "string",
            "enum": [
              "manual",
              "auto_from_spec",
              "auto_from_tag"
            ],
            "description": "The rule governing how forms are admitted to this bank. 'manual' requires explicit bank_member contentReference rows; 'auto_from_spec' admits forms matching the spec's KC coverage grid; 'auto_from_tag' admits forms by catalog facet assignment."
          },
          "minForms": {
            "type": "integer",
            "minimum": 1,
            "description": "The minimum number of forms this bank must contain before it is considered usable for gating. Drives the bank_exhausted 409 when curriculum's next-form selector finds fewer available unseen forms than this threshold."
          }
        }
      },
      "CreateTestSpecRequest": {
        "type": "object",
        "description": "Create-TestSpec request body (readOnly/server-managed fields excluded).",
        "required": [
          "specId",
          "passingRule",
          "minForms",
          "kcCoverage"
        ],
        "additionalProperties": false,
        "properties": {
          "specId": {
            "type": "string",
            "format": "uuid",
            "description": "The test specification identifier. Together with tenantId this is the composite-natural primary key."
          },
          "passingRule": {
            "type": "string",
            "pattern": "^content\\..+$",
            "minLength": 1,
            "maxLength": 255,
            "description": "Reference to the contentPolicy row (policyKey) that defines the passing cutoff for this spec. The 89.5 hardcode is replaced by a policy config reference — never inline.",
            "x-references": "contentPolicy.policyKey",
            "x-onDelete": "restrict"
          },
          "minForms": {
            "type": "integer",
            "minimum": 1,
            "description": "The minimum number of distinct forms the bank must contain before this spec is considered complete. Drives the bank exhaustion 409 in curriculum's next-form gate."
          },
          "kcCoverage": {
            "type": "object",
            "description": "The DOK coverage grid: a JSONB structure mapping knowledge-component identifiers to required DOK level coverage targets per blueprint cell. Shape is implementation-defined per the spec author. Validated by write hook against the spec's declared KC vocabulary.",
            "additionalProperties": true
          }
        }
      },
      "UpdateTestSpecRequest": {
        "type": "object",
        "description": "Update-TestSpec request body (partial — all fields optional; readOnly + immutable fields excluded; null clears a nullable column).",
        "additionalProperties": false,
        "properties": {
          "passingRule": {
            "type": "string",
            "pattern": "^content\\..+$",
            "minLength": 1,
            "maxLength": 255,
            "description": "Reference to the contentPolicy row (policyKey) that defines the passing cutoff for this spec. The 89.5 hardcode is replaced by a policy config reference — never inline.",
            "x-references": "contentPolicy.policyKey",
            "x-onDelete": "restrict"
          },
          "minForms": {
            "type": "integer",
            "minimum": 1,
            "description": "The minimum number of distinct forms the bank must contain before this spec is considered complete. Drives the bank exhaustion 409 in curriculum's next-form gate."
          },
          "kcCoverage": {
            "type": "object",
            "description": "The DOK coverage grid: a JSONB structure mapping knowledge-component identifiers to required DOK level coverage targets per blueprint cell. Shape is implementation-defined per the spec author. Validated by write hook against the spec's declared KC vocabulary.",
            "additionalProperties": true
          }
        }
      },
      "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://alpha.platform4.alphaschool.dev"
    }
  ]
}
