{
  "openapi": "3.1.0",
  "info": {
    "title": "GroundIT — Docs, Desk & Assets",
    "version": "0.1.0",
    "license": {
      "name": "Proprietary — GroundIT/Sysmedac internal"
    },
    "description": "The governed HR document library with in-house e-sign (OTP/Aadhaar-eSign India, accepted-signature KSA), template-generated CTC/increment/experience letters, defensible document acknowledgements, and the read-gated policy rollout (`docs.*`); helpdesk tickets with SLA timers, threaded messages and a CSAT survey, plus a searchable knowledge base (`desk.*`); and the lite asset register with lifecycle-linked assignment and return that brackets onboarding and exit (`assets.*`). See ../../api-docs/00-api-overview-and-conventions.md.\n"
  },
  "servers": [
    {
      "url": "/api/v1"
    }
  ],
  "security": [
    {
      "bearerJWT": []
    }
  ],
  "tags": [
    {
      "name": "docs",
      "description": "Document library & folders, in-house e-sign, generated letters, acknowledgements, policy read-gate."
    },
    {
      "name": "desk",
      "description": "Helpdesk tickets, SLA, threaded messages, CSAT, knowledge base."
    },
    {
      "name": "assets",
      "description": "Asset register, assignment & return (lite at launch)."
    },
    {
      "name": "ticket",
      "description": "Helpdesk tickets — raise, thread, SLA, resolve/close, and the DSK-F04 conversion to a work task. Declared so the resource tag on those operations resolves; the remaining `docs`/`desk`/`assets` resource tags in this file are still undeclared and back-filling them is a separate housekeeping pass.\n"
    }
  ],
  "x-reuse-anchors": {
    "parameters": {
      "path_id": {
        "$ref": "#/components/parameters/PathId"
      },
      "page_size": {
        "$ref": "#/components/parameters/PageSize"
      },
      "page_after": {
        "$ref": "#/components/parameters/PageAfter"
      },
      "page_before": {
        "$ref": "#/components/parameters/PageBefore"
      },
      "idempotency_key": {
        "$ref": "#/components/parameters/IdempotencyKey"
      },
      "if_match": {
        "$ref": "#/components/parameters/IfMatch"
      }
    },
    "responses": {
      "unauthorized": {
        "$ref": "#/components/responses/Unauthorized"
      },
      "forbidden": {
        "$ref": "#/components/responses/Forbidden"
      },
      "not_found": {
        "$ref": "#/components/responses/NotFound"
      },
      "conflict": {
        "$ref": "#/components/responses/Conflict"
      },
      "unprocessable": {
        "$ref": "#/components/responses/UnprocessableEntity"
      },
      "locked": {
        "$ref": "#/components/responses/Locked"
      },
      "too_many": {
        "$ref": "#/components/responses/TooManyRequests"
      },
      "precondition_required": {
        "$ref": "#/components/responses/PreconditionRequired"
      },
      "precondition_failed": {
        "$ref": "#/components/responses/PreconditionFailed"
      },
      "gone": {
        "$ref": "#/components/responses/Gone"
      }
    },
    "headers": {
      "etag": {
        "$ref": "#/components/headers/ETag"
      },
      "location": {
        "$ref": "#/components/headers/Location"
      },
      "idem_replayed": {
        "$ref": "#/components/headers/IdempotencyReplayed"
      }
    }
  },
  "paths": {
    "/document-folders": {
      "get": {
        "operationId": "docs.document_folder.list",
        "summary": "List/browse the document folder tree",
        "description": "The foldered organisation of the document library — company-wide roots and per-employee branches (DOC-S07). Folders nest via `parent_folder_id`; pass `parent_folder_id=null` (omit the filter) for roots. Visibility composes with tenant RLS as an RBAC overlay (db 10 §1.1).\n",
        "tags": [
          "docs",
          "document_folder"
        ],
        "x-token": "docs.document_folder.list",
        "x-realizes-features": [
          "DOC-F01"
        ],
        "x-screens": [
          "DOC-S07"
        ],
        "x-touches-entities": [
          "docs.document_library"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "name": "parent_folder_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "folder_type",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/FolderType"
            }
          },
          {
            "name": "legal_entity_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `sort_order`, `name`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of folder nodes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentFolderPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "docs.document_folder.create",
        "summary": "Create a document folder",
        "description": "Adds a folder node to the library tree (DOC-S07).",
        "tags": [
          "docs",
          "document_folder"
        ],
        "x-token": "docs.document_folder.create",
        "x-realizes-features": [
          "DOC-F01"
        ],
        "x-screens": [
          "DOC-S07"
        ],
        "x-touches-entities": [
          "docs.document_library"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentFolderCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Folder created.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentFolder"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/document-folders/{id}": {
      "patch": {
        "operationId": "docs.document_folder.update",
        "summary": "Update a document folder",
        "description": "Renames, re-parents, or changes the RBAC-visibility scope of a folder (DOC-S07).",
        "tags": [
          "docs",
          "document_folder"
        ],
        "x-token": "docs.document_folder.update",
        "x-realizes-features": [
          "DOC-F01"
        ],
        "x-screens": [
          "DOC-S07"
        ],
        "x-touches-entities": [
          "docs.document_library"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentFolderUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated folder.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentFolder"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "delete": {
        "operationId": "docs.document_folder.delete",
        "summary": "Delete a document folder",
        "description": "Soft-deletes an **empty, non-system** folder node (DOC-S07). The tree served `list`/`create`/`update` and nothing else, so a mistyped folder was permanent; a library that can only ever grow is not a governed one.\n\n**Soft, not hard.** `document_library.parent_folder_id` and `documents.folder_id` are both `ON DELETE RESTRICT` (db 10 §1.1), so a physical delete is unavailable even on a node that looks empty; a folder has no `status` column, so `deleted_at` plus the version bump is the tombstone and every read already filters it out.\n\n**`409 STATE_TRANSITION_INVALID`** when the folder is `is_system = true`, has any live child folder, or holds any live document — the same predicate `document_count` projects, so the count the tree shows and the refusal the delete gives can never disagree. Direct children are the whole test: a folder cannot be non-empty by descendant without being non-empty by child.\n",
        "tags": [
          "docs",
          "document_folder"
        ],
        "x-token": "docs.document_folder.delete",
        "x-realizes-features": [
          "DOC-F01"
        ],
        "x-screens": [
          "DOC-S07"
        ],
        "x-touches-entities": [
          "docs.document_library",
          "docs.documents"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "204": {
            "description": "Folder soft-deleted."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/documents": {
      "get": {
        "operationId": "docs.document.list",
        "summary": "My documents — HR document library",
        "description": "The employee's own documents — letters, payslips, certificates, policies — searchable and filterable, with the pending-signature chip surfaced inline (DOC-S01, frame 64 / mobile v2 documents cluster). **Chip mapping (derived, not stored):** *Payslip* = `doc_type = 'PAYSLIP'`; *Promotion* = `letter_type IN ('INCREMENT','OTHER')` on the joined letter (no dedicated `'PROMOTION'` value, fsd 09 coverage gap 9); *All* = no filter.\n",
        "tags": [
          "docs",
          "document"
        ],
        "x-token": "docs.document.list",
        "x-realizes-features": [
          "DOC-F01",
          "DOC-F03"
        ],
        "x-screens": [
          "DOC-S01"
        ],
        "x-touches-entities": [
          "docs.documents",
          "docs.letters",
          "docs.esign_requests",
          "docs.document_library"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Free-text search over `title`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "doc_type",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/DocType"
            }
          },
          {
            "name": "letter_type",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/LetterType"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `issued_at`, `-issued_at`, `title`. Default `-issued_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the caller's own documents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/documents/{id}": {
      "get": {
        "operationId": "docs.document.get",
        "summary": "Get one document (view & sign)",
        "description": "A document/letter as a rendered PDF handle plus e-sign/acknowledge affordances (DOC-S02). `file` is a freshly minted presigned URL (`XC-F07`) — bytes never transit Postgres.\n\n**`esign` is the employee's whole e-sign contract.** `docs.esign_request.get` is HR-scoped, so this read carries a caller-scoped `DocumentEsignSummary` — the ceremony's shape plus the caller's own seat (`your_order` / `your_role` / `your_state` / `your_signed_at`), `null` when there is no ceremony or the caller holds no seat on it. It never carries the roster: DOC-S03 renders the sign affordance from this field alone, and no co-signer's identity is derivable from it.\n",
        "tags": [
          "docs",
          "document"
        ],
        "x-token": "docs.document.get",
        "x-realizes-features": [
          "DOC-F01",
          "DOC-F02",
          "DOC-F03",
          "DOC-F04"
        ],
        "x-screens": [
          "DOC-S02"
        ],
        "x-touches-entities": [
          "docs.documents",
          "docs.letters",
          "docs.esign_requests"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The document, resolved letter/e-sign projections and a presigned download.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Document"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/documents/admin": {
      "get": {
        "operationId": "docs.document.list_admin",
        "summary": "Document library console — browse & search",
        "description": "HR browses/organises the library across employees and the company (DOC-S07).",
        "tags": [
          "docs",
          "document"
        ],
        "x-token": "docs.document.list_admin",
        "x-realizes-features": [
          "DOC-F01"
        ],
        "x-screens": [
          "DOC-S07"
        ],
        "x-touches-entities": [
          "docs.documents"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "name": "employee_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "legal_entity_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "folder_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "doc_type",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/DocType"
            }
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/DocumentSource"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/DocumentStatus"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `title`, `issued_at`, `-issued_at`, `status`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tenant-wide page of documents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "docs.document.upload",
        "summary": "Upload a document into the library",
        "description": "Files a `source = 'UPLOAD'` document (DOC-S07); `storage_key`/`content_hash` are the result of a prior presigned-upload flow (`XC-F07`) — bytes never post here.\n",
        "tags": [
          "docs",
          "document"
        ],
        "x-token": "docs.document.upload",
        "x-realizes-features": [
          "DOC-F01"
        ],
        "x-screens": [
          "DOC-S07"
        ],
        "x-touches-entities": [
          "docs.documents",
          "docs.document_library"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "docs.document.uploaded",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentUpload"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Document filed.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Document"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/documents/{id}/admin": {
      "get": {
        "operationId": "docs.document.get_admin",
        "summary": "Open one document (back-office)",
        "description": "The back-office read that OPENS a document the console can list (DOC-S07 detail, DOC-S10's body preview, PPL-S14's vault). `docs.document.list_admin` returns `file: null` for every row by design and `docs.document.get` runs at `self` scope, so without this operation HR can enumerate a vault and reach nothing in it.\n\nReturns the full `Document` shape with a **freshly minted presigned `file` handle** (`XC-F07`, 15-minute TTL, never stored) plus the whole `supersedes_id` **version chain**, newest first — the pairing of the chain with `content_hash` is what makes *\"this is the letter we issued\"* provable. Chain entries carry `file: null`: presigning is a detail concern, and a reader opens an earlier version by calling this operation again for it.\n\n`file: null` on the requested document is a **state, not an error** — the storage client refuses a key whose object is missing or mis-prefixed and the service answers an absent handle rather than a 500, so the metadata that is still readable stays readable. A document belonging to another workspace answers **404, never 403**.\n\n**Privileged read** (`R-7`): tagged `PII_OTHER`, raised to an identity class for `doc_type = 'ID_PROOF'`, and each call writes one `audit.access_log` `DATA_ACCESS` row for the document actually served (`purpose = 'EMPLOYMENT_ADMIN'`).\n",
        "tags": [
          "docs",
          "document"
        ],
        "x-token": "docs.document.get_admin",
        "x-realizes-features": [
          "DOC-F01"
        ],
        "x-screens": [
          "DOC-S07",
          "DOC-S10",
          "PPL-S14"
        ],
        "x-touches-entities": [
          "docs.documents",
          "docs.letters",
          "docs.esign_requests",
          "docs.document_library",
          "audit.access_log"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The document with a presigned download and its version chain.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentAdminDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "docs.document.update",
        "summary": "Edit a document's library metadata",
        "description": "Edits title, folder, doc_type or the `requires_ack` flag (DOC-S07).",
        "tags": [
          "docs",
          "document"
        ],
        "x-token": "docs.document.update",
        "x-realizes-features": [
          "DOC-F01"
        ],
        "x-screens": [
          "DOC-S07"
        ],
        "x-touches-entities": [
          "docs.documents"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated document.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Document"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "delete": {
        "operationId": "docs.document.delete",
        "summary": "Soft-delete a document",
        "description": "fsd 09 DOC-S07 **Delete**. Soft-delete (`deleted_at`/`status = 'DELETED'`, db 10 §1.1).",
        "tags": [
          "docs",
          "document"
        ],
        "x-token": "docs.document.delete",
        "x-realizes-features": [
          "DOC-F01"
        ],
        "x-screens": [
          "DOC-S07"
        ],
        "x-touches-entities": [
          "docs.documents"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "204": {
            "description": "Document soft-deleted."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/documents/{id}/reissue": {
      "post": {
        "operationId": "docs.document.reissue",
        "summary": "Re-issue a document (new version)",
        "description": "Creates a new `version_no` document row (`supersedes_id` chain); the prior version flips to `SUPERSEDED` (DOC-S07 **Re-issue**, db 10 §1.1).\n",
        "tags": [
          "docs",
          "document"
        ],
        "x-token": "docs.document.reissue",
        "x-realizes-features": [
          "DOC-F01"
        ],
        "x-screens": [
          "DOC-S07"
        ],
        "x-touches-entities": [
          "docs.documents"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "docs.document.reissued",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentReissue"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "New version filed; the prior version is now `SUPERSEDED`.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Document"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/documents/{id}/archive": {
      "post": {
        "operationId": "docs.document.archive",
        "summary": "Archive a document",
        "description": "fsd 09 DOC-S07 **Archive**. `status: ACTIVE → ARCHIVED` (db 10 §1.1).",
        "tags": [
          "docs",
          "document"
        ],
        "x-token": "docs.document.archive",
        "x-realizes-features": [
          "DOC-F01"
        ],
        "x-screens": [
          "DOC-S07"
        ],
        "x-touches-entities": [
          "docs.documents"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "docs.document.archived",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActionNoteInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Archived.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Document"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/esign-requests": {
      "get": {
        "operationId": "docs.esign_request.list",
        "summary": "E-sign console — list signature ceremonies",
        "description": "HR's e-sign requests grid — document, initiator, method, order, progress, status (DOC-S09).",
        "tags": [
          "docs",
          "esign_request"
        ],
        "x-token": "docs.esign_request.list",
        "x-realizes-features": [
          "DOC-F02"
        ],
        "x-screens": [
          "DOC-S09"
        ],
        "x-touches-entities": [
          "docs.esign_requests"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/EsignRequestStatus"
            }
          },
          {
            "name": "document_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "initiated_by",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `created_at`, `-created_at`, `expires_at`, `status`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of e-sign requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EsignRequestPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "docs.esign_request.create",
        "summary": "Assemble a signature ceremony",
        "description": "Builds a `DRAFT` ceremony over a document — signatory roster, order and rail (DOC-S09 wizard). `sign_method` is pack-gated (India OTP/Aadhaar-eSign vs KSA accepted-signature, `XC-F01`). **Rails this product cannot perform are refused with a `422`**: `AADHAAR_ESIGN` (no ASP/ESP integration exists), `ACCEPTED_SIGNATURE` (KSA is roadmap-only this wave) and `EXTERNAL` (`Later` by charter). Only `OTP` and `DRAWN` may be assembled. The enum is unchanged — it is the vocabulary; this is a statement about the current wave, enforced server-side behind the per-screen rule in the `DOC-S03` spec §3.3.2 rather than trusting the picker.\n",
        "tags": [
          "docs",
          "esign_request"
        ],
        "x-token": "docs.esign_request.create",
        "x-realizes-features": [
          "DOC-F02"
        ],
        "x-screens": [
          "DOC-S09"
        ],
        "x-touches-entities": [
          "docs.esign_requests",
          "docs.documents"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EsignRequestCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Ceremony assembled, `DRAFT`.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EsignRequest"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/esign-requests/{id}": {
      "get": {
        "operationId": "docs.esign_request.get",
        "summary": "Get one e-sign ceremony with its signature trail",
        "description": "The ceremony plus the append-only signature evidence panel (DOC-S09).",
        "tags": [
          "docs",
          "esign_request"
        ],
        "x-token": "docs.esign_request.get",
        "x-realizes-features": [
          "DOC-F02"
        ],
        "x-screens": [
          "DOC-S09"
        ],
        "x-touches-entities": [
          "docs.esign_requests",
          "docs.esign_signatures"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The e-sign request with its signature evidence.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EsignRequestDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/esign-requests/{id}/send": {
      "post": {
        "operationId": "docs.esign_request.send",
        "summary": "Send a ceremony to its signatories",
        "description": "`status: DRAFT → SENT`; pending in the unified approvals inbox (`XC-F12`) for each signatory (DOC-S09 **Send**).\n",
        "tags": [
          "docs",
          "esign_request"
        ],
        "x-token": "docs.esign_request.send",
        "x-realizes-features": [
          "DOC-F02"
        ],
        "x-screens": [
          "DOC-S09"
        ],
        "x-touches-entities": [
          "docs.esign_requests"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "docs.esign_request.sent",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActionNoteInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sent.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EsignRequest"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/esign-requests/{id}/cancel": {
      "post": {
        "operationId": "docs.esign_request.cancel",
        "summary": "Cancel a ceremony",
        "description": "Initiator withdraws an in-flight ceremony: `status → CANCELLED` (DOC-S09).",
        "tags": [
          "docs",
          "esign_request"
        ],
        "x-token": "docs.esign_request.cancel",
        "x-realizes-features": [
          "DOC-F02"
        ],
        "x-screens": [
          "DOC-S09"
        ],
        "x-touches-entities": [
          "docs.esign_requests"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "docs.esign_request.cancelled",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActionNoteInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cancelled.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EsignRequest"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/esign-requests/{id}/sign": {
      "post": {
        "operationId": "docs.esign_signature.sign",
        "summary": "Capture a signatory's signature (sign ceremony)",
        "description": "The signing employee's own e-sign ceremony step (DOC-S03 **Confirm & Sign**) — captures an append-only `docs.esign_signatures` row (`decision = 'SIGNED'`, `signed_at`, `evidence_hash`, `otp_ref`, `signature_metadata`, db 10 §1.2) and updates the parent ceremony (`signed_count`++, `signatories[].state`, `status → IN_PROGRESS`/`COMPLETED` on the last required signature). On `COMPLETED` the signed artifact is filed as a `source = 'ESIGN'` document and a linked `docs.letters.status → 'SIGNED'`. Confirms on **DOC-S04** (signed-on date). No `If-Match` — the mobile flow reaches this action from the document's derived pending-signature state (DOC-S02), not a direct e-sign-request fetch; the `(request, signatory)` uniqueness constraint (db 10 §1.2) makes a duplicate sign a `409`, not a lost update. **A ceremony on a rail this product cannot perform is refused here with a `422`** — `AADHAAR_ESIGN`, `ACCEPTED_SIGNATURE` and `EXTERNAL` (see `docs.esign_request.create`). The refusal is repeated at capture as defense in depth: an append-only trail must never record a signature kind that could not have been executed. `docs.esign_signature.decline` is deliberately NOT gated this way — declining is the signatory's way out of such a ceremony. On the `OTP` / `AADHAAR_ESIGN` rails `otp_ref` must be a handle currently VERIFIED for this `(ceremony, signatory)` through `docs.esign_signature.verify_challenge`; anything else is a `422`.\n",
        "tags": [
          "docs",
          "esign_signature"
        ],
        "x-token": "docs.esign_signature.sign",
        "x-realizes-features": [
          "DOC-F02"
        ],
        "x-screens": [
          "DOC-S03",
          "DOC-S04"
        ],
        "x-touches-entities": [
          "docs.esign_signatures",
          "docs.esign_requests",
          "docs.letters",
          "docs.documents"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "docs.esign_signature.signed",
        "x-rls-scope": "self",
        "x-append-only": true,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EsignSignatureSignInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Signature captured (immutable), plus the caller-scoped `EsignCeremonyState` — the ceremony's status and progress counts, never its roster.\n",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EsignSignatureResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/esign-requests/{id}/decline": {
      "post": {
        "operationId": "docs.esign_signature.decline",
        "summary": "Decline to sign",
        "description": "The signing employee declines (DOC-S03 **Decline**) — an append-only `docs.esign_signatures` row (`decision = 'DECLINED'`); the ceremony branches `status → DECLINED` (db 10 §1.2).\n",
        "tags": [
          "docs",
          "esign_signature"
        ],
        "x-token": "docs.esign_signature.decline",
        "x-realizes-features": [
          "DOC-F02"
        ],
        "x-screens": [
          "DOC-S03"
        ],
        "x-touches-entities": [
          "docs.esign_signatures",
          "docs.esign_requests"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "docs.esign_signature.declined",
        "x-rls-scope": "self",
        "x-append-only": true,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EsignSignatureDeclineInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Decline captured (immutable), plus the caller-scoped `EsignCeremonyState` — the ceremony's status and progress counts, never its roster.\n",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EsignSignatureResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/esign-requests/{id}/challenge": {
      "post": {
        "operationId": "docs.esign_signature.challenge",
        "summary": "Request a signing code",
        "description": "Issues a single-use code bound to **this ceremony and this signatory** (DOC-S03 §3.3.3), delivered to the signatory's own work email through the outbound-mail rail (ADR 0038/0041). Rate-limited; a resend re-uses the same `otp_ref` and mints a fresh code. The code lives in `xc`/Redis and is never stored in `docs`.\n",
        "tags": [
          "docs",
          "esign_signature"
        ],
        "x-token": "docs.esign_signature.challenge",
        "x-realizes-features": [
          "DOC-F02"
        ],
        "x-screens": [
          "DOC-S03"
        ],
        "x-touches-entities": [
          "docs.esign_requests",
          "xc.mail_messages"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "async",
        "x-emits-event": "xc.email.requested",
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "202": {
            "description": "Code queued for delivery.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EsignChallengeResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/esign-requests/{id}/challenge/verify": {
      "post": {
        "operationId": "docs.esign_signature.verify_challenge",
        "summary": "Verify a signing code",
        "description": "Checks the submitted code and marks the `otp_ref` handle verified in `xc`/Redis for a short window, which `docs.esign_signature.sign` then requires on the OTP / Aadhaar-eSign rails. **The code never reaches the `docs` module** and is destroyed on first successful use. `422` wrong code · `429` too many attempts · `410` expired or unknown handle.\n",
        "tags": [
          "docs",
          "esign_signature"
        ],
        "x-token": "docs.esign_signature.verify_challenge",
        "x-realizes-features": [
          "DOC-F02"
        ],
        "x-screens": [
          "DOC-S03"
        ],
        "x-touches-entities": [
          "docs.esign_requests"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EsignChallengeVerifyInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Handle verified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EsignChallengeVerifyResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "410": {
            "$ref": "#/components/responses/Gone"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/letters/me": {
      "get": {
        "operationId": "docs.letter.list_me",
        "summary": "My letter requests",
        "description": "The caller's own self-serve letter requests, in-flight ones included, so the ESS surface can show a pending request rather than losing it between the 202 and the filed PDF (ESS #693).\n",
        "tags": [
          "docs",
          "letter"
        ],
        "x-token": "docs.letter.list_me",
        "x-realizes-features": [
          "DOC-F03"
        ],
        "x-screens": [
          "DOC-S01"
        ],
        "x-touches-entities": [
          "docs.letters"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "name": "letter_type",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/LetterType"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/LetterStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `issued_at`, `-issued_at`, `status`. Default `-issued_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the caller's own letters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LetterPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "docs.letter.request",
        "summary": "Request my own letter (self-serve, no HR ticket)",
        "description": "The ESS self-serve flagship (#693) — an employee raises their own bonafide/employment certificate, salary certificate or experience letter straight to a rendered PDF, with no HR ticket in the loop. The template is the PUBLISHED `org.templates` `LETTER` row whose `sub_type` names the letter type, so HR turns self-serve on for a type by publishing one and off by superseding it. `letter_type` is restricted to the fact-restating set (`CTC`, `EXPERIENCE`, `CONFIRMATION`, `OTHER`); the decision-asserting types are refused. Renders on the **jobs tier** (`XC-F08`, async) and is filed into the caller's own document library as `source = 'GENERATED'`, status `ISSUED` — poll `docs.letter.get_me`.\n",
        "tags": [
          "docs",
          "letter"
        ],
        "x-token": "docs.letter.request",
        "x-realizes-features": [
          "DOC-F03"
        ],
        "x-screens": [
          "DOC-S01"
        ],
        "x-touches-entities": [
          "docs.letters",
          "docs.documents",
          "org.templates",
          "org.template_renders"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "async",
        "x-emits-event": "docs.letter.generated",
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LetterSelfRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Render queued; `status = 'DRAFT'` until the jobs-tier render completes.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Letter"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/letters/me/{id}": {
      "get": {
        "operationId": "docs.letter.get_me",
        "summary": "Get one of my letters",
        "description": "The poll behind the 202. Carries a presigned `file` handle once the render has landed and the letter has been filed into the library; a failed render answers `status = 'VOID'` with `render_error` rather than leaving the request in limbo. Another employee's letter is a 404.\n",
        "tags": [
          "docs",
          "letter"
        ],
        "x-token": "docs.letter.get_me",
        "x-realizes-features": [
          "DOC-F03"
        ],
        "x-screens": [
          "DOC-S01",
          "DOC-S02"
        ],
        "x-touches-entities": [
          "docs.letters",
          "docs.documents"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The caller's letter, with a presigned download once filed.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Letter"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/letters": {
      "get": {
        "operationId": "docs.letter.list",
        "summary": "Letter generation console — list generated letters",
        "description": "HR's letters grid — employee, type, status, issued (DOC-S08).",
        "tags": [
          "docs",
          "letter"
        ],
        "x-token": "docs.letter.list",
        "x-realizes-features": [
          "DOC-F03"
        ],
        "x-screens": [
          "DOC-S08"
        ],
        "x-touches-entities": [
          "docs.letters"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "name": "employee_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "letter_type",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/LetterType"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/LetterStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `issued_at`, `-issued_at`, `status`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of generated letters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LetterPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "docs.letter.generate",
        "summary": "Generate an HR letter from a template",
        "description": "DOC-S08 **Generate** — creates a `DRAFT` letter and renders it to PDF on the **jobs tier** (`XC-F08`, async); on completion files a `source = 'GENERATED'` document and stamps the canonical config envelope (`pay_structure_version`, `compliance_pack_version`, and resolved config-version maps) plus `template_version` into `render_context` (**frozen**, db 10 §1.3 — a later template/config edit never retroactively rewrites an issued letter). `letter_type` has no `'PROMOTION'` value (fsd 09 coverage gap 9) — promotion letters render as `'INCREMENT'`/`'OTHER'`. Poll `docs.letter.get` or await `docs.letter.generated`.\n",
        "tags": [
          "docs",
          "letter"
        ],
        "x-token": "docs.letter.generate",
        "x-realizes-features": [
          "DOC-F03"
        ],
        "x-screens": [
          "DOC-S08"
        ],
        "x-touches-entities": [
          "docs.letters",
          "docs.documents",
          "org.templates"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "async",
        "x-emits-event": "docs.letter.generated",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LetterGenerateRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Render queued; `status = 'DRAFT'` until the jobs-tier render completes.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Letter"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/letters/{id}": {
      "get": {
        "operationId": "docs.letter.get",
        "summary": "Get one generated letter",
        "description": "Row-click detail — merge context, template, status, e-sign linkage, filed document (DOC-S08).",
        "tags": [
          "docs",
          "letter"
        ],
        "x-token": "docs.letter.get",
        "x-realizes-features": [
          "DOC-F03"
        ],
        "x-screens": [
          "DOC-S08"
        ],
        "x-touches-entities": [
          "docs.letters"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The generated letter.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Letter"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/letters/{id}/issue": {
      "post": {
        "operationId": "docs.letter.issue",
        "summary": "Mark a letter delivered to the employee",
        "description": "`status: GENERATED → ISSUED` (DOC-S08).",
        "tags": [
          "docs",
          "letter"
        ],
        "x-token": "docs.letter.issue",
        "x-realizes-features": [
          "DOC-F03"
        ],
        "x-screens": [
          "DOC-S08"
        ],
        "x-touches-entities": [
          "docs.letters"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "docs.letter.issued",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActionNoteInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Issued.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Letter"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/letters/{id}/route-to-esign": {
      "post": {
        "operationId": "docs.letter.route_to_esign",
        "summary": "Route a letter through in-house e-sign",
        "description": "DOC-S08 **Route to e-sign** — creates a `docs.esign_requests` ceremony over the letter's filed document and sets `letters.esign_request_id` (`DOC-F02`); on the ceremony's `COMPLETED`, `letters.status → 'SIGNED'` (db 10 §1.3). Use `docs.esign_request.send`/`.get` to progress and track the created ceremony (returned as `esign_request_id`). `sign_method` is subject to the same rail refusal as `docs.esign_request.create` — only `OTP` and `DRAWN` may be assembled.\n",
        "tags": [
          "docs",
          "letter"
        ],
        "x-token": "docs.letter.route_to_esign",
        "x-realizes-features": [
          "DOC-F03",
          "DOC-F02"
        ],
        "x-screens": [
          "DOC-S08"
        ],
        "x-touches-entities": [
          "docs.letters",
          "docs.esign_requests"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "docs.letter.routed_to_esign",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LetterRouteToEsignInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Letter linked to a new (DRAFT) e-sign ceremony.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Letter"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/letters/{id}/void": {
      "post": {
        "operationId": "docs.letter.void",
        "summary": "Retire a letter issued in error",
        "description": "DOC-S08 **Void** (`REQUIRED-OP R-11`) — `status: ISSUED`/`SIGNED` → `VOID` with a stated reason. `letters.status` has a `VOID` member the lifecycle otherwise reaches only through a render failure, so nothing let HR retire a letter issued in error: the corrected letter rendered a new row while the wrong one stayed `ISSUED` forever. The reason lands in `render_error`, which DOC-S08 already renders as *the* reason a letter reads `VOID`. Voiding never touches an e-sign trail: `docs.esign_signatures` is append-only and a signature that was given stays given.\n",
        "tags": [
          "docs",
          "letter"
        ],
        "x-token": "docs.letter.void",
        "x-realizes-features": [
          "DOC-F03"
        ],
        "x-screens": [
          "DOC-S08"
        ],
        "x-touches-entities": [
          "docs.letters"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "docs.letter.voided",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LetterVoidInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Voided.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Letter"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/acknowledgements": {
      "post": {
        "operationId": "docs.acknowledgement.create",
        "summary": "Acknowledge a document (read receipt / accept)",
        "description": "DOC-S02 **Acknowledge** — an append-only `docs.acknowledgements` row, version-pinned to `document_version_no` (db 10 §1.3); a re-issued document requires a fresh acknowledgement. Shown when `documents.requires_ack = true` and no acknowledgement exists for the current `version_no`.\n\n**Refused with 409 `STATE_TRANSITION_INVALID`** when the target is a **policy body** (a `docs.policies.document_id`), when the document does **not** set `requires_ack`, or when it is no longer `ACTIVE`. The policy-body refusal is a security boundary, not a convenience: this operation is employee-held and asserts no consent, so allowing it at a policy body would let a receipt that never claimed consent become the evidence the read-gate binds to — irreversibly, since both receipt tables are append-only. Acknowledge a policy through `docs.policy_read.acknowledge`, which is consent-gated and writes both receipts as one act.\n",
        "tags": [
          "docs",
          "acknowledgement"
        ],
        "x-token": "docs.acknowledgement.create",
        "x-realizes-features": [
          "DOC-F04"
        ],
        "x-screens": [
          "DOC-S02"
        ],
        "x-touches-entities": [
          "docs.acknowledgements",
          "docs.documents"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "docs.acknowledgement.created",
        "x-rls-scope": "self",
        "x-append-only": true,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AcknowledgementCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Acknowledgement recorded (immutable).",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Acknowledgement"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/acknowledgements/me": {
      "get": {
        "operationId": "docs.acknowledgement.list_me",
        "summary": "My acknowledgement receipts",
        "description": "The caller's OWN append-only acknowledgement receipts (DOC-S01/DOC-S02 history). `docs.acknowledgement.list_admin` is tenant-scoped with no self equivalent, which made this a defensible-receipt system in which only HR could read the receipts — an employee asked to accept a handbook and later asked whether they did has to be able to answer from their own side.\n\nSame envelope, view shape and immutability as the admin register, narrowed to the caller's employee record and masked again by the `acknowledgements` ownership overlay under `self` scope. A principal with no linked employee gets an **empty page**, not a refusal.\n",
        "tags": [
          "docs",
          "acknowledgement"
        ],
        "x-token": "docs.acknowledgement.list_me",
        "x-realizes-features": [
          "DOC-F04"
        ],
        "x-screens": [
          "DOC-S01",
          "DOC-S02"
        ],
        "x-touches-entities": [
          "docs.acknowledgements"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": true,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "name": "document_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "ack_type",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/AckType"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `acknowledged_at`, `-acknowledged_at`. Default `-acknowledged_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the caller's own acknowledgement receipts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcknowledgementPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/acknowledgements/admin": {
      "get": {
        "operationId": "docs.acknowledgement.list_admin",
        "summary": "Acknowledgement compliance tracking",
        "description": "HR's cross-workforce acknowledgement evidence for `requires_ack` documents (DOC-S10).",
        "tags": [
          "docs",
          "acknowledgement"
        ],
        "x-token": "docs.acknowledgement.list_admin",
        "x-realizes-features": [
          "DOC-F04"
        ],
        "x-screens": [
          "DOC-S10"
        ],
        "x-touches-entities": [
          "docs.acknowledgements"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": true,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "name": "document_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "employee_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "ack_type",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/AckType"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `acknowledged_at`, `-acknowledged_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of acknowledgement evidence.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcknowledgementPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/policies": {
      "get": {
        "operationId": "docs.policy.list",
        "summary": "My policies",
        "description": "The employee's HR policies with read/unread status (DOC-S05). Only `status = 'PUBLISHED'` policies in the caller's `audience` are returned. **Filter mapping:** *To read* = no acknowledged `policy_reads` row for the current `version_no`; *Read* = `acknowledged = true`.\n",
        "tags": [
          "docs",
          "policy"
        ],
        "x-token": "docs.policy.list",
        "x-realizes-features": [
          "DOC-F05"
        ],
        "x-screens": [
          "DOC-S05"
        ],
        "x-touches-entities": [
          "docs.policies",
          "docs.policy_reads"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/PolicyCategory"
            }
          },
          {
            "name": "read_status",
            "in": "query",
            "required": false,
            "description": "Derived filter over `docs.policy_reads.acknowledged` for the current version.",
            "schema": {
              "type": "string",
              "enum": [
                "ALL",
                "TO_READ",
                "READ"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `title`, `effective_from`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the caller's audience-scoped published policies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PolicyPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/policies/{id}": {
      "get": {
        "operationId": "docs.policy.get",
        "summary": "Get one policy version (view & acknowledge)",
        "description": "The policy body plus the read-gate accept affordance (DOC-S06).",
        "tags": [
          "docs",
          "policy"
        ],
        "x-token": "docs.policy.get",
        "x-realizes-features": [
          "DOC-F05",
          "DOC-F04"
        ],
        "x-screens": [
          "DOC-S06"
        ],
        "x-touches-entities": [
          "docs.policies",
          "docs.documents",
          "docs.policy_reads"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The policy version with a presigned body handle.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PolicyDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/policies/admin": {
      "get": {
        "operationId": "docs.policy.list_admin",
        "summary": "Policy management console — list",
        "description": "HR's policy grid — code, title, category, version, mandatory, status, effective (DOC-S10).",
        "tags": [
          "docs",
          "policy"
        ],
        "x-token": "docs.policy.list_admin",
        "x-realizes-features": [
          "DOC-F05"
        ],
        "x-screens": [
          "DOC-S10"
        ],
        "x-touches-entities": [
          "docs.policies"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/PolicyCategory"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/PolicyStatus"
            }
          },
          {
            "name": "legal_entity_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Free-text search, `ILIKE` over `title` **and** `policy_code` — the code is the tenant-stable identifier a version chain hangs off, so looking a policy up by the string printed on it resolves.\n",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "is_mandatory",
            "in": "query",
            "required": false,
            "description": "Narrows to mandatory (or non-mandatory) policy versions — `DOC-S10`'s Mandatory filter.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `policy_code`, `effective_from`, `status`, `title`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tenant-wide page of policy versions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PolicyPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "docs.policy.create",
        "summary": "Author a policy version",
        "description": "DOC-S10 authoring wizard — a `DRAFT` policy version bound to a policy body document (`document_id`, templated via `org.templates`, `ORG-F08`) and an audience-targeting rule (db 10 §1.3).\n",
        "tags": [
          "docs",
          "policy"
        ],
        "x-token": "docs.policy.create",
        "x-realizes-features": [
          "DOC-F05"
        ],
        "x-screens": [
          "DOC-S10"
        ],
        "x-touches-entities": [
          "docs.policies",
          "docs.documents",
          "org.templates"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PolicyCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Policy version drafted.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Policy"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/policies/{id}/admin": {
      "get": {
        "operationId": "docs.policy.get_admin",
        "summary": "Read a policy version (back-office)",
        "description": "The policy version at **any** status and **not** audience-filtered, plus a presigned handle on its body document (DOC-S10 Overview).\n\nBoth are the point. `docs.policy.list_admin` selects no `file`, and `docs.policy.get` is `self`-scope AND audience-filtered — so an HR admin outside a policy's own audience (a Bangalore HR admin publishing a Riyadh handbook) could not read the body they were about to make mandatory for someone else. Publishing a document you cannot open is not a reviewable act.\n\nThe handle is minted through the module's single presign path, so `storage_key` never leaves the server; `file` is `null` when the body object cannot be reached, which is a state to render, not an error.\n",
        "tags": [
          "docs",
          "policy"
        ],
        "x-token": "docs.policy.get_admin",
        "x-realizes-features": [
          "DOC-F05"
        ],
        "x-screens": [
          "DOC-S10"
        ],
        "x-touches-entities": [
          "docs.policies",
          "docs.documents"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The policy version with a presigned body handle.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PolicyDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "docs.policy.update",
        "summary": "Edit a draft policy version",
        "description": "Edits title/category/document/audience/mandatory/effective_from, pre-publish (DOC-S10).",
        "tags": [
          "docs",
          "policy"
        ],
        "x-token": "docs.policy.update",
        "x-realizes-features": [
          "DOC-F05"
        ],
        "x-screens": [
          "DOC-S10"
        ],
        "x-touches-entities": [
          "docs.policies"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PolicyUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated policy version.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Policy"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/policies/{id}/publish": {
      "post": {
        "operationId": "docs.policy.publish",
        "summary": "Publish a policy version (opens the read-gate)",
        "description": "DOC-S10 **Publish** — `status: DRAFT → PUBLISHED`, stamps `published_at`/`effective_from`; if this version supersedes a prior `PUBLISHED` version of the same `policy_code`, the prior flips to `SUPERSEDED` and **the read-gate resets** — every required reader must re-read and re-acknowledge (db 10 §1.3).\n",
        "tags": [
          "docs",
          "policy"
        ],
        "x-token": "docs.policy.publish",
        "x-realizes-features": [
          "DOC-F05"
        ],
        "x-screens": [
          "DOC-S10"
        ],
        "x-touches-entities": [
          "docs.policies"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "docs.policy.published",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PolicyPublishInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Published.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Policy"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/policies/{id}/compliance": {
      "get": {
        "operationId": "docs.policy.compliance_summary",
        "summary": "Policy compliance — the audience-vs-reads aggregate and the required-reader roster",
        "description": "`DOC-S10`'s reason to exist. `docs.policy_read.list_admin` selects `FROM docs.policy_reads`, so it returns **only the people who have read** — \"not yet read\" is the ABSENCE of a row. A console whose only read is the readers can report *\"41 accepted\"* and can never answer *\"41 of how many?\"*. This operation drives the roster from the **resolved audience** and joins the receipts onto it.\n\nReturns `required` / `read` / `outstanding`, computed over the WHOLE audience and never over the page, plus a keyset-paged roster of required readers each carrying `read_status ∈ {READ, TO_READ}`, `read_at` and `acknowledgement_id`. Filter `read_status=TO_READ` for the outstanding readers — the console's default view.\n\nThree things the numbers depend on: the denominator is the **resolved audience** (all four `audience` legs, the same predicate `docs.policy.list` uses, so the two cannot disagree); it counts **non-terminated** employees only (`EXITED`/`ALUMNI` are the statuses `people.employees` names terminal, and a leaver is not an outstanding reader); and receipts are matched on the **current `version_no`**, so publishing a new version resets the gate in the number as well as in the copy.\n",
        "tags": [
          "docs",
          "policy"
        ],
        "x-token": "docs.policy.compliance_summary",
        "x-realizes-features": [
          "DOC-F05",
          "DOC-F04"
        ],
        "x-screens": [
          "DOC-S10"
        ],
        "x-touches-entities": [
          "docs.policies",
          "docs.policy_reads",
          "people.employees"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "read_status",
            "in": "query",
            "required": false,
            "description": "Narrows the roster; the counts are always over the whole audience.",
            "schema": {
              "type": "string",
              "enum": [
                "TO_READ",
                "READ"
              ]
            }
          },
          {
            "name": "employee_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "department_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `full_name`, `employee_no`. Default `full_name`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The compliance aggregate and a page of required readers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PolicyComplianceSummary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/policies/{id}/remind": {
      "post": {
        "operationId": "docs.policy_read.remind",
        "summary": "Remind the outstanding readers of a policy version",
        "description": "`DOC-S10` **Send reminder** — queues **one `xc.mail_messages` row per outstanding reader** and answers `202`. Without it the console can show non-compliance and do nothing about it.\n\n**Nothing here sends anything.** The write is a `QUEUED` row plus the single `xc.email.requested` outbox event that releases it, in one transaction; the jobs tier resolves the tenant's configuration and dispatches (ADR 0038/0041; the API request path never dials a mail host, api-docs/08 §14.8). The response therefore says **queued**, never *sent* — the `org.template.send_test` precedent is binding.\n\n`employee_ids` **narrows, it does not choose**: an id that is not an outstanding reader — already accepted, outside the audience, exited — is silently SKIPPED, because the console sends the selection the operator was looking at and a race with an acceptance that landed a second ago must not fail the whole batch. A malformed id is still a `422`. An outstanding reader with no `work_email` is skipped and counted in `skipped_without_email`, so the response never claims to have reached someone it has no address for. Omit the body (or the field) to remind **every** outstanding reader.\n\nRefused `409` on a policy that is not `PUBLISHED` — there is no read-gate to remind anyone about.\n",
        "tags": [
          "docs",
          "policy_read"
        ],
        "x-token": "docs.policy_read.remind",
        "x-realizes-features": [
          "DOC-F05"
        ],
        "x-screens": [
          "DOC-S10"
        ],
        "x-touches-entities": [
          "docs.policies",
          "docs.policy_reads",
          "people.employees",
          "xc.mail_messages",
          "xc.outbox"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "async",
        "x-emits-event": "xc.email.requested",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PolicyRemindInput"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Reminders queued for dispatch by the jobs tier.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PolicyRemindResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/policies/{id}/acknowledge": {
      "post": {
        "operationId": "docs.policy_read.acknowledge",
        "summary": "Accept the read-gate for a policy version",
        "description": "DOC-S06 **I have read and accept** — the read-gate composite action: writes an append-only `docs.acknowledgements` row (`ack_type = 'ACCEPT'`, `document_version_no`) **and** an append-only `docs.policy_reads` row (`acknowledged = true`, `policy_version_no`, linking `acknowledgement_id`) in one transaction (db 10 §1.3 — the read-gate is acknowledgement-tracked, DOC-F05 → DOC-F04). Enabled client-side only once the policy body has been opened/scrolled to end.\n",
        "tags": [
          "docs",
          "policy_read"
        ],
        "x-token": "docs.policy_read.acknowledge",
        "x-realizes-features": [
          "DOC-F05",
          "DOC-F04"
        ],
        "x-screens": [
          "DOC-S06"
        ],
        "x-touches-entities": [
          "docs.policy_reads",
          "docs.acknowledgements",
          "docs.policies"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "docs.policy_read.acknowledged",
        "x-rls-scope": "self",
        "x-append-only": true,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PolicyAcknowledgeInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Read-gate satisfied (immutable evidence recorded).",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PolicyAcknowledgeResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/policies/{id}/reads": {
      "get": {
        "operationId": "docs.policy_read.list_admin",
        "summary": "Policy read-compliance — who has / has not read",
        "description": "DOC-S10 read-compliance panel — per-employee read-gate status for one policy version (db 10 §1.3).",
        "tags": [
          "docs",
          "policy_read"
        ],
        "x-token": "docs.policy_read.list_admin",
        "x-realizes-features": [
          "DOC-F05"
        ],
        "x-screens": [
          "DOC-S10"
        ],
        "x-touches-entities": [
          "docs.policy_reads"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": true,
        "x-entitlement": null,
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "acknowledged",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "employee_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `read_at`, `-read_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of per-employee read-gate rows for this policy version.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PolicyReadPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/tickets": {
      "get": {
        "operationId": "desk.ticket.list",
        "summary": "My helpdesk tickets",
        "description": "The employee's tickets by status, with the SLA/CSAT indicator (DSK-S01). **Chip mapping:** *Open* = `'OPEN'`; *In progress* = `'IN_PROGRESS'`+`'ON_HOLD'`; *Resolved* = `'RESOLVED'`; *Closed* = `'CLOSED'`; `'CANCELLED'` falls under *All* (db 10 §2.1 — `'REOPENED'` is not a reachable status value, rev. 2026-07-02; a reopen is `RESOLVED`/`CLOSED → IN_PROGRESS` plus `reopened_count`++).\n",
        "tags": [
          "desk",
          "ticket"
        ],
        "x-token": "desk.ticket.list",
        "x-realizes-features": [
          "DSK-F01"
        ],
        "x-screens": [
          "DSK-S01"
        ],
        "x-touches-entities": [
          "desk.tickets",
          "desk.ticket_slas",
          "desk.csat_responses"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Free-text search over `subject`/`ticket_no`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/TicketStatus"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/TicketCategory"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `created_at`, `-created_at`, `status`. Default `-created_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the caller's own tickets.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "desk.ticket.create",
        "summary": "Raise a helpdesk ticket",
        "description": "DSK-S02 **Submit** — creates the ticket `OPEN` with a minted `ticket_no`, an initial `desk.ticket_messages` row (`author_role = 'REQUESTER'`, `message_type = 'COMMENT'`), and a `desk.ticket_slas` row (`response_due_at`/`resolution_due_at` from the category/priority pack, `XC-F08`).\n",
        "tags": [
          "desk",
          "ticket"
        ],
        "x-token": "desk.ticket.create",
        "x-realizes-features": [
          "DSK-F01"
        ],
        "x-screens": [
          "DSK-S02"
        ],
        "x-touches-entities": [
          "desk.tickets",
          "desk.ticket_messages",
          "desk.ticket_slas"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "desk.ticket.created",
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TicketCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Ticket raised, `OPEN`, SLA clock started.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ticket"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/tickets/{id}": {
      "get": {
        "operationId": "desk.ticket.get",
        "summary": "Get one of my tickets",
        "description": "Header, SLA and resolution note (DSK-S03).",
        "tags": [
          "desk",
          "ticket"
        ],
        "x-token": "desk.ticket.get",
        "x-realizes-features": [
          "DSK-F01"
        ],
        "x-screens": [
          "DSK-S03"
        ],
        "x-touches-entities": [
          "desk.tickets",
          "desk.ticket_slas"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The ticket with its SLA state.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ticket"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/tickets/{id}/reopen": {
      "post": {
        "operationId": "desk.ticket.reopen",
        "summary": "Reopen a resolved/closed ticket",
        "description": "DSK-S03 **Reopen** — `RESOLVED`/`CLOSED → IN_PROGRESS`, `reopened_count`++, a system `message_type = 'REOPEN'` post (db 10 §2.1). A reopen→reclose owes a fresh CSAT survey.\n",
        "tags": [
          "desk",
          "ticket"
        ],
        "x-token": "desk.ticket.reopen",
        "x-realizes-features": [
          "DSK-F01"
        ],
        "x-screens": [
          "DSK-S03"
        ],
        "x-touches-entities": [
          "desk.tickets",
          "desk.ticket_messages"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "desk.ticket.reopened",
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActionNoteInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reopened.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ticket"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/tickets/admin": {
      "get": {
        "operationId": "desk.ticket.list_admin",
        "summary": "Helpdesk admin dashboard — ticket queue",
        "description": "Resolvers/admins work the queue across categories with SLA breach visible per row (DSK-S06).",
        "tags": [
          "desk",
          "ticket"
        ],
        "x-token": "desk.ticket.list_admin",
        "x-realizes-features": [
          "DSK-F01"
        ],
        "x-screens": [
          "DSK-S06"
        ],
        "x-touches-entities": [
          "desk.tickets",
          "desk.ticket_slas"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/TicketStatus"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/TicketCategory"
            }
          },
          {
            "name": "priority",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/TicketPriority"
            }
          },
          {
            "name": "assigned_to",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "requester_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "breach_status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/SlaBreachStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `created_at`, `-created_at`, `priority`, `status`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tenant-wide page of tickets.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/tickets/{id}/admin": {
      "get": {
        "operationId": "desk.ticket.get_admin",
        "summary": "Ticket detail & resolution (resolver)",
        "description": "The resolver's working view — status, SLA timers, resolution note (DSK-S07).",
        "tags": [
          "desk",
          "ticket"
        ],
        "x-token": "desk.ticket.get_admin",
        "x-realizes-features": [
          "DSK-F01",
          "DSK-F02"
        ],
        "x-screens": [
          "DSK-S07"
        ],
        "x-touches-entities": [
          "desk.tickets",
          "desk.ticket_slas"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The ticket with full SLA timer detail.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ticket"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/tickets/{id}/assign": {
      "post": {
        "operationId": "desk.ticket.assign",
        "summary": "Assign / reassign a ticket",
        "description": "DSK-S06/DSK-S07 **Assign** — sets `assigned_to`/`assigned_team` and posts a system `message_type = 'ASSIGNMENT'` message (db 10 §2.1).\n",
        "tags": [
          "desk",
          "ticket"
        ],
        "x-token": "desk.ticket.assign",
        "x-realizes-features": [
          "DSK-F01"
        ],
        "x-screens": [
          "DSK-S06",
          "DSK-S07"
        ],
        "x-touches-entities": [
          "desk.tickets",
          "desk.ticket_messages"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "desk.ticket.assigned",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TicketAssignInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Assigned.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ticket"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/tickets/{id}/hold": {
      "post": {
        "operationId": "desk.ticket.hold",
        "summary": "Place a ticket on hold",
        "description": "`status → ON_HOLD`; the SLA clock pauses (`ticket_slas.paused_minutes`, DSK-S07 **Hold**).",
        "tags": [
          "desk",
          "ticket"
        ],
        "x-token": "desk.ticket.hold",
        "x-realizes-features": [
          "DSK-F01"
        ],
        "x-screens": [
          "DSK-S07"
        ],
        "x-touches-entities": [
          "desk.tickets",
          "desk.ticket_slas"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "desk.ticket.held",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActionNoteInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "On hold.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ticket"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/tickets/{id}/resolve": {
      "post": {
        "operationId": "desk.ticket.resolve",
        "summary": "Resolve a ticket",
        "description": "DSK-S07 **Resolve** — `status → RESOLVED`, `resolution_note`, `resolved_at`; posts a system `message_type = 'RESOLUTION'` message (db 10 §2.1/§2.2).\n",
        "tags": [
          "desk",
          "ticket"
        ],
        "x-token": "desk.ticket.resolve",
        "x-realizes-features": [
          "DSK-F02"
        ],
        "x-screens": [
          "DSK-S07"
        ],
        "x-touches-entities": [
          "desk.tickets",
          "desk.ticket_messages"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "desk.ticket.resolved",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TicketResolveInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resolved.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ticket"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/tickets/{id}/close": {
      "post": {
        "operationId": "desk.ticket.close",
        "summary": "Close a ticket (requests CSAT)",
        "description": "DSK-S07 **Close** — `status → CLOSED`, `closed_at`; stamps `csat_requested_at` (the CSAT-pending marker, db 10 §2.1) and notifies the requester (`XC-F05`) — rated on `DSK-S04`.\n",
        "tags": [
          "desk",
          "ticket"
        ],
        "x-token": "desk.ticket.close",
        "x-realizes-features": [
          "DSK-F02"
        ],
        "x-screens": [
          "DSK-S07"
        ],
        "x-touches-entities": [
          "desk.tickets"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "desk.ticket.closed",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActionNoteInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Closed; CSAT requested.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ticket"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/tickets/admin/dashboard-summary": {
      "get": {
        "operationId": "desk.ticket.dashboard_summary",
        "summary": "Helpdesk KPI strip",
        "description": "DSK-S06 `PT-KPI` — open/in-progress/breached counts and the CSAT average (db 10 §2.1/§2.2).",
        "tags": [
          "desk",
          "ticket"
        ],
        "x-token": "desk.ticket.dashboard_summary",
        "x-realizes-features": [
          "DSK-F01",
          "DSK-F02"
        ],
        "x-screens": [
          "DSK-S06"
        ],
        "x-touches-entities": [
          "desk.tickets",
          "desk.ticket_slas",
          "desk.csat_responses"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [],
        "responses": {
          "200": {
            "description": "KPI counts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketDashboardSummary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/tickets/{id}/messages": {
      "get": {
        "operationId": "desk.ticket_message.list",
        "summary": "My ticket's message thread",
        "description": "The requester's view of the thread — `is_internal` resolver notes never returned (DSK-S03).",
        "tags": [
          "desk",
          "ticket_message"
        ],
        "x-token": "desk.ticket_message.list",
        "x-realizes-features": [
          "DSK-F01"
        ],
        "x-screens": [
          "DSK-S03"
        ],
        "x-touches-entities": [
          "desk.ticket_messages"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `created_at`. Default `created_at` (thread order).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the requester-visible thread.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketMessagePage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "desk.ticket_message.create",
        "summary": "Reply to my ticket",
        "description": "DSK-S03 **Reply** — `author_role = 'REQUESTER'`, `message_type = 'COMMENT'`; `is_internal` always false.",
        "tags": [
          "desk",
          "ticket_message"
        ],
        "x-token": "desk.ticket_message.create",
        "x-realizes-features": [
          "DSK-F01"
        ],
        "x-screens": [
          "DSK-S03"
        ],
        "x-touches-entities": [
          "desk.ticket_messages"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "desk.ticket_message.posted",
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TicketMessageCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Reply posted.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketMessage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/tickets/{id}/messages/admin": {
      "get": {
        "operationId": "desk.ticket_message.list_admin",
        "summary": "Full ticket thread (resolver)",
        "description": "The resolver's view of the thread, including `is_internal` notes (DSK-S07).",
        "tags": [
          "desk",
          "ticket_message"
        ],
        "x-token": "desk.ticket_message.list_admin",
        "x-realizes-features": [
          "DSK-F01"
        ],
        "x-screens": [
          "DSK-S07"
        ],
        "x-touches-entities": [
          "desk.ticket_messages"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `created_at`. Default `created_at` (thread order).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the full thread, internal notes included.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketMessagePage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/tickets/{id}/resolver-messages": {
      "post": {
        "operationId": "desk.ticket_message.create_resolver",
        "summary": "Resolver reply / internal note",
        "description": "DSK-S07 composer — `author_role = 'RESOLVER'`; `is_internal = true` posts are RBAC-hidden from the requester. The first resolver reply stamps `ticket_slas.first_responded_at` (db 10 §2.1).\n",
        "tags": [
          "desk",
          "ticket_message"
        ],
        "x-token": "desk.ticket_message.create_resolver",
        "x-realizes-features": [
          "DSK-F01"
        ],
        "x-screens": [
          "DSK-S07"
        ],
        "x-touches-entities": [
          "desk.ticket_messages",
          "desk.ticket_slas"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "desk.ticket_message.posted",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TicketMessageCreateResolver"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Message posted.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketMessage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/tickets/{id}/csat-response": {
      "post": {
        "operationId": "desk.csat_response.create",
        "summary": "Rate a resolution (CSAT survey)",
        "description": "DSK-S04 **Submit** — a satisfaction score + optional comment for a `CLOSED` ticket; `sentiment` is server-derived (`4–5 → POSITIVE`, `3 → NEUTRAL`, `1–2 → NEGATIVE`, db 10 §2.2). Clears the CSAT-pending prompt (`csat_requested_at` set ∧ no response with `responded_at ≥ csat_requested_at`).\n",
        "tags": [
          "desk",
          "csat_response"
        ],
        "x-token": "desk.csat_response.create",
        "x-realizes-features": [
          "DSK-F02"
        ],
        "x-screens": [
          "DSK-S04"
        ],
        "x-touches-entities": [
          "desk.csat_responses",
          "desk.tickets"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "desk.csat_response.submitted",
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CsatResponseCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "CSAT response recorded.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CsatResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/tickets/{id}/convert-to-task": {
      "post": {
        "operationId": "desk.ticket.convert_to_task",
        "summary": "Convert a ticket into a linked work task",
        "description": "DSK-S07 **Convert to task** — one-click conversion of a helpdesk ticket into a linked work task (DSK-F04: client request → delivery work). The desk module records the conversion on the ticket and **emits the cross-module event `desk.ticket.converted`**; the `work` module consumes it and mints the task with an **origin back-reference** to this ticket. Linkage is by **soft ref + event** — this operation never writes into `work.tasks`, and there is no cross-schema write anywhere on the path (architecture-docs 03-domain-modules §4, api-docs 00 §5).\n\n**The ticket keeps its own SLA lifecycle.** Conversion is not a resolution and not a hand-off of state: SLA timers, `status`, threads and CSAT continue to run on the ticket exactly as before, while the minted task carries delivery. Closing the task does not close the ticket, and `desk.ticket.resolve`/`.close` remain the only way the ticket reaches a terminal status.\n\n**Idempotent and single-shot.** `Idempotency-Key` is required (04 §1); a replay of the same key returns the original result with `Idempotency-Replayed`. A ticket that has **already been converted** answers `409` `CONFLICT` under a *different* key — conversion is once-per-ticket, so a second conversion is a caller error, not a silent second task. `422` covers a ticket in a state conversion is not offered from.\n\n**Contract ahead of build, stated plainly.** `desk` is a **contract stub today** — the module seam exists but no handler behind it does (the whole namespace answers `501` via the stub layer). This operation therefore ships **with or after the desk implementation slice**, together with the ticket-side conversion marker its response projects; until then it is a designed surface a consumer must not assume is live, and `deskTicketConverted` has no publisher. Specced now so the `work` side can be built against a fixed event and payload rather than a guess.\n",
        "tags": [
          "desk",
          "ticket"
        ],
        "x-token": "desk.ticket.convert_to_task",
        "x-realizes-features": [
          "DSK-F04"
        ],
        "x-screens": [
          "DSK-S07"
        ],
        "x-touches-entities": [
          "desk.tickets"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "desk.ticket.converted",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "description": "Optional routing hints handed to the `work` module on the event; all are advisory and none is required to convert.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TicketConvertToTaskInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conversion recorded on the ticket and the event emitted.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketConversionResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/kb-articles": {
      "get": {
        "operationId": "desk.kb_article.list",
        "summary": "Browse & search the knowledge base",
        "description": "DSK-S05 — only `status = 'PUBLISHED'`, `visibility ∈ ('ALL_EMPLOYEES','RBAC')` articles (`'RESOLVER_ONLY'` never returned here); indexed by global search (`XC-F13`).\n",
        "tags": [
          "desk",
          "kb_article"
        ],
        "x-token": "desk.kb_article.list",
        "x-realizes-features": [
          "DSK-F03"
        ],
        "x-screens": [
          "DSK-S05"
        ],
        "x-touches-entities": [
          "desk.kb_articles"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Free-text search over `title`/`body`/`tags` (`XC-F13`).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/KbCategory"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `title`, `helpful_count`, `-helpful_count`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of published, visibility-scoped articles.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KbArticlePage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "desk.kb_article.create",
        "summary": "Author a knowledge-base article",
        "description": "DSK-S08 editor — a `DRAFT` article with localized `{en, ar}` title/body (db 10 §2.2).",
        "tags": [
          "desk",
          "kb_article"
        ],
        "x-token": "desk.kb_article.create",
        "x-realizes-features": [
          "DSK-F03"
        ],
        "x-screens": [
          "DSK-S08"
        ],
        "x-touches-entities": [
          "desk.kb_articles"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KbArticleCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Article drafted.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KbArticle"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/kb-articles/{id}": {
      "get": {
        "operationId": "desk.kb_article.get",
        "summary": "Read an article",
        "description": "DSK-S05 article view (title/body/media in the caller's locale).",
        "tags": [
          "desk",
          "kb_article"
        ],
        "x-token": "desk.kb_article.get",
        "x-realizes-features": [
          "DSK-F03"
        ],
        "x-screens": [
          "DSK-S05"
        ],
        "x-touches-entities": [
          "desk.kb_articles"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The article.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KbArticle"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "desk.kb_article.update",
        "summary": "Edit an article",
        "description": "DSK-S08 editor — localized title/body/media/tags/category/visibility edits (db 10 §2.2).",
        "tags": [
          "desk",
          "kb_article"
        ],
        "x-token": "desk.kb_article.update",
        "x-realizes-features": [
          "DSK-F03"
        ],
        "x-screens": [
          "DSK-S08"
        ],
        "x-touches-entities": [
          "desk.kb_articles"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KbArticleUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated article.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KbArticle"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/kb-articles/{id}/view": {
      "post": {
        "operationId": "desk.kb_article.mark_viewed",
        "summary": "Record an article view (deflection metric)",
        "description": "DSK-S05 — opening an article increments `view_count` (`XC-F15` deflection metric). Low-contention counter — no `If-Match` (`_shared.yaml` `IfMatch` note).\n",
        "tags": [
          "desk",
          "kb_article"
        ],
        "x-token": "desk.kb_article.mark_viewed",
        "x-realizes-features": [
          "DSK-F03"
        ],
        "x-screens": [
          "DSK-S05"
        ],
        "x-touches-entities": [
          "desk.kb_articles"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "View recorded.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KbArticleCounters"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/kb-articles/{id}/helpful": {
      "post": {
        "operationId": "desk.kb_article.mark_helpful",
        "summary": "Mark an article helpful",
        "description": "DSK-S05 **Was this helpful?** — increments `helpful_count`. **Advisory only** — no per-employee vote/view dedupe at launch-lite KB (fsd 09 coverage gap 3; a per-user vote table is design- & DB-pending). No `If-Match` (low-contention counter).\n",
        "tags": [
          "desk",
          "kb_article"
        ],
        "x-token": "desk.kb_article.mark_helpful",
        "x-realizes-features": [
          "DSK-F03"
        ],
        "x-screens": [
          "DSK-S05"
        ],
        "x-touches-entities": [
          "desk.kb_articles"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Helpful vote recorded.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KbArticleCounters"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/kb-articles/admin": {
      "get": {
        "operationId": "desk.kb_article.list_admin",
        "summary": "Knowledge base management console — list",
        "description": "DSK-S08 grid — title, category, visibility, status, views, helpful (db 10 §2.2).",
        "tags": [
          "desk",
          "kb_article"
        ],
        "x-token": "desk.kb_article.list_admin",
        "x-realizes-features": [
          "DSK-F03"
        ],
        "x-screens": [
          "DSK-S08"
        ],
        "x-touches-entities": [
          "desk.kb_articles"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/KbCategory"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/KbStatus"
            }
          },
          {
            "name": "visibility",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/KbVisibility"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `title`, `status`, `view_count`, `-view_count`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tenant-wide page of articles.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KbArticlePage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/kb-articles/{id}/submit-for-review": {
      "post": {
        "operationId": "desk.kb_article.submit_for_review",
        "summary": "Submit an article for editorial review",
        "description": "`status: DRAFT → UNDER_REVIEW` (DSK-S08 **Submit for review**).",
        "tags": [
          "desk",
          "kb_article"
        ],
        "x-token": "desk.kb_article.submit_for_review",
        "x-realizes-features": [
          "DSK-F03"
        ],
        "x-screens": [
          "DSK-S08"
        ],
        "x-touches-entities": [
          "desk.kb_articles"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActionNoteInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Submitted for review.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KbArticle"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/kb-articles/{id}/publish": {
      "post": {
        "operationId": "desk.kb_article.publish",
        "summary": "Publish an article",
        "description": "`status → PUBLISHED`, stamps `published_at`; becomes searchable (`XC-F13`, DSK-S08 **Publish**).",
        "tags": [
          "desk",
          "kb_article"
        ],
        "x-token": "desk.kb_article.publish",
        "x-realizes-features": [
          "DSK-F03"
        ],
        "x-screens": [
          "DSK-S08"
        ],
        "x-touches-entities": [
          "desk.kb_articles"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "desk.kb_article.published",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActionNoteInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Published.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KbArticle"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/kb-articles/{id}/archive": {
      "post": {
        "operationId": "desk.kb_article.archive",
        "summary": "Archive an article",
        "description": "`status → ARCHIVED`; no longer surfaced in list/search (DSK-S08 **Archive**).",
        "tags": [
          "desk",
          "kb_article"
        ],
        "x-token": "desk.kb_article.archive",
        "x-realizes-features": [
          "DSK-F03"
        ],
        "x-screens": [
          "DSK-S08"
        ],
        "x-touches-entities": [
          "desk.kb_articles"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "desk.kb_article.archived",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "desk",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActionNoteInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Archived.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KbArticle"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/asset-assignments": {
      "get": {
        "operationId": "assets.asset_assignment.list",
        "summary": "My assets — assigned custody",
        "description": "The employee's own custody — asset + assignment status (AST-S01). Own custody only (`employee_id = self`).",
        "tags": [
          "assets",
          "asset_assignment"
        ],
        "x-token": "assets.asset_assignment.list",
        "x-realizes-features": [
          "AST-F01",
          "AST-F02"
        ],
        "x-screens": [
          "AST-S01"
        ],
        "x-touches-entities": [
          "assets.asset_assignments",
          "assets.assets"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "assets",
        "x-provisional": null,
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/AssetAssignmentStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `assigned_at`, `-assigned_at`, `status`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the caller's own asset assignments.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetAssignmentPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/asset-assignments/{id}": {
      "get": {
        "operationId": "assets.asset_assignment.get",
        "summary": "Asset detail & handover",
        "description": "Handover details for one assignment — condition-out, issuer, expected return (AST-S02).",
        "tags": [
          "assets",
          "asset_assignment"
        ],
        "x-token": "assets.asset_assignment.get",
        "x-realizes-features": [
          "AST-F02"
        ],
        "x-screens": [
          "AST-S02"
        ],
        "x-touches-entities": [
          "assets.asset_assignments",
          "assets.assets"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "assets",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The assignment with its resolved asset.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetAssignment"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/asset-assignments/{id}/acknowledge": {
      "post": {
        "operationId": "assets.asset_assignment.acknowledge",
        "summary": "Acknowledge custody receipt",
        "description": "AST-S02 **Acknowledge receipt** — `status: ASSIGNED → ACKNOWLEDGED`, stamps `acknowledged_at` (≥ `assigned_at`, db 10 §3.2).",
        "tags": [
          "assets",
          "asset_assignment"
        ],
        "x-token": "assets.asset_assignment.acknowledge",
        "x-realizes-features": [
          "AST-F02"
        ],
        "x-screens": [
          "AST-S02"
        ],
        "x-touches-entities": [
          "assets.asset_assignments"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "assets.asset_assignment.acknowledged",
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "assets",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActionNoteInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetAssignment"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/asset-assignments/admin": {
      "get": {
        "operationId": "assets.asset_assignment.list_admin",
        "summary": "Assignment & return console — assignments grid",
        "description": "HR/IT's assignments grid — asset, employee, assigned-by, assigned, ack, expected return, status (AST-S05).",
        "tags": [
          "assets",
          "asset_assignment"
        ],
        "x-token": "assets.asset_assignment.list_admin",
        "x-realizes-features": [
          "AST-F02"
        ],
        "x-screens": [
          "AST-S05"
        ],
        "x-touches-entities": [
          "assets.asset_assignments"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "assets",
        "x-provisional": null,
        "parameters": [
          {
            "name": "employee_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "asset_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/AssetAssignmentStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `assigned_at`, `-assigned_at`, `expected_return_date`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tenant-wide page of asset assignments.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetAssignmentPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "assets.asset_assignment.create",
        "summary": "Assign an asset to an employee",
        "description": "AST-S05 **Assign** — custody handover (`status = 'ASSIGNED'`, `condition_out`); the asset flips to `ASSIGNED` (db 10 §3.2, partial-unique — one live custody per asset). Also the internal target of the **onboarding trigger** (`REC-F07` → `recruit.onboarding_tasks` event, `onboarding_task_ref` soft ref) — this operation is the manual/HR-facing path; the event-driven path invokes the same write server-side.\n",
        "tags": [
          "assets",
          "asset_assignment"
        ],
        "x-token": "assets.asset_assignment.create",
        "x-realizes-features": [
          "AST-F02"
        ],
        "x-screens": [
          "AST-S05"
        ],
        "x-touches-entities": [
          "assets.asset_assignments",
          "assets.assets",
          "recruit.onboarding_tasks"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "assets.asset_assignment.created",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "assets",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssetAssignmentCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Assigned.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetAssignment"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/assets": {
      "post": {
        "operationId": "assets.asset.create",
        "summary": "Register a company asset",
        "description": "AST-S04 **Add** — a new register row, `status = 'AVAILABLE'` (db 10 §3.1).",
        "tags": [
          "assets",
          "asset"
        ],
        "x-token": "assets.asset.create",
        "x-realizes-features": [
          "AST-F01"
        ],
        "x-screens": [
          "AST-S04"
        ],
        "x-touches-entities": [
          "assets.assets"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "assets",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssetCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Asset registered.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Asset"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/assets/admin": {
      "get": {
        "operationId": "assets.asset.list_admin",
        "summary": "Asset register console — list",
        "description": "AST-S04 grid — `asset_no`, name, category, serial/tag, status, condition, holder, value (db 10 §3.1).",
        "tags": [
          "assets",
          "asset"
        ],
        "x-token": "assets.asset.list_admin",
        "x-realizes-features": [
          "AST-F01"
        ],
        "x-screens": [
          "AST-S04"
        ],
        "x-touches-entities": [
          "assets.assets"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "assets",
        "x-provisional": null,
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/AssetCategory"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/AssetStatus"
            }
          },
          {
            "name": "condition",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/AssetCondition"
            }
          },
          {
            "name": "current_holder_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `asset_no`, `name`, `status`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tenant-wide page of registered assets.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/assets/{id}": {
      "get": {
        "operationId": "assets.asset.get",
        "summary": "Get one registered asset",
        "description": "AST-S04 detail drill-down.",
        "tags": [
          "assets",
          "asset"
        ],
        "x-token": "assets.asset.get",
        "x-realizes-features": [
          "AST-F01"
        ],
        "x-screens": [
          "AST-S04"
        ],
        "x-touches-entities": [
          "assets.assets"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "assets",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The registered asset.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Asset"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "assets.asset.update",
        "summary": "Edit a registered asset",
        "description": "AST-S04 — edits fields and drives status transitions (`AVAILABLE`/`IN_REPAIR`/`LOST`/`RETIRED`/`RESERVED`, db 10 §3.1).",
        "tags": [
          "assets",
          "asset"
        ],
        "x-token": "assets.asset.update",
        "x-realizes-features": [
          "AST-F01"
        ],
        "x-screens": [
          "AST-S04"
        ],
        "x-touches-entities": [
          "assets.assets"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "assets",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssetUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated asset.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Asset"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/asset-returns": {
      "post": {
        "operationId": "assets.asset_return.create",
        "summary": "Request the return of an assigned asset",
        "description": "AST-S03 **Submit return** — opens a return (`status = 'PENDING'`) against the assignment being closed; the assignment flips to `RETURN_REQUESTED` (db 10 §3.2). At exit, linked to the exit clearance item via `clearance_ref` (`ref→exit.exit_clearances`, `EXT-F02`) for HR/IT to receive/accept in `AST-S05`.\n\n**`clearance_ref` is DERIVED by this operation, never sent.** It is deliberately absent from `AssetReturnCreate`: the operation is `SELF`-scoped, so a caller-supplied cross-schema id would let one leaver point their return at another leaver's clearance case. The server reads the caller's own open clearance case under the caller's own scope — where the `exit_clearance_self_or_tenant` overlay makes any other case unreachable — and binds it. `null` is the ordinary answer: most returns are not exit returns, and the Exit-owned clearance consumer correctly ignores an unlinked one.\n",
        "tags": [
          "assets",
          "asset_return"
        ],
        "x-token": "assets.asset_return.create",
        "x-realizes-features": [
          "AST-F02"
        ],
        "x-screens": [
          "AST-S03"
        ],
        "x-touches-entities": [
          "assets.asset_returns",
          "assets.asset_assignments"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "assets.asset_return.requested",
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "assets",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssetReturnCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Return requested, `PENDING`; the assignment is now `RETURN_REQUESTED`.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetReturn"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/asset-returns/admin": {
      "get": {
        "operationId": "assets.asset_return.list_admin",
        "summary": "Assignment & return console — returns grid",
        "description": "HR/IT's returns grid — asset, employee, returned, condition-in, damage charge, clearance, status (AST-S05).",
        "tags": [
          "assets",
          "asset_return"
        ],
        "x-token": "assets.asset_return.list_admin",
        "x-realizes-features": [
          "AST-F02"
        ],
        "x-screens": [
          "AST-S05"
        ],
        "x-touches-entities": [
          "assets.asset_returns"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "assets",
        "x-provisional": null,
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/AssetReturnStatus"
            }
          },
          {
            "name": "employee_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "asset_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `returned_at`, `-returned_at`, `status`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tenant-wide page of asset returns.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetReturnPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "assets.asset_return.request_admin",
        "summary": "HR opens the return of somebody else's assigned asset",
        "description": "AST-S05 **Request return** — the HR/IT-driven half of `AST-F02`, and the counterpart of the `SELF`-scoped `assets.asset_return.create` above. It opens the same `PENDING` return against the same assignment and flips it to `RETURN_REQUESTED`; the only difference is WHOSE custody may be closed. `create` filters the assignment by the caller's own `employee_id`, so an HR admin acting on another employee's assignment never matched a row (404) and an owner with no employee row of their own was refused before that (403) — issue #1651. This operation carries no ownership filter and reads the assignment under the tenant scope instead.\n\n**The employee does not have to act.** The `assets.asset_return.requested` envelope this emits is consumed by the jobs tier, which writes the custodian an `IN_APP` notification naming the asset and the request date (`assets.return_requested`, design-ess/03 §5.4); HR then closes the loop with `assets.asset_return.confirm`.\n\n**`clearance_ref` is DERIVED by this operation, never sent** — as on `create`, and for the same reason. The case is read for the ASSIGNMENT's employee (the leaver), not for the caller, which is the one thing this tenant-scoped path must resolve differently: the open case belongs to the person whose custody is being closed.\n",
        "tags": [
          "assets",
          "asset_return"
        ],
        "x-token": "assets.asset_return.request_admin",
        "x-realizes-features": [
          "AST-F02"
        ],
        "x-screens": [
          "AST-S05"
        ],
        "x-touches-entities": [
          "assets.asset_returns",
          "assets.asset_assignments"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "assets.asset_return.requested",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "assets",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssetReturnCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Return requested, `PENDING`; the assignment is now `RETURN_REQUESTED`.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetReturn"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/asset-returns/{id}/confirm": {
      "post": {
        "operationId": "assets.asset_return.confirm",
        "summary": "Confirm a return in one action (receive, then accept)",
        "description": "AST-S05 **Confirm return** — one operator action that performs `assets.asset_return.receive` and `assets.asset_return.accept` inside ONE transaction: `status: PENDING → RETURNED → ACCEPTED`, `returned_at`/`condition_in` stamped, the assignment closed to `RETURNED` and the asset restocked to `AVAILABLE`. Both underlying envelopes are emitted, in order (`assets.asset_return.received` then `assets.asset_return.accepted`), so the Exit-owned clearance consumer sees exactly what the two-step path produces and the `clearance_ref` seam is unchanged.\n\n**The two verbs remain, and this composes them — it does not replace them.** Receiving and accepting separately is still right whenever the condition has to be adjudicated between the two (dispute, waive); confirm is for the ordinary case where the asset is back on the desk and the operator is settling it in one go. It is granted to exactly the roles that hold `receive` + `accept`, so it widens no reach (security-docs/02 §3, issue #1651).\n\n`If-Match` carries the version of the **PENDING** return, exactly as `receive` does; the intermediate version this operation writes is never observed by the caller.\n",
        "tags": [
          "assets",
          "asset_return"
        ],
        "x-token": "assets.asset_return.confirm",
        "x-realizes-features": [
          "AST-F02"
        ],
        "x-screens": [
          "AST-S05"
        ],
        "x-touches-entities": [
          "assets.asset_returns",
          "assets.asset_assignments",
          "assets.assets",
          "exit.exit_clearances"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "assets.asset_return.accepted",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "assets",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssetReturnReceiveInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received and accepted; custody closed and the asset is back in stock.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetReturn"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/asset-returns/{id}/receive": {
      "post": {
        "operationId": "assets.asset_return.receive",
        "summary": "Receive a returned asset",
        "description": "AST-S05 **Receive return** — `status: PENDING → RETURNED`, stamps `returned_at`, confirms `condition_in` (db 10 §3.2).",
        "tags": [
          "assets",
          "asset_return"
        ],
        "x-token": "assets.asset_return.receive",
        "x-realizes-features": [
          "AST-F02"
        ],
        "x-screens": [
          "AST-S05"
        ],
        "x-touches-entities": [
          "assets.asset_returns"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "assets.asset_return.received",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "assets",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssetReturnReceiveInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetReturn"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/asset-returns/{id}/accept": {
      "post": {
        "operationId": "assets.asset_return.accept",
        "summary": "Accept a returned asset (closes custody, clears F&F gate)",
        "description": "AST-S05 **Accept** — `status → ACCEPTED`; the parent asset flips back to `AVAILABLE` and the linked `asset_assignments` row closes to `RETURNED` (db 10 §3.2). **Gates full-&-final:** until every assigned asset is `ACCEPTED`/`WAIVED`, exit clearance (`EXT-F02`) holds, blocking F&F settlement in `pay` (`PAY-F07`) — by **event**, never a cross-schema write.\n",
        "tags": [
          "assets",
          "asset_return"
        ],
        "x-token": "assets.asset_return.accept",
        "x-realizes-features": [
          "AST-F02"
        ],
        "x-screens": [
          "AST-S05"
        ],
        "x-touches-entities": [
          "assets.asset_returns",
          "assets.asset_assignments",
          "assets.assets",
          "exit.exit_clearances"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "assets.asset_return.accepted",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "assets",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActionNoteInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Accepted; custody closed.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetReturn"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/asset-returns/{id}/waive": {
      "post": {
        "operationId": "assets.asset_return.waive",
        "summary": "Waive a return (closes custody without physical hand-back)",
        "description": "AST-S05 **Waive** — `status → WAIVED` (e.g. asset assigned permanently / written off); the linked `asset_assignments` row still closes to `RETURNED`, but the asset does **not** re-enter `AVAILABLE` stock (db 10 §3.2 Notes). Also clears the F&F gate, same as `accept`.\n",
        "tags": [
          "assets",
          "asset_return"
        ],
        "x-token": "assets.asset_return.waive",
        "x-realizes-features": [
          "AST-F02"
        ],
        "x-screens": [
          "AST-S05"
        ],
        "x-touches-entities": [
          "assets.asset_returns",
          "assets.asset_assignments",
          "exit.exit_clearances"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "assets.asset_return.waived",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "assets",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActionNoteInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Waived; custody closed.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetReturn"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/asset-returns/{id}/dispute": {
      "post": {
        "operationId": "assets.asset_return.dispute",
        "summary": "Flag a return discrepancy (damage/loss charge)",
        "description": "AST-S05 — `status → DISPUTED` when the returned condition doesn't match custody-out (damage/ discrepancy); may raise `damage_charge_amount`, which flows into full-&-final as a recovery, by event, never a cross-schema write (db 10 §3.2).\n",
        "tags": [
          "assets",
          "asset_return"
        ],
        "x-token": "assets.asset_return.dispute",
        "x-realizes-features": [
          "AST-F02"
        ],
        "x-screens": [
          "AST-S05"
        ],
        "x-touches-entities": [
          "assets.asset_returns"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "assets.asset_return.disputed",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "assets",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssetReturnDisputeInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Disputed.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetReturn"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerJWT": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Product session token. Two mint paths, one contract (ADR 0010): employees/managers authenticate against Keycloak (mobile + web); workspace staff arrive from the One portal via bridge-token SSO (`POST /api/sso/exchange` verifies the platform's Ed25519 token and mints the product session). The token carries IDENTITY ONLY — `sub`, `tenantUid`, `principal_class`, MFA level, session ref, `exp`. Roles/permissions are re-resolved server-side per request. Enforcement is layered: gateway (TLS/WAF/routing only — NEVER trusted for auth) → NestJS auth guard (validates token, builds the request auth-context) → entitlement middleware (subscription-status → feature-flag → numeric-limit, ADR 0009) → `SET LOCAL app.tenant_id` / `app.user_id` → Postgres FORCED RLS. `tenantUid` is NEVER a path, query, or body parameter.\n"
      }
    },
    "schemas": {
      "UuidRef": {
        "$ref": "#/components/schemas/Uuid"
      },
      "TimestampRef": {
        "$ref": "#/components/schemas/Timestamp"
      },
      "DateOnlyRef": {
        "$ref": "#/components/schemas/DateOnly"
      },
      "BusinessNoRef": {
        "$ref": "#/components/schemas/BusinessNo"
      },
      "MoneyRef": {
        "$ref": "#/components/schemas/Money"
      },
      "LocalizedTextRef": {
        "$ref": "#/components/schemas/LocalizedText"
      },
      "FileDownloadRef": {
        "$ref": "#/components/schemas/FileDownload"
      },
      "AuditMetaRef": {
        "$ref": "#/components/schemas/AuditMeta"
      },
      "AppendOnlyMetaRef": {
        "$ref": "#/components/schemas/AppendOnlyMeta"
      },
      "CursorPageRef": {
        "$ref": "#/components/schemas/CursorPage"
      },
      "SoftRefRef": {
        "$ref": "#/components/schemas/SoftRef"
      },
      "ActionNoteInput": {
        "type": "object",
        "description": "Generic optional-note body shared by every no-payload approve/transition action in this file.",
        "additionalProperties": false,
        "properties": {
          "note": {
            "type": "string"
          }
        }
      },
      "FolderType": {
        "type": "string",
        "enum": [
          "EMPLOYEE",
          "COMPANY",
          "POLICY",
          "LETTER",
          "STATUTORY",
          "GENERAL"
        ],
        "description": "docs.document_library.folder_type (db 10 §1.1)."
      },
      "FolderVisibility": {
        "type": "string",
        "enum": [
          "RBAC",
          "EMPLOYEE_SELF",
          "MANAGER",
          "HR_ONLY"
        ],
        "description": "docs.document_library.visibility (db 10 §1.1)."
      },
      "DocType": {
        "type": "string",
        "enum": [
          "LETTER",
          "POLICY",
          "PAYSLIP",
          "CERTIFICATE",
          "ID_PROOF",
          "CONTRACT",
          "STATUTORY",
          "GENERAL"
        ],
        "description": "docs.documents.doc_type (db 10 §1.1)."
      },
      "DocumentSource": {
        "type": "string",
        "enum": [
          "UPLOAD",
          "GENERATED",
          "ESIGN",
          "IMPORTED"
        ],
        "description": "docs.documents.source (db 10 §1.1)."
      },
      "DocumentStatus": {
        "type": "string",
        "enum": [
          "ACTIVE",
          "SUPERSEDED",
          "ARCHIVED",
          "DELETED"
        ],
        "description": "docs.documents.status (db 10 §1.1)."
      },
      "EsignSignMethod": {
        "type": "string",
        "enum": [
          "OTP",
          "AADHAAR_ESIGN",
          "ACCEPTED_SIGNATURE",
          "DRAWN",
          "EXTERNAL"
        ],
        "description": "docs.esign_requests.sign_method — pack-gated (XC-F01); `EXTERNAL` is a Later facet (db 10 §1.2)."
      },
      "EsignSigningOrder": {
        "type": "string",
        "enum": [
          "PARALLEL",
          "SEQUENTIAL"
        ],
        "description": "docs.esign_requests.signing_order (db 10 §1.2)."
      },
      "EsignRequestStatus": {
        "type": "string",
        "enum": [
          "DRAFT",
          "SENT",
          "IN_PROGRESS",
          "COMPLETED",
          "DECLINED",
          "EXPIRED",
          "CANCELLED"
        ],
        "description": "docs.esign_requests.status (db 10 §1.2)."
      },
      "SignatoryRole": {
        "type": "string",
        "enum": [
          "SIGNER",
          "APPROVER",
          "WITNESS"
        ],
        "description": "docs.esign_requests.signatories[].role (db 10 §1.2 JSONB payload shape)."
      },
      "SignatoryState": {
        "type": "string",
        "enum": [
          "PENDING",
          "SIGNED",
          "DECLINED"
        ],
        "description": "docs.esign_requests.signatories[].state (db 10 §1.2 JSONB payload shape)."
      },
      "EsignDecision": {
        "type": "string",
        "enum": [
          "SIGNED",
          "DECLINED"
        ],
        "description": "docs.esign_signatures.decision (db 10 §1.2)."
      },
      "LetterType": {
        "type": "string",
        "enum": [
          "CTC",
          "INCREMENT",
          "EXPERIENCE",
          "APPOINTMENT",
          "CONFIRMATION",
          "RELIEVING",
          "WARNING",
          "OTHER"
        ],
        "description": "docs.letters.letter_type (db 10 §1.3). No `'PROMOTION'` value exists — promotion letters carry `'INCREMENT'`/`'OTHER'` (fsd 09 coverage gap 9, candidate not added here).\n"
      },
      "LetterStatus": {
        "type": "string",
        "enum": [
          "DRAFT",
          "GENERATED",
          "ISSUED",
          "SIGNED",
          "VOID"
        ],
        "description": "docs.letters.status (db 10 §1.3)."
      },
      "AckType": {
        "type": "string",
        "enum": [
          "READ",
          "ACCEPT"
        ],
        "description": "docs.acknowledgements.ack_type (db 10 §1.3)."
      },
      "PolicyCategory": {
        "type": "string",
        "enum": [
          "HR",
          "IT",
          "FINANCE",
          "SECURITY",
          "CONDUCT",
          "SAFETY",
          "OTHER"
        ],
        "description": "docs.policies.category (db 10 §1.3)."
      },
      "PolicyStatus": {
        "type": "string",
        "enum": [
          "DRAFT",
          "PUBLISHED",
          "SUPERSEDED",
          "ARCHIVED"
        ],
        "description": "docs.policies.status (db 10 §1.3)."
      },
      "TicketCategory": {
        "type": "string",
        "enum": [
          "HR",
          "IT",
          "PAYROLL",
          "FACILITIES",
          "ADMIN",
          "OTHER"
        ],
        "description": "desk.tickets.category — drives routing + SLA target (db 10 §2.1)."
      },
      "TicketPriority": {
        "type": "string",
        "enum": [
          "LOW",
          "MEDIUM",
          "HIGH",
          "URGENT"
        ],
        "description": "desk.tickets.priority (db 10 §2.1)."
      },
      "TicketStatus": {
        "type": "string",
        "enum": [
          "OPEN",
          "IN_PROGRESS",
          "ON_HOLD",
          "RESOLVED",
          "CLOSED",
          "CANCELLED"
        ],
        "description": "desk.tickets.status (db 10 §2.1, rev. 2026-07-02). No reachable `'REOPENED'` value — a reopen is `RESOLVED`/`CLOSED → IN_PROGRESS` plus `reopened_count`++ and a system `'REOPEN'` message.\n"
      },
      "MessageAuthorRole": {
        "type": "string",
        "enum": [
          "REQUESTER",
          "RESOLVER",
          "SYSTEM"
        ],
        "description": "desk.ticket_messages.author_role (db 10 §2.1)."
      },
      "MessageType": {
        "type": "string",
        "enum": [
          "COMMENT",
          "STATUS_CHANGE",
          "ASSIGNMENT",
          "RESOLUTION",
          "REOPEN"
        ],
        "description": "desk.ticket_messages.message_type (db 10 §2.1)."
      },
      "SlaBreachStatus": {
        "type": "string",
        "enum": [
          "WITHIN_SLA",
          "AT_RISK",
          "RESPONSE_BREACHED",
          "RESOLUTION_BREACHED"
        ],
        "description": "desk.ticket_slas.breach_status (db 10 §2.1)."
      },
      "CsatSentiment": {
        "type": "string",
        "enum": [
          "POSITIVE",
          "NEUTRAL",
          "NEGATIVE"
        ],
        "description": "desk.csat_responses.sentiment — bucketed from rating (4–5/3/1–2, db 10 §2.2)."
      },
      "KbCategory": {
        "type": "string",
        "enum": [
          "HR",
          "IT",
          "PAYROLL",
          "FACILITIES",
          "ONBOARDING",
          "OTHER"
        ],
        "description": "desk.kb_articles.category (db 10 §2.2)."
      },
      "KbVisibility": {
        "type": "string",
        "enum": [
          "ALL_EMPLOYEES",
          "RBAC",
          "RESOLVER_ONLY"
        ],
        "description": "desk.kb_articles.visibility (db 10 §2.2)."
      },
      "KbStatus": {
        "type": "string",
        "enum": [
          "DRAFT",
          "UNDER_REVIEW",
          "PUBLISHED",
          "ARCHIVED"
        ],
        "description": "desk.kb_articles.status (db 10 §2.2)."
      },
      "AssetCategory": {
        "type": "string",
        "enum": [
          "LAPTOP",
          "PHONE",
          "SIM",
          "ACCESS_CARD",
          "VEHICLE",
          "MONITOR",
          "PERIPHERAL",
          "EQUIPMENT",
          "TOOL",
          "OTHER"
        ],
        "description": "`assets.assets.category` (db 10 §3.1). Append-only vocabulary — a member is added, never renamed. `EQUIPMENT` (powered/major plant the crew deploys) and `TOOL` (hand tooling) joined in migration `0220` (#1597): the register was authored for the office estate and had no member for SITE PLANT, and a `ONE_TIME` project petty-cash line may now register what it bought (`work.project_cost.create`'s `register_as_asset`).\n"
      },
      "AssetCondition": {
        "type": "string",
        "enum": [
          "NEW",
          "GOOD",
          "FAIR",
          "DAMAGED",
          "RETIRED"
        ],
        "description": "assets.asset_condition (db 10 §3.1)."
      },
      "AssetStatus": {
        "type": "string",
        "enum": [
          "AVAILABLE",
          "ASSIGNED",
          "IN_REPAIR",
          "LOST",
          "RETIRED",
          "RESERVED"
        ],
        "description": "assets.assets.status (db 10 §3.1)."
      },
      "AssetAssignmentStatus": {
        "type": "string",
        "enum": [
          "ASSIGNED",
          "ACKNOWLEDGED",
          "RETURN_REQUESTED",
          "RETURNED",
          "LOST"
        ],
        "description": "assets.asset_assignments.status (db 10 §3.2)."
      },
      "AssetReturnStatus": {
        "type": "string",
        "enum": [
          "PENDING",
          "RETURNED",
          "ACCEPTED",
          "DISPUTED",
          "WAIVED"
        ],
        "description": "assets.asset_returns.status (db 10 §3.2)."
      },
      "DocumentFolder": {
        "description": "docs.document_library — a folder node in the RBAC-scoped document tree (db 10 §1.1).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "name",
              "folder_type",
              "visibility"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "legal_entity_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "null = tenant-global root."
              },
              "parent_folder_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "name": {
                "type": "string"
              },
              "slug": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "folder_type": {
                "$ref": "#/components/schemas/FolderType"
              },
              "visibility": {
                "$ref": "#/components/schemas/FolderVisibility"
              },
              "is_system": {
                "type": "boolean"
              },
              "sort_order": {
                "type": "integer",
                "minimum": 0
              },
              "document_count": {
                "type": "integer",
                "minimum": 0,
                "readOnly": true,
                "description": "Derived: live `docs.documents` rows filed **at this node** — direct children only, not the subtree, which is what the `DOC-S07` tree renders beside a single node. It is the same predicate `docs.document_folder.delete` refuses on, so the count a console shows and the refusal it gets can never disagree.\n"
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "DocumentFolderCreate": {
        "type": "object",
        "required": [
          "name"
        ],
        "additionalProperties": false,
        "properties": {
          "legal_entity_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "parent_folder_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "name": {
            "type": "string",
            "minLength": 1
          },
          "slug": {
            "type": "string"
          },
          "folder_type": {
            "$ref": "#/components/schemas/FolderType"
          },
          "visibility": {
            "$ref": "#/components/schemas/FolderVisibility"
          },
          "sort_order": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "DocumentFolderUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1
          },
          "parent_folder_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "visibility": {
            "$ref": "#/components/schemas/FolderVisibility"
          },
          "sort_order": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "DocumentFolderPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/DocumentFolder"
                }
              }
            }
          }
        ]
      },
      "DocumentLetterSummary": {
        "type": "object",
        "readOnly": true,
        "description": "Joined `docs.letters` projection for a letter-backed document (DOC-S01 expandable letter summary) — `render_context` carries `{ctc, currency, effective_date, ...}` frozen at render.\n",
        "properties": {
          "letter_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "letter_type": {
            "$ref": "#/components/schemas/LetterType"
          },
          "status": {
            "$ref": "#/components/schemas/LetterStatus"
          },
          "render_context": {
            "type": "object",
            "additionalProperties": true
          },
          "esign_request_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/UuidRef"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "DocumentEsignSummary": {
        "type": "object",
        "readOnly": true,
        "additionalProperties": false,
        "required": [
          "esign_request_id",
          "status",
          "sign_method",
          "signing_order",
          "total_signatories",
          "your_state"
        ],
        "description": "**Caller-scoped** `docs.esign_requests` projection for a document under signature (DOC-S03/ DOC-S04) — the ceremony's shape plus **the requesting employee's own seat, and no other**.\nThis exists because `docs.esign_request.get` is an `hr_admin`, tenant-scoped operation: the employee being asked to sign has no read of the ceremony itself, so this field is the entire e-sign contract the ESS surface is built on. It is therefore deliberately subtractive — `total_signatories` is a **count**, never a roster, and no co-signer's `employee_id`, `role`, `state` or `signed_at` appears anywhere in it. HR reads the full roster through `EsignRequest.signatories`, which is a different operation behind a different token.\n`null` when this document has no e-sign request **or** when the caller holds no seat on its roster — the two are indistinguishable by design, so that neither the initiator nor an admin-scoped reader can learn a signatory's position from a document read.\n",
        "properties": {
          "esign_request_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "status": {
            "$ref": "#/components/schemas/EsignRequestStatus"
          },
          "sign_method": {
            "$ref": "#/components/schemas/EsignSignMethod"
          },
          "signing_order": {
            "$ref": "#/components/schemas/EsignSigningOrder"
          },
          "expires_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TimestampRef"
              },
              {
                "type": "null"
              }
            ]
          },
          "requested_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TimestampRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the ceremony was raised (`esign_requests.created_at`); there is no separate `sent_at`."
          },
          "initiated_by": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/UuidRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "The initiator's employee id — an id, not a name; ESS copy stays name-free."
          },
          "total_signatories": {
            "type": "integer",
            "minimum": 0,
            "description": "How many seats the ceremony has — a count only. Falls back to the roster length while the denormalized counter is still 0 on a `DRAFT` (`05 §4.3`); identical to it once sent.\n"
          },
          "your_order": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "description": "The caller's own position in the routing order."
          },
          "your_role": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SignatoryRole"
              },
              {
                "type": "null"
              }
            ]
          },
          "your_state": {
            "allOf": [
              {
                "$ref": "#/components/schemas/SignatoryState"
              }
            ],
            "description": "The caller's OWN seat state. Non-null whenever this object is present — a seat is what makes it present."
          },
          "your_signed_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TimestampRef"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "Document": {
        "description": "docs.documents — a stored HR document (letter, payslip, certificate, ID/Iqama scan, policy PDF). Bytes never in Postgres — `file` is a freshly minted presigned handle (`XC-F07`, db 10 §1.1).\n",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "title",
              "doc_type",
              "source",
              "version_no",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "folder_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "employee_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "legal_entity_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "title": {
                "type": "string"
              },
              "doc_type": {
                "$ref": "#/components/schemas/DocType"
              },
              "source": {
                "$ref": "#/components/schemas/DocumentSource"
              },
              "file": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/FileDownloadRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "A freshly minted, short-lived presigned handle (`XC-F07`) — the storage key itself never leaves the server. **Detail reads only**: `docs.document.list` / `.list_admin` return `null` here, because minting a handle is a round-trip to the object-storage seam and a library grid does not download every file. Open the document (`docs.document.get`) to get one.\n"
              },
              "mime_type": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "file_size_bytes": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 0
              },
              "version_no": {
                "type": "integer",
                "minimum": 1
              },
              "supersedes_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "status": {
                "$ref": "#/components/schemas/DocumentStatus"
              },
              "requires_ack": {
                "type": "boolean"
              },
              "retention_class": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "issued_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "folder_visibility": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/FolderVisibility"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Derived: the filing folder's visibility scope (DOC-S01 privacy note)."
              },
              "pending_signature": {
                "type": "boolean",
                "description": "Derived: an `esign_requests` row on this document (directly, or via `letters.esign_request_id`) has `status ∈ ('SENT','IN_PROGRESS')` with the caller's `signatories[].state = 'PENDING'` (fsd 09 coverage gap 4 — not a stored column).\n"
              },
              "esign_status": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/EsignRequestStatus"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "esign": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DocumentEsignSummary"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Derived, **caller-scoped**: the ceremony on this document (directly, or via `letters.esign_request_id`) as seen by the requesting employee — their own seat plus the ceremony's shape, and no co-signer identity. `null` when there is no ceremony, or when the caller holds no seat on it. This is the ESS signing surface's only e-sign read (`docs.esign_request.get` is HR-scoped), so it is present on every `Document` projection, list rows included.\n"
              },
              "letter": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DocumentLetterSummary"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "DocumentAdminDetail": {
        "description": "`docs.document.get_admin` — the document plus its `supersedes_id` version chain (DOC-S07 detail). Chain entries are the same wire shape and carry `file: null`; only the requested document is presigned.\n",
        "allOf": [
          {
            "$ref": "#/components/schemas/Document"
          },
          {
            "type": "object",
            "required": [
              "versions"
            ],
            "properties": {
              "versions": {
                "type": "array",
                "readOnly": true,
                "description": "Every version on this document's `supersedes_id` chain — the ones it replaced AND the ones that replaced it — **newest `version_no` first**, the requested row included. A single-version document returns exactly itself.\n",
                "items": {
                  "$ref": "#/components/schemas/Document"
                }
              }
            }
          }
        ]
      },
      "DocumentUpload": {
        "type": "object",
        "description": "storage_key/content_hash are the result of a prior presigned-upload flow (`XC-F07`) — bytes never post here.",
        "required": [
          "title",
          "doc_type",
          "storage_key"
        ],
        "additionalProperties": false,
        "properties": {
          "folder_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "employee_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "legal_entity_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "title": {
            "type": "string",
            "minLength": 1
          },
          "doc_type": {
            "$ref": "#/components/schemas/DocType"
          },
          "storage_key": {
            "type": "string"
          },
          "content_hash": {
            "type": "string"
          },
          "mime_type": {
            "type": "string"
          },
          "file_size_bytes": {
            "type": "integer",
            "minimum": 0
          },
          "requires_ack": {
            "type": "boolean"
          },
          "issued_at": {
            "$ref": "#/components/schemas/TimestampRef"
          }
        }
      },
      "DocumentUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1
          },
          "folder_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "doc_type": {
            "$ref": "#/components/schemas/DocType"
          },
          "requires_ack": {
            "type": "boolean"
          },
          "retention_class": {
            "type": "string"
          }
        }
      },
      "DocumentReissue": {
        "type": "object",
        "description": "New version fields; `storage_key`/`content_hash` from a fresh presigned-upload flow (`XC-F07`).",
        "required": [
          "storage_key"
        ],
        "additionalProperties": false,
        "properties": {
          "storage_key": {
            "type": "string"
          },
          "content_hash": {
            "type": "string"
          },
          "mime_type": {
            "type": "string"
          },
          "file_size_bytes": {
            "type": "integer",
            "minimum": 0
          },
          "title": {
            "type": "string"
          },
          "issued_at": {
            "$ref": "#/components/schemas/TimestampRef"
          }
        }
      },
      "DocumentPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Document"
                }
              }
            }
          }
        ]
      },
      "Signatory": {
        "type": "object",
        "description": "docs.esign_requests.signatories[] — the routing roster snapshot (db 10 §1.2 JSONB payload shape).",
        "required": [
          "employee_id",
          "order",
          "role",
          "state"
        ],
        "additionalProperties": false,
        "properties": {
          "employee_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "order": {
            "type": "integer",
            "minimum": 1
          },
          "role": {
            "$ref": "#/components/schemas/SignatoryRole"
          },
          "state": {
            "$ref": "#/components/schemas/SignatoryState"
          },
          "signed_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TimestampRef"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "EsignRequest": {
        "description": "docs.esign_requests — a signature ceremony over one document (db 10 §1.2).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "document_id",
              "sign_method",
              "signing_order",
              "status",
              "signed_count",
              "total_signatories"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "document_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "initiated_by": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "sign_method": {
                "$ref": "#/components/schemas/EsignSignMethod"
              },
              "signing_order": {
                "$ref": "#/components/schemas/EsignSigningOrder"
              },
              "signatories": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Signatory"
                }
              },
              "status": {
                "$ref": "#/components/schemas/EsignRequestStatus"
              },
              "signed_count": {
                "type": "integer",
                "minimum": 0
              },
              "total_signatories": {
                "type": "integer",
                "minimum": 0
              },
              "signed_file": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/FileDownloadRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Presigned signed-artifact download; `content_hash` carries tamper-evidence."
              },
              "expires_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "completed_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "EsignSignature": {
        "description": "docs.esign_signatures — the captured, append-only evidence of one signatory's decision (Immutable, db 10 §1.2). `otp_ref` is an opaque handle only — OTP material lives in `xc`/Redis.\n",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "esign_request_id",
              "signatory_id",
              "sign_method",
              "decision",
              "signed_at"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "esign_request_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "signatory_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "sign_method": {
                "$ref": "#/components/schemas/EsignSignMethod"
              },
              "decision": {
                "$ref": "#/components/schemas/EsignDecision"
              },
              "signed_at": {
                "$ref": "#/components/schemas/TimestampRef"
              },
              "evidence_hash": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "otp_ref": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "signature_metadata": {
                "type": "object",
                "description": "Capture evidence — ip, device, user_agent, geo, consent_text_version, captured_at (db 10 §1.2 JSONB payload shape).",
                "additionalProperties": true
              }
            }
          },
          {
            "$ref": "#/components/schemas/AppendOnlyMetaRef"
          }
        ]
      },
      "EsignRequestDetail": {
        "description": "DOC-S09 detail — the ceremony plus its append-only signature evidence panel.",
        "allOf": [
          {
            "$ref": "#/components/schemas/EsignRequest"
          },
          {
            "type": "object",
            "properties": {
              "signatures": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/EsignSignature"
                }
              }
            }
          }
        ]
      },
      "EsignRequestCreate": {
        "type": "object",
        "required": [
          "document_id",
          "sign_method",
          "signing_order",
          "signatories"
        ],
        "additionalProperties": false,
        "properties": {
          "document_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "sign_method": {
            "$ref": "#/components/schemas/EsignSignMethod"
          },
          "signing_order": {
            "$ref": "#/components/schemas/EsignSigningOrder"
          },
          "signatories": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "required": [
                "employee_id",
                "order",
                "role"
              ],
              "additionalProperties": false,
              "properties": {
                "employee_id": {
                  "$ref": "#/components/schemas/UuidRef"
                },
                "order": {
                  "type": "integer",
                  "minimum": 1
                },
                "role": {
                  "$ref": "#/components/schemas/SignatoryRole"
                }
              }
            }
          },
          "expires_at": {
            "$ref": "#/components/schemas/TimestampRef"
          }
        }
      },
      "EsignRequestPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/EsignRequest"
                }
              }
            }
          }
        ]
      },
      "EsignSignatureSignInput": {
        "type": "object",
        "required": [
          "consent"
        ],
        "additionalProperties": false,
        "description": "DOC-S03 sign ceremony. `otp_ref` is required on OTP/Aadhaar-eSign rails; omitted on accepted-signature (`XC-F01`).",
        "properties": {
          "consent": {
            "type": "boolean",
            "description": "Must be true — explicit e-sign consent (consent-gated)."
          },
          "otp_ref": {
            "type": "string",
            "description": "Opaque OTP/Aadhaar-eSign verification handle — never the OTP itself."
          },
          "signature_metadata": {
            "type": "object",
            "properties": {
              "device": {
                "type": "string"
              },
              "user_agent": {
                "type": "string"
              },
              "geo": {
                "type": "string"
              },
              "consent_text_version": {
                "type": "string"
              }
            }
          }
        }
      },
      "EsignSignatureDeclineInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "reason": {
            "type": "string"
          },
          "signature_metadata": {
            "type": "object",
            "properties": {
              "device": {
                "type": "string"
              },
              "user_agent": {
                "type": "string"
              }
            }
          }
        }
      },
      "EsignChallengeResult": {
        "type": "object",
        "description": "The issued signing challenge (`R-12`). Carries the OPAQUE handle only — the code itself is delivered out of band and lives in `xc`/Redis, never in `docs`.\n",
        "required": [
          "otp_ref",
          "expires_at",
          "resend_after"
        ],
        "additionalProperties": false,
        "properties": {
          "otp_ref": {
            "type": "string",
            "description": "Opaque verification handle. A resend re-uses it; the code behind it is fresh."
          },
          "expires_at": {
            "$ref": "#/components/schemas/TimestampRef"
          },
          "delivered_to_masked": {
            "type": [
              "string",
              "null"
            ],
            "description": "The delivery target, masked (`p•••@example.com`). Never the full address."
          },
          "resend_after": {
            "type": "integer",
            "minimum": 0,
            "description": "Seconds before another code may be requested. The UI renders this as a timer."
          }
        }
      },
      "EsignChallengeVerifyInput": {
        "type": "object",
        "required": [
          "otp_ref",
          "code"
        ],
        "additionalProperties": false,
        "properties": {
          "otp_ref": {
            "type": "string",
            "description": "The handle returned by `docs.esign_signature.challenge`."
          },
          "code": {
            "type": "string",
            "pattern": "^[0-9]{6}$",
            "description": "The six-digit delivered code. Checked against `xc`/Redis and never persisted."
          }
        }
      },
      "EsignChallengeVerifyResult": {
        "type": "object",
        "required": [
          "otp_ref",
          "verified",
          "verified_until"
        ],
        "additionalProperties": false,
        "properties": {
          "otp_ref": {
            "type": "string"
          },
          "verified": {
            "type": "boolean"
          },
          "verified_until": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TimestampRef"
              }
            ],
            "description": "When the verified window lapses; `docs.esign_signature.sign` must be called before it."
          }
        }
      },
      "EsignCeremonyState": {
        "type": "object",
        "readOnly": true,
        "additionalProperties": false,
        "required": [
          "status",
          "signed_count",
          "total_signatories"
        ],
        "description": "**Caller-scoped** post-action state of the ceremony, returned to the signatory who just acted (`docs.esign_signature.sign` / `.decline`).\nDeliberately subtractive, for the same reason as `DocumentEsignSummary`: those two operations are `self`-scoped, employee-held tokens, and the roster read sits behind `docs.esign_request.get`, an `hr_admin`/tenant token the signatory does not hold. Completing a ceremony must not become the way a signatory learns **who else was asked and what they decided** — no co-signer's `employee_id`, `role`, `state` or `signed_at` appears here. `signed_count`/`total_signatories` are **counts**, never a roster: \"signature 2 of 3\" is what DOC-S03 renders, and it needs no other person's identity to render it. HR reads the full ceremony — roster, signed artifact, audit meta — through `EsignRequest`, a different operation behind a different token.\n",
        "properties": {
          "status": {
            "$ref": "#/components/schemas/EsignRequestStatus"
          },
          "signed_count": {
            "type": "integer",
            "minimum": 0
          },
          "total_signatories": {
            "type": "integer",
            "minimum": 0,
            "description": "How many seats the ceremony has — a count only. Falls back to the roster length while the denormalized counter is still 0 on a `DRAFT` (`05 §4.3`); identical to it once sent.\n"
          }
        }
      },
      "EsignSignatureResult": {
        "description": "The captured signature/decline plus the CALLER-SCOPED post-action state of the ceremony. `esign_request` is an `EsignCeremonyState`, not an `EsignRequest`: the acting signatory is `self`-scoped and never receives the co-signer roster from their own capture.\n",
        "allOf": [
          {
            "$ref": "#/components/schemas/EsignSignature"
          },
          {
            "type": "object",
            "properties": {
              "esign_request": {
                "$ref": "#/components/schemas/EsignCeremonyState"
              }
            }
          }
        ]
      },
      "LetterRenderContext": {
        "type": "object",
        "readOnly": true,
        "allOf": [
          {
            "$ref": "#/components/schemas/ConfigVersionStamp"
          }
        ],
        "description": "db 10 §1.3 `letters.render_context` JSONB shape — the **frozen** merge data the letter was rendered from, plus the resolved tenant-config key→version map (rev. 2026-07-02, replaces the scalar `tenant_config_version`); schemaless, not queried.\n",
        "properties": {
          "employee_name": {
            "type": "string"
          },
          "designation": {
            "type": "string"
          },
          "ctc": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "effective_date": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "components": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "locale": {
            "type": "string"
          },
          "template_version": {
            "type": "integer",
            "minimum": 1
          },
          "self_serve": {
            "type": "boolean"
          }
        }
      },
      "Letter": {
        "description": "docs.letters — a generated HR letter (CTC/increment/experience/appointment/...), rendered from an `org.templates` row on the jobs tier and filed back as a `documents` row (db 10 §1.3).\n",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "letter_type",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "document_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "The filed `source = 'GENERATED'` document. **Null while `status = 'DRAFT'`** — the jobs tier has not produced the PDF yet, and `documents.storage_key` is NOT NULL, so there is nothing to file until it has (db 10 §1.3 Build notes, issue #100). Non-null from `GENERATED` onward, enforced by a CHECK.\n"
              },
              "template_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→org.templates (ORG-F08)."
              },
              "template_render_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→org.template_renders — the ADR 0023 render this letter is waiting on (db 10 §1.3 Build notes)."
              },
              "employee_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "letter_type": {
                "$ref": "#/components/schemas/LetterType"
              },
              "render_context": {
                "$ref": "#/components/schemas/LetterRenderContext"
              },
              "template_version": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "pay_structure_version": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "compliance_pack_version": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "status": {
                "$ref": "#/components/schemas/LetterStatus"
              },
              "esign_request_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "issued_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "render_error": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The worker's permanent-failure reason when the render could not succeed; the letter is `VOID`. Null on every other path — a poll that returns this has a reason the caller can act on rather than a request stuck in `DRAFT`.\n"
              },
              "file": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/FileDownloadRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Presigned download of the filed document (resolved via `document_id`). **Detail reads only** — `docs.letter.list` / `.list_me` return `null` here, because minting a handle is a round-trip to the object-storage seam and a grid does not download every PDF.\n"
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "LetterGenerateRequest": {
        "type": "object",
        "required": [
          "template_id",
          "employee_id",
          "letter_type"
        ],
        "additionalProperties": false,
        "properties": {
          "template_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "employee_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "letter_type": {
            "$ref": "#/components/schemas/LetterType"
          },
          "render_context_overrides": {
            "type": "object",
            "description": "Optional wizard-reviewed overrides merged into the server-resolved render context before render.",
            "additionalProperties": true
          }
        }
      },
      "LetterSelfRequest": {
        "type": "object",
        "description": "The whole self-serve request body (ESS #693). It carries a letter type and nothing else BY DESIGN: the subject is the caller (from the authorization decision, never the body) and every merge value is resolved server-side from the caller's own employee and compensation rows, so there is no field through which content could be injected into a document the company signs. Compare `LetterGenerateRequest`, whose `render_context_overrides` is a legitimate affordance for an `hr_admin` already trusted with the underlying render token.\n",
        "required": [
          "letter_type"
        ],
        "additionalProperties": false,
        "properties": {
          "letter_type": {
            "allOf": [
              {
                "$ref": "#/components/schemas/LetterType"
              }
            ],
            "description": "Restricted to the fact-restating set — `CTC` (salary certificate), `EXPERIENCE`, `CONFIRMATION` (bonafide/employment certificate) and `OTHER`. `INCREMENT`, `APPOINTMENT`, `RELIEVING` and `WARNING` each assert a DECISION and are refused with 422.\n"
          }
        }
      },
      "LetterRouteToEsignInput": {
        "type": "object",
        "required": [
          "sign_method",
          "signing_order",
          "signatories"
        ],
        "additionalProperties": false,
        "properties": {
          "sign_method": {
            "$ref": "#/components/schemas/EsignSignMethod"
          },
          "signing_order": {
            "$ref": "#/components/schemas/EsignSigningOrder"
          },
          "signatories": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "required": [
                "employee_id",
                "order",
                "role"
              ],
              "additionalProperties": false,
              "properties": {
                "employee_id": {
                  "$ref": "#/components/schemas/UuidRef"
                },
                "order": {
                  "type": "integer",
                  "minimum": 1
                },
                "role": {
                  "$ref": "#/components/schemas/SignatoryRole"
                }
              }
            }
          }
        }
      },
      "LetterVoidInput": {
        "type": "object",
        "required": [
          "reason"
        ],
        "additionalProperties": false,
        "properties": {
          "reason": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2000,
            "description": "Why this letter is being retired. **Required** — a void with no stated reason is a deletion wearing a status, and the letter stays on the record forever.\n"
          }
        }
      },
      "LetterPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Letter"
                }
              }
            }
          }
        ]
      },
      "Acknowledgement": {
        "description": "docs.acknowledgements — the read-and-accept receipt for a document (Immutable, version-pinned to `document_version_no`, db 10 §1.3).\n",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "document_id",
              "employee_id",
              "ack_type",
              "document_version_no",
              "acknowledged_at"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "document_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "employee_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "ack_type": {
                "$ref": "#/components/schemas/AckType"
              },
              "document_version_no": {
                "type": "integer",
                "minimum": 1
              },
              "acknowledged_at": {
                "$ref": "#/components/schemas/TimestampRef"
              },
              "evidence": {
                "type": "object",
                "additionalProperties": true,
                "description": "Capture evidence (db 10 §1.3). Server-observed `ip`, `user_agent` and `captured_at` sit at the TOP level; everything the caller supplied is quarantined under a `client` sub-object, so an auditor can always tell what the system witnessed from what the subject of the receipt wrote about themselves.\n"
              }
            }
          },
          {
            "$ref": "#/components/schemas/AppendOnlyMetaRef"
          }
        ]
      },
      "AcknowledgementCreate": {
        "type": "object",
        "required": [
          "document_id",
          "document_version_no"
        ],
        "additionalProperties": false,
        "properties": {
          "document_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "ack_type": {
            "$ref": "#/components/schemas/AckType"
          },
          "document_version_no": {
            "type": "integer",
            "minimum": 1
          },
          "evidence": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "AcknowledgementPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Acknowledgement"
                }
              }
            }
          }
        ]
      },
      "PolicyAudience": {
        "type": "object",
        "description": "docs.policies.audience — targeting rule resolving required readers (db 10 §1.3 JSONB payload shape); refs are soft, resolved by service.",
        "properties": {
          "legal_entity_ids": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          "department_ids": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          "grade_ids": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          "all_employees": {
            "type": "boolean"
          }
        }
      },
      "Policy": {
        "description": "docs.policies — a published, versioned HR policy behind a read-gate (db 10 §1.3).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "document_id",
              "policy_code",
              "title",
              "category",
              "version_no",
              "is_mandatory",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "document_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "legal_entity_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "null = tenant-wide policy."
              },
              "policy_code": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "category": {
                "$ref": "#/components/schemas/PolicyCategory"
              },
              "version_no": {
                "type": "integer",
                "minimum": 1
              },
              "is_mandatory": {
                "type": "boolean"
              },
              "audience": {
                "$ref": "#/components/schemas/PolicyAudience"
              },
              "status": {
                "$ref": "#/components/schemas/PolicyStatus"
              },
              "effective_from": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DateOnlyRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "published_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "read_status": {
                "anyOf": [
                  {
                    "type": "string",
                    "enum": [
                      "TO_READ",
                      "READ"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Derived, self-scoped only: the caller's read-gate status for the current `version_no` (DOC-S05)."
              },
              "read_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Derived, self-scoped only: WHEN the caller accepted the current `version_no`, from their own `policy_reads` receipt; null while `read_status` is `TO_READ`. Projected on the LIST as well as the detail so an ESS policies screen can render \"Read on <date>\" per row without an N+1 detail call. The tenant-wide compliance view is `docs.policy_read.list_admin`.\n"
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "PolicyDetail": {
        "description": "DOC-S06 — the policy version with a presigned body handle.",
        "allOf": [
          {
            "$ref": "#/components/schemas/Policy"
          },
          {
            "type": "object",
            "properties": {
              "file": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/FileDownloadRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Presigned download of the policy body (resolved via `document_id`)."
              }
            }
          }
        ]
      },
      "PolicyCreate": {
        "type": "object",
        "required": [
          "policy_code",
          "title",
          "category",
          "document_id"
        ],
        "additionalProperties": false,
        "properties": {
          "policy_code": {
            "type": "string",
            "minLength": 1
          },
          "title": {
            "type": "string",
            "minLength": 1
          },
          "category": {
            "$ref": "#/components/schemas/PolicyCategory"
          },
          "document_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "legal_entity_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "is_mandatory": {
            "type": "boolean"
          },
          "audience": {
            "$ref": "#/components/schemas/PolicyAudience"
          },
          "effective_from": {
            "$ref": "#/components/schemas/DateOnlyRef"
          }
        }
      },
      "PolicyUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1
          },
          "category": {
            "$ref": "#/components/schemas/PolicyCategory"
          },
          "document_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "is_mandatory": {
            "type": "boolean"
          },
          "audience": {
            "$ref": "#/components/schemas/PolicyAudience"
          },
          "effective_from": {
            "$ref": "#/components/schemas/DateOnlyRef"
          }
        }
      },
      "PolicyPublishInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "effective_from": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "note": {
            "type": "string"
          }
        }
      },
      "PolicyPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Policy"
                }
              }
            }
          }
        ]
      },
      "PolicyRead": {
        "description": "docs.policy_reads — the read-gate receipt, linked to its backing `acknowledgements` row (Immutable, version-pinned, db 10 §1.3).\n",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "policy_id",
              "employee_id",
              "policy_version_no",
              "read_at",
              "acknowledged"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "policy_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "employee_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "acknowledgement_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "policy_version_no": {
                "type": "integer",
                "minimum": 1
              },
              "read_at": {
                "$ref": "#/components/schemas/TimestampRef"
              },
              "acknowledged": {
                "type": "boolean"
              }
            }
          },
          {
            "$ref": "#/components/schemas/AppendOnlyMetaRef"
          }
        ]
      },
      "PolicyAcknowledgeInput": {
        "type": "object",
        "required": [
          "consent"
        ],
        "additionalProperties": false,
        "properties": {
          "consent": {
            "type": "boolean",
            "description": "Must be true — read-gate accept (consent-gated, enabled client-side after open/scroll)."
          },
          "evidence": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "PolicyAcknowledgeResult": {
        "type": "object",
        "readOnly": true,
        "required": [
          "acknowledgement_id",
          "policy_read_id",
          "read_at",
          "acknowledged"
        ],
        "properties": {
          "acknowledgement_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "policy_read_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "read_at": {
            "$ref": "#/components/schemas/TimestampRef"
          },
          "acknowledged": {
            "type": "boolean"
          }
        }
      },
      "PolicyReadPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PolicyRead"
                }
              }
            }
          }
        ]
      },
      "PolicyComplianceRow": {
        "type": "object",
        "readOnly": true,
        "description": "One **required reader** of a policy version. Not a receipt: `read_status` is derived from whether a version-pinned acceptance exists, so a person who has never accepted is a row here — which is the whole difference between this and `PolicyRead`.\n",
        "required": [
          "employee_id",
          "read_status"
        ],
        "properties": {
          "employee_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "employee_no": {
            "$ref": "#/components/schemas/BusinessNoRef"
          },
          "full_name": {
            "type": "string"
          },
          "department_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/UuidRef"
              },
              {
                "type": "null"
              }
            ]
          },
          "grade_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/UuidRef"
              },
              {
                "type": "null"
              }
            ]
          },
          "legal_entity_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/UuidRef"
              },
              {
                "type": "null"
              }
            ]
          },
          "read_status": {
            "type": "string",
            "enum": [
              "TO_READ",
              "READ"
            ],
            "description": "`READ` iff an acknowledged `policy_reads` row exists for the CURRENT `version_no`."
          },
          "read_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TimestampRef"
              },
              {
                "type": "null"
              }
            ]
          },
          "acknowledgement_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/UuidRef"
              },
              {
                "type": "null"
              }
            ]
          },
          "policy_read_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/UuidRef"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "PolicyComplianceSummary": {
        "description": "`docs.policy.compliance_summary` — the aggregate plus one keyset page of the required-reader roster. The three counts are computed over the WHOLE audience, never over `data`.\n",
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "required": [
              "policy_id",
              "policy_version_no",
              "required",
              "read",
              "outstanding"
            ],
            "properties": {
              "policy_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "policy_version_no": {
                "type": "integer",
                "minimum": 1,
                "description": "The version the counts and every `read_status` are pinned to."
              },
              "status": {
                "$ref": "#/components/schemas/PolicyStatus"
              },
              "is_mandatory": {
                "type": "boolean"
              },
              "required": {
                "type": "integer",
                "minimum": 0,
                "description": "Resolved audience ∩ non-terminated employees — the denominator."
              },
              "read": {
                "type": "integer",
                "minimum": 0
              },
              "outstanding": {
                "type": "integer",
                "minimum": 0,
                "description": "`required - read`; the actionable number, and what the reminder acts on."
              },
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PolicyComplianceRow"
                }
              }
            }
          }
        ]
      },
      "PolicyRemindInput": {
        "type": "object",
        "additionalProperties": false,
        "description": "Omit the body, or the field, to remind every outstanding reader.",
        "properties": {
          "employee_ids": {
            "type": "array",
            "description": "Narrows the reminder to a selection. An id that is not an outstanding reader is skipped, not refused; a malformed id is a `422`.\n",
            "items": {
              "$ref": "#/components/schemas/UuidRef"
            }
          }
        }
      },
      "PolicyRemindResult": {
        "type": "object",
        "readOnly": true,
        "required": [
          "queued",
          "policy_id",
          "policy_version_no",
          "reminders_queued"
        ],
        "properties": {
          "queued": {
            "type": "boolean",
            "description": "Always true on a 202 — the rows and their outbox events are committed; the jobs tier sends."
          },
          "policy_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "policy_version_no": {
            "type": "integer",
            "minimum": 1
          },
          "reminders_queued": {
            "type": "integer",
            "minimum": 0
          },
          "skipped_without_email": {
            "type": "integer",
            "minimum": 0,
            "description": "Outstanding readers with no `work_email` — counted rather than silently dropped."
          },
          "queued_at": {
            "$ref": "#/components/schemas/TimestampRef"
          }
        }
      },
      "TicketSlaSummary": {
        "type": "object",
        "readOnly": true,
        "description": "desk.ticket_slas — the SLA timer & escalation state, embedded on the ticket (db 10 §2.1).",
        "properties": {
          "policy_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "response_due_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TimestampRef"
              },
              {
                "type": "null"
              }
            ]
          },
          "resolution_due_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TimestampRef"
              },
              {
                "type": "null"
              }
            ]
          },
          "first_responded_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TimestampRef"
              },
              {
                "type": "null"
              }
            ]
          },
          "paused_minutes": {
            "type": "integer",
            "minimum": 0
          },
          "escalation_level": {
            "type": "integer",
            "minimum": 0
          },
          "breach_status": {
            "$ref": "#/components/schemas/SlaBreachStatus"
          },
          "last_escalated_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TimestampRef"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "Ticket": {
        "description": "desk.tickets — a tracked helpdesk request with SLA timers and a CSAT close-out (db 10 §2.1).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "ticket_no",
              "requester_id",
              "category",
              "subject",
              "priority",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "ticket_no": {
                "$ref": "#/components/schemas/BusinessNoRef"
              },
              "requester_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "legal_entity_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "category": {
                "$ref": "#/components/schemas/TicketCategory"
              },
              "subcategory": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "subject": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "priority": {
                "$ref": "#/components/schemas/TicketPriority"
              },
              "status": {
                "$ref": "#/components/schemas/TicketStatus"
              },
              "assigned_to": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "assigned_to_name": {
                "type": [
                  "string",
                  "null"
                ],
                "readOnly": true,
                "description": "Directory-safe assignee display name; null when unassigned or outside the caller visibility."
              },
              "assigned_team": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "resolution_note": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "resolved_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "closed_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "csat_requested_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "reopened_count": {
                "type": "integer",
                "minimum": 0
              },
              "converted_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "DSK-F04 — when this ticket was converted into a work task; `null` when it never was. Set is what makes a further `desk.ticket.convert_to_task` answer `409`. It is NOT a lifecycle state: `status` and the SLA timers are untouched by conversion (db 10 §2.1).\n"
              },
              "converted_by": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "DSK-F04 — who converted it (soft ref→people.employees)."
              },
              "task_ref": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/SoftRefRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "DSK-F04 — `(work.tasks, id)`, stamped once the `work` module has minted the task and reported back. **`converted_at` set with `task_ref` still `null` is the normal in-flight window**, not a failure: the mint is asynchronous on the other side of `desk.ticket.converted`. Displayed, never joined (db 00 §13).\n"
              },
              "sla": {
                "$ref": "#/components/schemas/TicketSlaSummary"
              },
              "csat_pending": {
                "type": "boolean",
                "description": "Derived: `csat_requested_at` set ∧ no `csat_responses` with `responded_at ≥ csat_requested_at` (db 10 §2.1)."
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "TicketCreate": {
        "type": "object",
        "required": [
          "category",
          "subject",
          "priority"
        ],
        "additionalProperties": false,
        "properties": {
          "category": {
            "$ref": "#/components/schemas/TicketCategory"
          },
          "subcategory": {
            "type": "string"
          },
          "subject": {
            "type": "string",
            "minLength": 1
          },
          "description": {
            "type": "string"
          },
          "priority": {
            "$ref": "#/components/schemas/TicketPriority"
          },
          "attachments": {
            "type": "array",
            "description": "Initial-message attachments — pre-uploaded object-storage keys (`XC-F07`).",
            "items": {
              "$ref": "#/components/schemas/AttachmentInput"
            }
          }
        }
      },
      "TicketAssignInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "assigned_to": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "assigned_team": {
            "type": "string"
          },
          "note": {
            "type": "string"
          }
        }
      },
      "TicketResolveInput": {
        "type": "object",
        "required": [
          "resolution_note"
        ],
        "additionalProperties": false,
        "properties": {
          "resolution_note": {
            "type": "string",
            "minLength": 1
          }
        }
      },
      "TicketConvertToTaskInput": {
        "type": "object",
        "description": "Optional routing hints carried on the `desk.ticket.converted` event. Every field is advisory: the `work` module validates them under its own tokens and may ignore or reject any of them — this module holds no authority over a `work` row and asserts none here. Absent hints, `work` applies its own defaults.\n",
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "$ref": "#/components/schemas/UuidRef",
            "description": "Suggested `work.projects` target (soft ref — never validated against a `work` table from here)."
          },
          "assignee_employee_id": {
            "$ref": "#/components/schemas/UuidRef",
            "description": "Suggested assignee (soft ref→people.employees)."
          },
          "due_date": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "title": {
            "type": "string",
            "maxLength": 200,
            "description": "Overrides the ticket subject as the task title; defaults to the ticket's own subject."
          },
          "note": {
            "type": "string",
            "description": "Conversion note",
            "recorded on the ticket thread and carried on the event.": null
          }
        }
      },
      "TicketConversionResult": {
        "type": "object",
        "description": "The outcome of `desk.ticket.convert_to_task`. It returns the **ticket**, not the task: the task is minted by the `work` module off the emitted event, so its id is not knowable inside this request.\n",
        "required": [
          "ticket",
          "converted_at"
        ],
        "properties": {
          "ticket": {
            "$ref": "#/components/schemas/Ticket",
            "description": "The ticket, unchanged in status — conversion is not a resolution and does not touch the SLA lifecycle."
          },
          "converted_at": {
            "$ref": "#/components/schemas/TimestampRef"
          },
          "emitted_event": {
            "type": "string",
            "const": "desk.ticket.converted",
            "description": "The domain event the `work` module consumes to mint the task with its origin back-reference."
          },
          "task_ref": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SoftRefRef"
              },
              {
                "type": "null"
              }
            ],
            "description": "`(work.tasks, id)` once the `work` module has minted the task and reported back. **`null` in the response that requested the conversion** — the mint is asynchronous on the other side of the event. Consumers must render the conversion as accepted-and-pending, never poll this operation for the id (re-calling it answers `409`); the task surfaces on the ticket's own read once `work` has reported.\n"
          }
        }
      },
      "TicketPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Ticket"
                }
              }
            }
          }
        ]
      },
      "TicketDashboardSummary": {
        "type": "object",
        "readOnly": true,
        "required": [
          "counts"
        ],
        "properties": {
          "counts": {
            "type": "object",
            "description": "DSK-S06 `PT-KPI` roll-up (db 10 §2.1/§2.2).",
            "properties": {
              "open": {
                "type": "integer"
              },
              "in_progress": {
                "type": "integer"
              },
              "on_hold": {
                "type": "integer"
              },
              "resolved": {
                "type": "integer"
              },
              "closed": {
                "type": "integer"
              },
              "breached": {
                "type": "integer"
              },
              "csat_avg": {
                "type": [
                  "number",
                  "null"
                ]
              }
            }
          }
        }
      },
      "AttachmentInput": {
        "type": "object",
        "description": "A pre-uploaded object-storage attachment reference (`XC-F07`) — bytes never post here.",
        "required": [
          "storage_key",
          "file_name"
        ],
        "additionalProperties": false,
        "properties": {
          "storage_key": {
            "type": "string"
          },
          "file_name": {
            "type": "string"
          },
          "mime_type": {
            "type": "string"
          },
          "size_bytes": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "TicketMessage": {
        "description": "desk.ticket_messages — a threaded post on a ticket (db 10 §2.1).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "ticket_id",
              "author_role",
              "message_type"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "ticket_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "author_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "null for system posts."
              },
              "author_role": {
                "$ref": "#/components/schemas/MessageAuthorRole"
              },
              "body": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "is_internal": {
                "type": "boolean"
              },
              "attachments": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/FileDownloadRef"
                }
              },
              "message_type": {
                "$ref": "#/components/schemas/MessageType"
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "TicketMessageCreate": {
        "type": "object",
        "description": "DSK-S03 reply — a `body` or an attachment is required.",
        "additionalProperties": false,
        "properties": {
          "body": {
            "type": "string"
          },
          "attachments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AttachmentInput"
            }
          }
        }
      },
      "TicketMessageCreateResolver": {
        "type": "object",
        "description": "DSK-S07 composer — resolver reply or internal note.",
        "additionalProperties": false,
        "properties": {
          "body": {
            "type": "string"
          },
          "is_internal": {
            "type": "boolean",
            "default": false
          },
          "message_type": {
            "$ref": "#/components/schemas/MessageType"
          },
          "attachments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AttachmentInput"
            }
          }
        }
      },
      "TicketMessagePage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TicketMessage"
                }
              }
            }
          }
        ]
      },
      "CsatResponse": {
        "description": "desk.csat_responses — the CSAT survey response captured on ticket close (db 10 §2.2).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "ticket_id",
              "rating",
              "responded_at"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "ticket_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "respondent_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "rating": {
                "type": "integer",
                "minimum": 1,
                "maximum": 5
              },
              "sentiment": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/CsatSentiment"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "comment": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "responded_at": {
                "$ref": "#/components/schemas/TimestampRef"
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "CsatResponseCreate": {
        "type": "object",
        "required": [
          "rating"
        ],
        "additionalProperties": false,
        "properties": {
          "rating": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5
          },
          "comment": {
            "type": "string"
          }
        }
      },
      "KbMediaRef": {
        "type": "object",
        "description": "desk.kb_articles.media[] item (db 10 §2.2 JSONB payload shape).",
        "required": [
          "kind"
        ],
        "additionalProperties": false,
        "properties": {
          "storage_key": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "IMAGE",
              "VIDEO",
              "FILE"
            ]
          },
          "alt": {
            "type": "string"
          }
        }
      },
      "KbArticle": {
        "description": "desk.kb_articles — a searchable help/FAQ article, localized `{en, ar}` (db 10 §2.2).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "title",
              "category",
              "visibility",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "legal_entity_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "slug": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "title": {
                "$ref": "#/components/schemas/LocalizedTextRef"
              },
              "body": {
                "$ref": "#/components/schemas/LocalizedTextRef"
              },
              "category": {
                "$ref": "#/components/schemas/KbCategory"
              },
              "tags": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "media": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/KbMediaRef"
                }
              },
              "visibility": {
                "$ref": "#/components/schemas/KbVisibility"
              },
              "status": {
                "$ref": "#/components/schemas/KbStatus"
              },
              "view_count": {
                "type": "integer",
                "minimum": 0
              },
              "helpful_count": {
                "type": "integer",
                "minimum": 0
              },
              "published_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "KbArticleCreate": {
        "type": "object",
        "required": [
          "title",
          "body",
          "category"
        ],
        "additionalProperties": false,
        "properties": {
          "slug": {
            "type": "string"
          },
          "title": {
            "$ref": "#/components/schemas/LocalizedTextRef"
          },
          "body": {
            "$ref": "#/components/schemas/LocalizedTextRef"
          },
          "category": {
            "$ref": "#/components/schemas/KbCategory"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "media": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KbMediaRef"
            }
          },
          "visibility": {
            "$ref": "#/components/schemas/KbVisibility"
          }
        }
      },
      "KbArticleUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "title": {
            "$ref": "#/components/schemas/LocalizedTextRef"
          },
          "body": {
            "$ref": "#/components/schemas/LocalizedTextRef"
          },
          "category": {
            "$ref": "#/components/schemas/KbCategory"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "media": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KbMediaRef"
            }
          },
          "visibility": {
            "$ref": "#/components/schemas/KbVisibility"
          }
        }
      },
      "KbArticleCounters": {
        "type": "object",
        "readOnly": true,
        "required": [
          "view_count",
          "helpful_count"
        ],
        "properties": {
          "view_count": {
            "type": "integer",
            "minimum": 0
          },
          "helpful_count": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "KbArticlePage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/KbArticle"
                }
              }
            }
          }
        ]
      },
      "Asset": {
        "description": "assets.assets — a company asset in the register (lite at launch, db 10 §3.1).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "asset_no",
              "category",
              "name",
              "status",
              "condition"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "asset_no": {
                "$ref": "#/components/schemas/BusinessNoRef"
              },
              "legal_entity_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "category": {
                "$ref": "#/components/schemas/AssetCategory"
              },
              "name": {
                "type": "string"
              },
              "serial_no": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "asset_tag": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "acquisition_value": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/MoneyRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "acquired_on": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DateOnlyRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "status": {
                "$ref": "#/components/schemas/AssetStatus"
              },
              "condition": {
                "$ref": "#/components/schemas/AssetCondition"
              },
              "current_holder_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "null = in stock."
              },
              "notes": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "AssetSummaryRef": {
        "type": "object",
        "readOnly": true,
        "description": "Minimal own-projection of an asset, embedded on assignment/return rows.",
        "properties": {
          "id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "asset_no": {
            "$ref": "#/components/schemas/BusinessNoRef"
          },
          "name": {
            "type": "string"
          },
          "category": {
            "$ref": "#/components/schemas/AssetCategory"
          },
          "condition": {
            "$ref": "#/components/schemas/AssetCondition"
          }
        }
      },
      "AssetCreate": {
        "type": "object",
        "required": [
          "category",
          "name"
        ],
        "additionalProperties": false,
        "properties": {
          "legal_entity_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "category": {
            "$ref": "#/components/schemas/AssetCategory"
          },
          "name": {
            "type": "string",
            "minLength": 1
          },
          "serial_no": {
            "type": "string"
          },
          "asset_tag": {
            "type": "string"
          },
          "acquisition_value": {
            "$ref": "#/components/schemas/MoneyRef"
          },
          "acquired_on": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "condition": {
            "$ref": "#/components/schemas/AssetCondition"
          },
          "notes": {
            "type": "string"
          }
        }
      },
      "AssetUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1
          },
          "serial_no": {
            "type": "string"
          },
          "asset_tag": {
            "type": "string"
          },
          "acquisition_value": {
            "$ref": "#/components/schemas/MoneyRef"
          },
          "acquired_on": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "status": {
            "$ref": "#/components/schemas/AssetStatus"
          },
          "condition": {
            "$ref": "#/components/schemas/AssetCondition"
          },
          "current_holder_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "notes": {
            "type": "string"
          }
        }
      },
      "AssetPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Asset"
                }
              }
            }
          }
        ]
      },
      "AssetAssignment": {
        "description": "assets.asset_assignments — an asset-to-employee custody handover, created at onboarding (`REC-F07`) or by HR/IT, closed by a matching return (db 10 §3.2).\n",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "asset_id",
              "employee_id",
              "assigned_at",
              "condition_out",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "asset_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "asset": {
                "$ref": "#/components/schemas/AssetSummaryRef"
              },
              "employee_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "assigned_by": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "assigned_at": {
                "$ref": "#/components/schemas/TimestampRef"
              },
              "condition_out": {
                "$ref": "#/components/schemas/AssetCondition"
              },
              "acknowledged_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "expected_return_date": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DateOnlyRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "status": {
                "$ref": "#/components/schemas/AssetAssignmentStatus"
              },
              "onboarding_task_ref": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→recruit.onboarding_tasks (REC-F07)."
              },
              "handover_notes": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "AssetAssignmentCreate": {
        "type": "object",
        "required": [
          "asset_id",
          "employee_id"
        ],
        "additionalProperties": false,
        "properties": {
          "asset_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "employee_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "condition_out": {
            "$ref": "#/components/schemas/AssetCondition"
          },
          "expected_return_date": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "handover_notes": {
            "type": "string"
          }
        }
      },
      "AssetAssignmentPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/AssetAssignment"
                }
              }
            }
          }
        ]
      },
      "AssetReturn": {
        "description": "assets.asset_returns — the custody hand-back at exit; an `ACCEPTED`/`WAIVED` return gates full-&-final in `pay` by event (db 10 §3.2).\n",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "asset_id",
              "employee_id",
              "condition_in",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "asset_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "asset": {
                "$ref": "#/components/schemas/AssetSummaryRef"
              },
              "assignment_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "employee_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "received_by": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "returned_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "condition_in": {
                "$ref": "#/components/schemas/AssetCondition"
              },
              "status": {
                "$ref": "#/components/schemas/AssetReturnStatus"
              },
              "damage_charge": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/MoneyRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "clearance_ref": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→exit.exit_clearances (EXT-F02). READ-ONLY — derived by `assets.asset_return.create` from the custodian's own open clearance case, never accepted on input. Null on an ordinary (non-exit) return."
              },
              "notes": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "AssetReturnCreate": {
        "type": "object",
        "required": [
          "assignment_id",
          "condition_in"
        ],
        "additionalProperties": false,
        "properties": {
          "assignment_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "condition_in": {
            "$ref": "#/components/schemas/AssetCondition"
          },
          "notes": {
            "type": "string"
          }
        }
      },
      "AssetReturnReceiveInput": {
        "type": "object",
        "required": [
          "condition_in"
        ],
        "additionalProperties": false,
        "properties": {
          "condition_in": {
            "$ref": "#/components/schemas/AssetCondition"
          },
          "returned_at": {
            "$ref": "#/components/schemas/TimestampRef"
          },
          "notes": {
            "type": "string"
          }
        }
      },
      "AssetReturnDisputeInput": {
        "type": "object",
        "required": [
          "damage_charge"
        ],
        "additionalProperties": false,
        "properties": {
          "damage_charge": {
            "$ref": "#/components/schemas/MoneyRef"
          },
          "notes": {
            "type": "string"
          }
        }
      },
      "AssetReturnPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/AssetReturn"
                }
              }
            }
          }
        ]
      },
      "Uuid": {
        "type": "string",
        "format": "uuid",
        "description": "UUIDv7 surrogate primary key (db-docs/00 §3). Never the business identifier."
      },
      "Timestamp": {
        "type": "string",
        "format": "date-time",
        "description": "timestamptz, serialized UTC ISO-8601. Presentation timezone is a client concern."
      },
      "DateOnly": {
        "type": "string",
        "format": "date",
        "description": "Calendar-only value (pay-period date, leave date, due date)."
      },
      "BusinessNo": {
        "type": "string",
        "description": "Tenant-unique, prefixed human reference (`employee_no`, `requisition_no`, `offer_no`, `payslip_no`, `claim_no`, `ticket_no`, `asset_no`, `case_no`). Read-model field; never a path key.\n"
      },
      "Money": {
        "type": "object",
        "description": "Exact decimal money (db-docs/00 §6). `amount` is a STRING so float never enters the wire.",
        "required": [
          "amount",
          "currency_code"
        ],
        "additionalProperties": false,
        "properties": {
          "amount": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d{1,2})?$",
            "description": "numeric(18,2) as a string, e.g. \"45000.00\"."
          },
          "currency_code": {
            "$ref": "#/components/schemas/CurrencyCode"
          }
        }
      },
      "LocalizedText": {
        "type": "object",
        "description": "Locale-keyed content map (db-docs/00 §9) for localized/white-label text (designation titles, announcement bodies, template names). Keys are the legal entity's active locale set.\n",
        "properties": {
          "en": {
            "type": "string"
          },
          "ar": {
            "type": "string"
          }
        },
        "additionalProperties": {
          "type": "string"
        }
      },
      "FileDownload": {
        "type": "object",
        "description": "Authorized file handle (db-docs/00 §14, xc.files). Bytes never transit the API — the backend mints a time-limited presigned URL after authorization. Clients never see storage keys or hold storage credentials; the presigned URL is never persisted.\n",
        "required": [
          "file_id",
          "file_name",
          "url",
          "expires_at"
        ],
        "properties": {
          "file_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "file_name": {
            "type": "string"
          },
          "mime_type": {
            "type": "string"
          },
          "size_bytes": {
            "type": "integer"
          },
          "content_hash": {
            "type": [
              "string",
              "null"
            ],
            "description": "SHA-256",
            "present where tamper-evidence matters (payslips": null,
            "letters": null,
            "e-sign artifacts).": null
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Time-limited presigned URL."
          },
          "expires_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "AuditMeta": {
        "type": "object",
        "description": "Standard mutable-entity columns (db-docs/00 §5). Read-only; present on every mutable read-model.",
        "readOnly": true,
        "properties": {
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "created_by": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              },
              {
                "type": "null"
              }
            ],
            "description": "null = system/jobs"
          },
          "updated_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "updated_by": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              },
              {
                "type": "null"
              }
            ]
          },
          "deleted_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ],
            "description": "soft-delete marker; live rows are null. Deleted rows are excluded by default scope."
          },
          "version": {
            "type": "integer",
            "description": "Optimistic-lock counter (where present); surfaces as the ETag."
          }
        }
      },
      "AppendOnlyMeta": {
        "type": "object",
        "description": "Standard append-only/immutable columns (db-docs/00 §5/§8). No update/version/delete; corrections are new compensating rows.",
        "readOnly": true,
        "properties": {
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "created_by": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "CursorPage": {
        "type": "object",
        "description": "Generic cursor-pagination envelope. List operations compose it via allOf to type `data`, e.g. `allOf: [ {$ref CursorPage}, { properties: { data: { items: {$ref Employee} } } } ]`.\n",
        "required": [
          "data",
          "page"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {}
          },
          "page": {
            "type": "object",
            "required": [
              "has_more"
            ],
            "properties": {
              "next_cursor": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "prev_cursor": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "has_more": {
                "type": "boolean"
              },
              "total_est": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Optional, capped, APPROXIMATE row estimate for grid \"X of Z\" display only — never an exact COUNT(*) on large tables (attend.attendance_records, xc.notifications, audit.*).\n"
              }
            }
          }
        }
      },
      "SoftRef": {
        "type": "object",
        "description": "Polymorphic cross-schema reference (db-docs/00 §13) — `(type → schema.table, id)`. Used by notifications, approvals inbox, audit.",
        "required": [
          "type",
          "id"
        ],
        "additionalProperties": false,
        "properties": {
          "type": {
            "type": "string",
            "description": "Target table, e.g. \"leave.leave_applications\"."
          },
          "id": {
            "$ref": "#/components/schemas/Uuid"
          }
        }
      },
      "ConfigVersionStamp": {
        "type": "object",
        "readOnly": true,
        "description": "Canonical v1 immutable-artifact envelope (db-docs/00 section 8). Version maps contain only config rows/keys actually read while resolving the artifact; empty means none were consumed.\n",
        "required": [
          "schema_version",
          "pay_structure_version",
          "compliance_pack_version",
          "statutory_config_versions",
          "tenant_config_versions"
        ],
        "properties": {
          "schema_version": {
            "type": "integer",
            "enum": [
              1
            ]
          },
          "pay_structure_version": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "compliance_pack_version": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "statutory_config_versions": {
            "type": "object",
            "additionalProperties": {
              "type": "integer",
              "minimum": 0
            }
          },
          "tenant_config_versions": {
            "type": "object",
            "additionalProperties": {
              "type": "integer",
              "minimum": 0
            }
          }
        }
      },
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem detail (application/problem+json). The platform-wide error envelope (03 §1).",
        "required": [
          "type",
          "title",
          "status"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "default": "about:blank",
            "description": "Problem-type URI."
          },
          "title": {
            "type": "string",
            "description": "Short, human-readable summary (stable per type)."
          },
          "status": {
            "type": "integer",
            "description": "HTTP status code, duplicated for convenience."
          },
          "detail": {
            "type": "string",
            "description": "Human-readable explanation specific to this occurrence."
          },
          "instance": {
            "type": "string",
            "description": "URI reference for this specific occurrence."
          },
          "code": {
            "$ref": "#/components/schemas/ErrorCode"
          },
          "correlation_id": {
            "$ref": "#/components/schemas/Uuid"
          }
        }
      },
      "ValidationProblem": {
        "description": "422 field-level validation failure; extends Problem with a per-field error array. `detail` is ALWAYS present on a 422 (#1251) and is the human summary of `errors[]`: one offending field renders as `\"<field>: <its message>\"` (`withholding_amount: is required for an India entity`), several as `\"N fields were refused: a, b, c.\"`, capped at five names. It is display copy derived from members already in the same body — clients keep branching on `code` and mapping `errors[].pointer` back to a control, never parsing this sentence.\n",
        "allOf": [
          {
            "$ref": "#/components/schemas/Problem"
          },
          {
            "type": "object",
            "required": [
              "detail",
              "errors"
            ],
            "properties": {
              "detail": {
                "type": "string",
                "description": "Human summary of `errors[]`, always populated on a 422 so a client never has to fall back to generic copy for the one status that names a fixable field.\n",
                "example": "withholding_amount: is required for an India entity"
              },
              "errors": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "pointer",
                    "rule"
                  ],
                  "properties": {
                    "pointer": {
                      "type": "string",
                      "description": "JSON Pointer to the offending field, e.g. /claim_amount"
                    },
                    "rule": {
                      "type": "string",
                      "enum": [
                        "required",
                        "format",
                        "length",
                        "range",
                        "cross-field",
                        "async-server",
                        "consent-gated",
                        "uniqueness-business",
                        "not_found"
                      ],
                      "description": "FSD validation taxonomy rule (fsd-docs/00 §8.2). `not_found` is the server-side-lookup arm: a body field that REFERENCES another resource (e.g. `project_id` on a work entry) and did not resolve for this caller. It is reported here, under the field's pointer, and NOT as a 404 — the request addresses its own resource, so the failure belongs on the form field the client can actually fix (#805).\n"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "CurrencyCode": {
        "type": "string",
        "enum": [
          "INR",
          "SAR"
        ],
        "description": "ISO-4217. A legal entity operates in a single currency (db-docs/00 §6)."
      },
      "ErrorCode": {
        "type": "string",
        "description": "Machine-stable error code (paired with the HTTP status; drives client handling, not display copy).",
        "enum": [
          "VALIDATION_FAILED",
          "IDEMPOTENCY_KEY_REUSE",
          "VERSION_CONFLICT",
          "PRECONDITION_REQUIRED",
          "MAKER_EQUALS_CHECKER",
          "STEP_UP_REQUIRED",
          "CONSENT_REQUIRED",
          "TOKEN_DENIED",
          "SCOPE_DENIED",
          "OWNERSHIP_DENIED",
          "STATE_TRANSITION_INVALID",
          "FACE_MISMATCH",
          "FACE_VERIFICATION_REQUIRED",
          "WITHHOLDING_REVIEW_REQUIRED",
          "FEATURE_NOT_IN_PLAN",
          "PLAN_LIMIT_EXCEEDED",
          "TENANT_PAST_DUE",
          "TENANT_SUSPENDED",
          "TENANT_CANCELLED",
          "RATE_LIMITED",
          "NOT_FOUND"
        ]
      }
    },
    "parameters": {
      "PathId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUIDv7 surrogate key of the target resource. Business numbers (`employee_no`, `claim_no`, …) are read-model fields, never path keys.",
        "schema": {
          "$ref": "#/components/schemas/Uuid"
        }
      },
      "PageSize": {
        "name": "page[size]",
        "in": "query",
        "required": false,
        "description": "Max items per page. Cursor pagination only (03 §2); offset pagination is rejected (ADR 0015).",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        }
      },
      "PageAfter": {
        "name": "page[after]",
        "in": "query",
        "required": false,
        "description": "Opaque forward keyset cursor (from a prior page's `page.next_cursor`).",
        "schema": {
          "type": "string"
        }
      },
      "PageBefore": {
        "name": "page[before]",
        "in": "query",
        "required": false,
        "description": "Opaque backward keyset cursor (from a prior page's `page.prev_cursor`).",
        "schema": {
          "type": "string"
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "Client-generated unique key. REQUIRED on every mutation (this round tightens ADR 0015's \"platform + retryable mutations\" floor to ALL mutations for uniformity — offline punch/leave sync depends on it). Scoped (tenant, principal, route, key); a replay within the ~24h window returns the stored response with `Idempotency-Replayed: true`; the same key with a different body → 409 IDEMPOTENCY_KEY_REUSE (04 §1).\n",
        "schema": {
          "type": "string",
          "minLength": 8,
          "maxLength": 255
        }
      },
      "IfMatch": {
        "name": "If-Match",
        "in": "header",
        "required": true,
        "description": "Optimistic-concurrency precondition for mutating a VERSIONED mutable entity (db-docs/00 §5 applies `version` where concurrent edits are likely). Value is the entity's current ETag (the row `version`). Absent → 428; stale → 412 (04 §2). N/A for append-only entities and for unversioned low-contention entities (their update ops simply omit this parameter).\n",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing, expired, or invalid session token (no authenticated principal).",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Authenticated but denied — permission token not granted, out of scope (self/team/branch), not the owner, tenant suspended, or an MC-2 operation without a fresh step-up challenge. `code` ∈ TOKEN_DENIED | SCOPE_DENIED | OWNERSHIP_DENIED | MAKER_EQUALS_CHECKER | STEP_UP_REQUIRED | CONSENT_REQUIRED | TENANT_SUSPENDED. A plan feature-flag being off is 402 FEATURE_NOT_IN_PLAN, not 403 (see PaymentRequired).\n",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource does not exist OR is masked by RLS (tenant/self/team/branch scope) — the API does not distinguish, so existence is never confirmed across a scope boundary (02 §4 disclosure posture).\n",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "Conflict": {
        "description": "Idempotency-key reuse with a different body, an invalid state transition, or a uniqueness/business-rule violation (fsd 00 §8.2). For database-backed uniqueness rules, detail names the exact violated rule; unmapped constraints are not collapsed into a generic 409.\n",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "UnprocessableEntity": {
        "description": "Field-level validation failed. The body carries both `errors[]` (per-field, pointer-addressed) and a `detail` summarising them — never an empty `detail` (#1251).\n",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ValidationProblem"
            },
            "examples": {
              "singleField": {
                "summary": "One refused field — `detail` names it",
                "value": {
                  "type": "about:blank",
                  "title": "Unprocessable Entity",
                  "status": 422,
                  "code": "VALIDATION_FAILED",
                  "detail": "withholding_amount: is required for an India entity",
                  "errors": [
                    {
                      "pointer": "/withholding_amount",
                      "rule": "required",
                      "message": "is required for an India entity"
                    }
                  ]
                }
              },
              "severalFields": {
                "summary": "Several refused fields — `detail` counts and names them",
                "value": {
                  "type": "about:blank",
                  "title": "Unprocessable Entity",
                  "status": 422,
                  "code": "VALIDATION_FAILED",
                  "detail": "2 fields were refused: effective_from, cap_amount.amount.",
                  "errors": [
                    {
                      "pointer": "/effective_from",
                      "rule": "cross-field",
                      "message": "Overlaps an existing version."
                    },
                    {
                      "pointer": "/cap_amount/amount",
                      "rule": "range",
                      "message": "Must be a non-negative decimal string."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "Locked": {
        "description": "Tenant subscription `past_due` (ADR 0009): WRITES are blocked (423), reads still succeed. `code` = TENANT_PAST_DUE. Mutations return this; list/get operations do not.\n",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Per-principal/route rate limit exceeded.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "PreconditionRequired": {
        "description": "If-Match header absent on a mutation of a versioned mutable entity (428).",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "PreconditionFailed": {
        "description": "If-Match / ETag mismatch — the row changed since it was read (412, VERSION_CONFLICT).",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "Gone": {
        "description": "Tenant cancelled/purged (ADR 0009 V1.5 lifecycle). `code` = TENANT_CANCELLED. Login and all product calls are blocked.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      }
    },
    "headers": {
      "ETag": {
        "description": "Strong validator of the row `version` (e.g. `\"v7\"`). Use as `If-Match` on the next mutation.",
        "schema": {
          "type": "string"
        }
      },
      "Location": {
        "description": "URI of the created/affected resource.",
        "schema": {
          "type": "string",
          "format": "uri-reference"
        }
      },
      "IdempotencyReplayed": {
        "description": "`true` when a stored idempotent response was replayed rather than freshly computed.",
        "schema": {
          "type": "boolean"
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait before retrying (on 429 / 503).",
        "schema": {
          "type": "integer"
        }
      }
    }
  }
}