{
  "openapi": "3.1.0",
  "info": {
    "title": "GroundIT — Recruit",
    "version": "0.1.0",
    "description": "Hire-to-onboard spine: requisitions → job openings → careers page → candidate pipeline (Kanban) → interviews & scorecards → offers & e-sign letters → pre-boarding → onboarding & provisioning. Grounded in fsd-docs/03-recruit-fsd.md, db-docs/04-recruit.md, features-docs/03-recruit-features.md. `recruit` owns the pre-employee world; Provision opens a candidate-linked guided flow through People's in-process owner seam, and `people` creates the canonical employee (PPL-F01) only when that flow completes — never a cross-schema write. Interview scorecards are append-only (frozen on submit); offers freeze their terms as a config-version stamp (`pay_structure_version`, `compliance_pack_version`) at submit time. Every CursorPage list honours the bracketed `page[size]` parameter under Express's extended parser and implements keyset continuation through `page[after]` / `page[before]`; the two cursor parameters are mutually exclusive.\n",
    "license": {
      "name": "Proprietary — GroundIT/Sysmedac internal"
    }
  },
  "servers": [
    {
      "url": "/api/v1"
    }
  ],
  "security": [
    {
      "bearerJWT": []
    }
  ],
  "tags": [
    {
      "name": "recruit",
      "description": "Hire-to-onboard module (recruit schema)."
    },
    {
      "name": "dashboard",
      "description": "Read-only recruitment ops projection (REC-S01, realizes XC-F09)."
    },
    {
      "name": "requisition",
      "description": "Headcount requisitions (REC-F01)."
    },
    {
      "name": "job_opening",
      "description": "Published fillable positions (REC-F01/REC-F02)."
    },
    {
      "name": "careers_posting",
      "description": "Channel publications of an opening (REC-F02)."
    },
    {
      "name": "careers_listing",
      "description": "Public, unauthenticated careers-page projection (REC-F02)."
    },
    {
      "name": "candidate",
      "description": "Applicant / pre-hire identity (REC-F02/F03)."
    },
    {
      "name": "candidate_inbound",
      "description": "Source-attributed mail intake for recruiter-controlled aliases (REC-F03)."
    },
    {
      "name": "candidate_pipeline",
      "description": "Kanban stage record (REC-F03)."
    },
    {
      "name": "refusal_reason",
      "description": "Tenant refusal-reason catalog (REC-F03)."
    },
    {
      "name": "interview",
      "description": "Interview rounds (REC-F04)."
    },
    {
      "name": "interview_scorecard",
      "description": "Append-only panellist feedback (REC-F04)."
    },
    {
      "name": "offer",
      "description": "Compensation offers (REC-F05)."
    },
    {
      "name": "offer_letter",
      "description": "Generated/e-signed offer letters (REC-F05/REC-F06)."
    },
    {
      "name": "preboarding",
      "description": "Accepted-offer pre-joining workflow (REC-F06)."
    },
    {
      "name": "onboarding_checklist",
      "description": "Day-one onboarding run + hire hand-off (REC-F07)."
    },
    {
      "name": "onboarding_task",
      "description": "Individual onboarding/provisioning tasks (REC-F07)."
    },
    {
      "name": "onboarding_template",
      "description": "Reusable onboarding checklist library (REC-F07)."
    }
  ],
  "paths": {
    "/recruit-dashboard": {
      "get": {
        "operationId": "recruit.dashboard.get",
        "summary": "Get the recruitment ops dashboard projection",
        "description": "Read-only projection over `recruit.requisitions`/`offers`/`candidate_pipeline`/`onboarding_checklists`/ `preboarding` — open-requisition and pending-offer counts, the candidate funnel by stage, and joiners this month. Realizes `XC-F09` (role-aware dashboard), **not** a `recruit` feature; no `recruit` table is written by this operation (fsd 03 §REC-S01, *gaps* 2). Hiring managers see a funnel scoped to their own requisitions (`XC-F04`); recruiter/HR Admin see tenant scope.\n",
        "tags": [
          "recruit",
          "dashboard"
        ],
        "x-token": "recruit.dashboard.get",
        "x-realizes-features": [
          "XC-F09"
        ],
        "x-screens": [
          "REC-S01"
        ],
        "x-touches-entities": [
          "recruit.requisitions",
          "recruit.offers",
          "recruit.candidate_pipeline",
          "recruit.onboarding_checklists",
          "recruit.preboarding"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Dashboard projection.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecruitDashboardSummary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/requisitions": {
      "get": {
        "operationId": "recruit.requisition.list",
        "summary": "List headcount requisitions",
        "description": "Requisitions board (fsd 03 §REC-S02) and the manager's \"My requisitions\" list (§REC-S18). Sort whitelist: `created_at`, `requisition_no`, `priority`, `status`.\n",
        "tags": [
          "recruit",
          "requisition"
        ],
        "x-token": "recruit.requisition.list",
        "x-realizes-features": [
          "REC-F01"
        ],
        "x-screens": [
          "REC-S02",
          "REC-S18"
        ],
        "x-touches-entities": [
          "recruit.requisitions"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "DRAFT",
                "PENDING_APPROVAL",
                "APPROVED",
                "REJECTED",
                "ON_HOLD",
                "OPEN",
                "FILLED",
                "CANCELLED",
                "CLOSED"
              ]
            }
          },
          {
            "name": "department_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "priority",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "LOW",
                "MEDIUM",
                "HIGH",
                "URGENT"
              ]
            }
          },
          {
            "name": "recruiter_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "hiring_manager_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of requisitions.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Requisition"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "recruit.requisition.create",
        "summary": "Raise a headcount requisition",
        "description": "Creates and immediately submits a `PENDING_APPROVAL` requisition in one transaction (fsd 03 §REC-S02, §REC-S18 manager raise). A distinct hiring manager or recruiter is required so four-eyes routing cannot leave a draft behind. db 04 §1 `requisitions`.",
        "tags": [
          "recruit",
          "requisition"
        ],
        "x-token": "recruit.requisition.create",
        "x-realizes-features": [
          "REC-F01"
        ],
        "x-screens": [
          "REC-S02",
          "REC-S18"
        ],
        "x-touches-entities": [
          "recruit.requisitions"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "recruit.requisition.submitted",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RequisitionCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Requisition created and routed (`status = PENDING_APPROVAL`).",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Requisition"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/requisitions/{id}": {
      "get": {
        "operationId": "recruit.requisition.get",
        "summary": "Get a requisition",
        "description": "Requisition detail panel (fsd 03 §REC-S02, §REC-S18).",
        "tags": [
          "recruit",
          "requisition"
        ],
        "x-token": "recruit.requisition.get",
        "x-realizes-features": [
          "REC-F01"
        ],
        "x-screens": [
          "REC-S02",
          "REC-S18"
        ],
        "x-touches-entities": [
          "recruit.requisitions"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Requisition.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Requisition"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "recruit.requisition.update",
        "summary": "Edit a draft requisition",
        "description": "Edits a `DRAFT` requisition's fields (fsd 03 §REC-S02). Versioned mutable entity — requires `If-Match`.",
        "tags": [
          "recruit",
          "requisition"
        ],
        "x-token": "recruit.requisition.update",
        "x-realizes-features": [
          "REC-F01"
        ],
        "x-screens": [
          "REC-S02"
        ],
        "x-touches-entities": [
          "recruit.requisitions"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RequisitionUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated requisition.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Requisition"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/requisitions/{id}/submit": {
      "post": {
        "operationId": "recruit.requisition.submit",
        "summary": "Submit a requisition for approval",
        "description": "`DRAFT → PENDING_APPROVAL`, stamps `submitted_by` (maker), routes into the unified approvals inbox (`XC-F12`) — the checker approves/rejects there, four-eyes `submitted_by <> approved_by` (fsd 03 §REC-S02/§REC-S18, db 04 §1). Emits `recruit.requisition.submitted` for the dashboard (`XC-F09`).\n",
        "tags": [
          "recruit",
          "requisition"
        ],
        "x-token": "recruit.requisition.submit",
        "x-realizes-features": [
          "REC-F01"
        ],
        "x-screens": [
          "REC-S02",
          "REC-S18"
        ],
        "x-touches-entities": [
          "recruit.requisitions"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "recruit.requisition.submitted",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Requisition submitted.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Requisition"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/requisitions/{id}/hold": {
      "post": {
        "operationId": "recruit.requisition.hold",
        "summary": "Put a requisition on hold",
        "description": "`APPROVED`/`OPEN` → `ON_HOLD` (budget freeze), fsd 03 §REC-S02.",
        "tags": [
          "recruit",
          "requisition"
        ],
        "x-token": "recruit.requisition.hold",
        "x-realizes-features": [
          "REC-F01"
        ],
        "x-screens": [
          "REC-S02"
        ],
        "x-touches-entities": [
          "recruit.requisitions"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "recruit.requisition.held",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Requisition on hold.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Requisition"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/requisitions/{id}/cancel": {
      "post": {
        "operationId": "recruit.requisition.cancel",
        "summary": "Cancel a requisition",
        "description": "Any non-terminal status → `CANCELLED` (fsd 03 §REC-S02).",
        "tags": [
          "recruit",
          "requisition"
        ],
        "x-token": "recruit.requisition.cancel",
        "x-realizes-features": [
          "REC-F01"
        ],
        "x-screens": [
          "REC-S02"
        ],
        "x-touches-entities": [
          "recruit.requisitions"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "recruit.requisition.cancelled",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Requisition cancelled.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Requisition"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/job-openings": {
      "get": {
        "operationId": "recruit.job_opening.list",
        "summary": "List job openings",
        "description": "Openings tab (fsd 03 §REC-S03). Sort whitelist: `created_at`, `published_at`, `title`.\n",
        "tags": [
          "recruit",
          "job_opening"
        ],
        "x-token": "recruit.job_opening.list",
        "x-realizes-features": [
          "REC-F01"
        ],
        "x-screens": [
          "REC-S03"
        ],
        "x-touches-entities": [
          "recruit.job_openings"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "name": "requisition_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "DRAFT",
                "OPEN",
                "ON_HOLD",
                "FILLED",
                "CLOSED",
                "CANCELLED"
              ]
            }
          },
          {
            "name": "department_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "work_location_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "work_mode",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "ONSITE",
                "HYBRID",
                "REMOTE"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of job openings.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/JobOpening"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "recruit.job_opening.create",
        "summary": "Publish a job opening from an approved requisition",
        "description": "Creates a `DRAFT` `job_openings` row against an `APPROVED`/`OPEN` requisition — the \"Convert to opening(s)\" action on the requisition detail (fsd 03 §REC-S02) hands off into this same create flow, which is also the \"+ Publish opening\" modal on §REC-S03. One requisition of `headcount > 1` may produce several openings (db 04 §1).\n",
        "tags": [
          "recruit",
          "job_opening"
        ],
        "x-token": "recruit.job_opening.create",
        "x-realizes-features": [
          "REC-F01"
        ],
        "x-screens": [
          "REC-S02",
          "REC-S03"
        ],
        "x-touches-entities": [
          "recruit.job_openings",
          "recruit.requisitions"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JobOpeningCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Job opening created (`status = 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/JobOpening"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/job-openings/{id}": {
      "get": {
        "operationId": "recruit.job_opening.get",
        "summary": "Get a job opening",
        "description": "Opening detail (fsd 03 §REC-S03).",
        "tags": [
          "recruit",
          "job_opening"
        ],
        "x-token": "recruit.job_opening.get",
        "x-realizes-features": [
          "REC-F01"
        ],
        "x-screens": [
          "REC-S03"
        ],
        "x-touches-entities": [
          "recruit.job_openings"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Job opening.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobOpening"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "recruit.job_opening.update",
        "summary": "Edit a job opening",
        "description": "Edits title/description/slug/work_mode/openings_count/is_internal/closes_at (fsd 03 §REC-S03). Versioned — requires `If-Match`.",
        "tags": [
          "recruit",
          "job_opening"
        ],
        "x-token": "recruit.job_opening.update",
        "x-realizes-features": [
          "REC-F01"
        ],
        "x-screens": [
          "REC-S03"
        ],
        "x-touches-entities": [
          "recruit.job_openings"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JobOpeningUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated job opening.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobOpening"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/job-openings/{id}/publish": {
      "post": {
        "operationId": "recruit.job_opening.publish",
        "summary": "Publish an opening",
        "description": "`DRAFT → OPEN`, stamps `published_at`; only while the parent requisition is `APPROVED`/`OPEN` (fsd 03 §REC-S03, db 04 §1).",
        "tags": [
          "recruit",
          "job_opening"
        ],
        "x-token": "recruit.job_opening.publish",
        "x-realizes-features": [
          "REC-F01",
          "REC-F02"
        ],
        "x-screens": [
          "REC-S03"
        ],
        "x-touches-entities": [
          "recruit.job_openings"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Opening published.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobOpening"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/job-openings/{id}/hold": {
      "post": {
        "operationId": "recruit.job_opening.hold",
        "summary": "Put an opening on hold",
        "description": "`OPEN → ON_HOLD` (fsd 03 §REC-S03).",
        "tags": [
          "recruit",
          "job_opening"
        ],
        "x-token": "recruit.job_opening.hold",
        "x-realizes-features": [
          "REC-F01"
        ],
        "x-screens": [
          "REC-S03"
        ],
        "x-touches-entities": [
          "recruit.job_openings"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Opening on hold.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobOpening"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/job-openings/{id}/close": {
      "post": {
        "operationId": "recruit.job_opening.close",
        "summary": "Close an opening",
        "description": "`→ CLOSED`; closing the last open position on a requisition moves it toward `FILLED` (service logic, same transaction) (fsd 03 §REC-S03).",
        "tags": [
          "recruit",
          "job_opening"
        ],
        "x-token": "recruit.job_opening.close",
        "x-realizes-features": [
          "REC-F01"
        ],
        "x-screens": [
          "REC-S03"
        ],
        "x-touches-entities": [
          "recruit.job_openings",
          "recruit.requisitions"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Opening closed.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobOpening"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/job-openings/{id}/careers-postings": {
      "post": {
        "operationId": "recruit.careers_posting.create",
        "summary": "Publish an opening to a channel",
        "description": "Creates a `careers_postings` row for the opening. `channel = CAREERS_PAGE` is the AUTOMATIC path: GroundIT publishes it, so it auto-publishes immediately (`status = PUBLISHED`, `published_at` stamped, `content_snapshot` frozen at publish so a later opening edit never silently rewrites a live post) and it REFUSES `external_url`/`external_ref`/`published_at` — those belong to the publisher, not the caller. Every other channel (`LINKEDIN`/`INDEED`/`NAUKRI`/`BAYT`/`OTHER_BOARD`) records a posting the recruiter made BY HAND (owner decision 2026-08-30, #1495): `external_url` is required, `external_ref` optionally carries the board's own id — or, for `OTHER_BOARD`, the board's NAME — and `published_at` may be backdated (never future-dated) because the record is always made after the fact. There is no outbound job-board integration and none is planned; these rows are tracking, not syndication. One live posting per `(opening, channel)` (`careers_postings_opening_channel_key`) — a second answers `409`. Posting content pack-varies (`XC-F01`).\n",
        "tags": [
          "recruit",
          "careers_posting"
        ],
        "x-token": "recruit.careers_posting.create",
        "x-realizes-features": [
          "REC-F02"
        ],
        "x-screens": [
          "REC-S03"
        ],
        "x-touches-entities": [
          "recruit.careers_postings",
          "recruit.job_openings"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CareersPostingCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Posting created (and published, for `CAREERS_PAGE`).",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CareersPosting"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/careers-postings": {
      "get": {
        "operationId": "recruit.careers_posting.list",
        "summary": "List channel postings",
        "description": "Channels tab (fsd 03 §REC-S03). Sort whitelist `published_at`, `created_at`.",
        "tags": [
          "recruit",
          "careers_posting"
        ],
        "x-token": "recruit.careers_posting.list",
        "x-realizes-features": [
          "REC-F02"
        ],
        "x-screens": [
          "REC-S03"
        ],
        "x-touches-entities": [
          "recruit.careers_postings"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "name": "job_opening_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "channel",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "CAREERS_PAGE",
                "LINKEDIN",
                "INDEED",
                "NAUKRI",
                "BAYT",
                "OTHER_BOARD"
              ]
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "DRAFT",
                "PUBLISHED",
                "SYNDICATION_PENDING",
                "UNPUBLISHED",
                "EXPIRED",
                "FAILED"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of postings.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/CareersPosting"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/careers-postings/{id}": {
      "patch": {
        "operationId": "recruit.careers_posting.update",
        "summary": "Correct a manual posting's link, reference or date",
        "description": "Fixes a hand-recorded external posting in place (#1495) — a mistyped board URL is a correction of the record, not a lifecycle event, and used to require unpublishing the row and adding another. Applies to external channels ONLY: `CAREERS_PAGE` answers `422`, since GroundIT publishes that one and owns its link and date. Not status-gated — an `UNPUBLISHED` or `EXPIRED` row is still a record of something that happened; `POST /careers-postings/{id}/unpublish` remains the only operation that moves the status.\n",
        "tags": [
          "recruit",
          "careers_posting"
        ],
        "x-token": "recruit.careers_posting.update",
        "x-realizes-features": [
          "REC-F02"
        ],
        "x-screens": [
          "REC-S03"
        ],
        "x-touches-entities": [
          "recruit.careers_postings"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CareersPostingUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Posting corrected.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CareersPosting"
                }
              }
            }
          },
          "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"
          }
        }
      },
      "get": {
        "operationId": "recruit.careers_posting.get",
        "summary": "Get a channel posting",
        "tags": [
          "recruit",
          "careers_posting"
        ],
        "x-token": "recruit.careers_posting.get",
        "x-realizes-features": [
          "REC-F02"
        ],
        "x-screens": [
          "REC-S03"
        ],
        "x-touches-entities": [
          "recruit.careers_postings"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Posting.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CareersPosting"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/careers-postings/{id}/unpublish": {
      "post": {
        "operationId": "recruit.careers_posting.unpublish",
        "summary": "Take a posting down",
        "description": "`PUBLISHED → UNPUBLISHED` (fsd 03 §REC-S03).",
        "tags": [
          "recruit",
          "careers_posting"
        ],
        "x-token": "recruit.careers_posting.unpublish",
        "x-realizes-features": [
          "REC-F02"
        ],
        "x-screens": [
          "REC-S03"
        ],
        "x-touches-entities": [
          "recruit.careers_postings"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Posting unpublished.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CareersPosting"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/careers-listings": {
      "get": {
        "operationId": "recruit.careers_listing.list",
        "summary": "Browse the public careers listing (unauthenticated)",
        "description": "The tenant's branded public careers page (fsd 03 §REC-S04). Principal: **unauthenticated public visitor** (no session token). Renders only `PUBLISHED`, non-`is_internal` openings from the `CAREERS_PAGE` posting's frozen `content_snapshot`. Sort whitelist: `published_at`.\n",
        "tags": [
          "recruit",
          "careers_listing"
        ],
        "x-token": "recruit.careers_listing.list",
        "x-realizes-features": [
          "REC-F02"
        ],
        "x-screens": [
          "REC-S04"
        ],
        "x-touches-entities": [
          "recruit.job_openings",
          "recruit.careers_postings"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          },
          {
            "name": "q",
            "in": "query",
            "description": "Keyword match against title/description.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "department_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "work_location_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "work_mode",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "ONSITE",
                "HYBRID",
                "REMOTE"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of public listings.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/CareersListing"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/careers-listings/{id}": {
      "get": {
        "operationId": "recruit.careers_listing.get",
        "summary": "Get a public job listing (unauthenticated)",
        "description": "Public opening detail (fsd 03 §REC-S05). Principal — unauthenticated public visitor.",
        "tags": [
          "recruit",
          "careers_listing"
        ],
        "x-token": "recruit.careers_listing.get",
        "x-realizes-features": [
          "REC-F02"
        ],
        "x-screens": [
          "REC-S05"
        ],
        "x-touches-entities": [
          "recruit.job_openings",
          "recruit.careers_postings"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Public listing detail.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CareersListing"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/careers-listings/{id}/applications": {
      "post": {
        "operationId": "recruit.candidate.apply",
        "summary": "Submit a job application (unauthenticated)",
        "description": "Creates a `candidates` row attributed to the posting, increments `careers_postings.apply_count`, provisions a pre-hire applicant identity (`applicant_user_id → xc.identities`, `XC-F03`), and opens a `candidate_pipeline` card at `stage = SOURCED` (fsd 03 §REC-S05, db 04 §3). Principal: **unauthenticated public applicant** submitting the form; identity is minted server-side on success. Résumé bytes are never posted here — the client uploads to a presigned URL first (`XC-F07`) and references the resulting `resume_storage_key`/`resume_content_hash`.\n",
        "tags": [
          "recruit",
          "candidate"
        ],
        "x-token": "recruit.candidate.apply",
        "x-realizes-features": [
          "REC-F02",
          "REC-F03"
        ],
        "x-screens": [
          "REC-S05"
        ],
        "x-touches-entities": [
          "recruit.candidates",
          "recruit.candidate_pipeline",
          "recruit.careers_postings"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CandidateApplicationRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Application received.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CandidateApplicationResult"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/candidate-inbound-intakes": {
      "post": {
        "operationId": "recruit.candidate.inbound_receive",
        "summary": "Receive an application from a source-specific mail alias",
        "description": "Authenticated mail-adapter door for `jobs+linkedin@…`, `jobs+naukri@…`, `jobs+job-board@…`, `jobs+agency@…`, and `jobs+direct@…`. The fixed job-platform registry matches the envelope sender and extracts the real candidate identity from the subject/body. A recognized platform sender is transport metadata only and is never stored as the candidate email. The source alias contributes application-grain UTM attribution on `candidate_pipeline`; raw subject/body are parsed in memory and not retained. `Idempotency-Key` must be the upstream mail-provider message id.\n",
        "tags": [
          "recruit",
          "candidate_inbound"
        ],
        "x-token": "recruit.candidate.inbound_receive",
        "x-realizes-features": [
          "REC-F03"
        ],
        "x-screens": [
          "REC-S06"
        ],
        "x-touches-entities": [
          "recruit.candidates",
          "recruit.candidate_pipeline"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "recruit.candidate.stage_changed",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CandidateInboundIntakeRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Candidate created or re-sourced, with a source-attributed `SOURCED` application card.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Candidate"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/candidates": {
      "post": {
        "operationId": "recruit.candidate.create",
        "summary": "Add a candidate (internal sourcing door)",
        "description": "The recruiter-side create door — sourcing a candidate directly (`DIRECT`/`REFERRAL`/`AGENCY`/ `WALK_IN`/`INTERNAL`) without the public careers page. Creates the `candidates` row and, when `job_opening_id` is given, its `SOURCED` pipeline card (db 04 §3 grain rule — the card is the application record; the identity cluster is the person). Re-sourcing a person who already exists (matching normalized email, phone, or profile URL) reuses the cluster's canonical candidate and opens a new card. **Contract addition 2026-08-04 (#202):** the corpus modelled only the public `recruit.candidate.apply` door, which defers with the public careers site (REC-S04/S05) — an internal ATS cannot source candidates without this operation.\n",
        "tags": [
          "recruit",
          "candidate"
        ],
        "x-token": "recruit.candidate.create",
        "x-realizes-features": [
          "REC-F03"
        ],
        "x-screens": [
          "REC-S06",
          "REC-S07"
        ],
        "x-touches-entities": [
          "recruit.candidates",
          "recruit.candidate_pipeline"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CandidateCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Candidate created (with its `SOURCED` pipeline card when an opening was given).",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Candidate"
                }
              }
            }
          },
          "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"
          }
        }
      },
      "get": {
        "operationId": "recruit.candidate.list",
        "summary": "List candidates",
        "description": "Candidate search backing the pipeline board and profile lookups (fsd 03 §REC-S06/§REC-S07). Sort whitelist: `created_at`, `full_name`.\n",
        "tags": [
          "recruit",
          "candidate"
        ],
        "x-token": "recruit.candidate.list",
        "x-realizes-features": [
          "REC-F03"
        ],
        "x-screens": [
          "REC-S06",
          "REC-S07"
        ],
        "x-touches-entities": [
          "recruit.candidates"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "name": "q",
            "in": "query",
            "description": "Name/email match.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "source",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "CAREERS_PAGE",
                "REFERRAL",
                "JOB_BOARD",
                "AGENCY",
                "DIRECT",
                "WALK_IN",
                "INTERNAL"
              ]
            }
          },
          {
            "name": "job_opening_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of candidates.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Candidate"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/candidates/{id}": {
      "get": {
        "operationId": "recruit.candidate.get",
        "summary": "Get a candidate profile",
        "description": "Candidate 360 header (fsd 03 §REC-S07).",
        "tags": [
          "recruit",
          "candidate"
        ],
        "x-token": "recruit.candidate.get",
        "x-realizes-features": [
          "REC-F03"
        ],
        "x-screens": [
          "REC-S07"
        ],
        "x-touches-entities": [
          "recruit.candidates"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Candidate.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Candidate"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/refusal-reasons": {
      "get": {
        "operationId": "recruit.refusal_reason.list",
        "summary": "List refusal reasons",
        "description": "Active/inactive tenant catalog ordered by `sequence`, then code (fsd 03 §REC-S06; db 04 §3).",
        "tags": [
          "recruit",
          "refusal_reason"
        ],
        "x-token": "recruit.refusal_reason.list",
        "x-realizes-features": [
          "REC-F03"
        ],
        "x-screens": [
          "REC-S06"
        ],
        "x-touches-entities": [
          "recruit.refusal_reasons"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "name": "is_active",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Refusal-reason page.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/RefusalReason"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "recruit.refusal_reason.create",
        "summary": "Create a refusal reason",
        "description": "Creates a translated, sequenced reason optionally bound to a published email template.",
        "tags": [
          "recruit",
          "refusal_reason"
        ],
        "x-token": "recruit.refusal_reason.create",
        "x-realizes-features": [
          "REC-F03"
        ],
        "x-screens": [
          "REC-S06"
        ],
        "x-touches-entities": [
          "recruit.refusal_reasons",
          "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": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefusalReasonCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Reason 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/RefusalReason"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/refusal-reasons/{id}": {
      "patch": {
        "operationId": "recruit.refusal_reason.update",
        "summary": "Update or retire a refusal reason",
        "description": "Updates labels/order/template/active state; the stable code and historical snapshots do not change.",
        "tags": [
          "recruit",
          "refusal_reason"
        ],
        "x-token": "recruit.refusal_reason.update",
        "x-realizes-features": [
          "REC-F03"
        ],
        "x-screens": [
          "REC-S06"
        ],
        "x-touches-entities": [
          "recruit.refusal_reasons",
          "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": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefusalReasonUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reason updated.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RefusalReason"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/candidate-pipeline-cards": {
      "get": {
        "operationId": "recruit.candidate_pipeline.list",
        "summary": "List Kanban pipeline cards",
        "description": "The Kanban board — grouped by `stage`, ordered by `rank` (fsd 03 §REC-S06). Sort whitelist: `rank`, `stage_entered_at`, `created_at`.\n",
        "tags": [
          "recruit",
          "candidate_pipeline"
        ],
        "x-token": "recruit.candidate_pipeline.list",
        "x-realizes-features": [
          "REC-F03"
        ],
        "x-screens": [
          "REC-S06"
        ],
        "x-touches-entities": [
          "recruit.candidate_pipeline",
          "recruit.candidates"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "name": "job_opening_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "stage",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "SOURCED",
                "SCREENED",
                "INTERVIEW",
                "OFFER",
                "HIRED",
                "REJECTED"
              ]
            }
          },
          {
            "name": "assigned_recruiter_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "is_rejected",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of pipeline cards.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/CandidatePipelineCard"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/candidate-pipeline-cards/refusal-preview": {
      "post": {
        "operationId": "recruit.candidate_pipeline.refusal_preview",
        "summary": "Render a live single-applicant refusal-mail preview",
        "description": "Resolves the reason's active template and server-renders the selected applicant in locale; no mail is queued.",
        "tags": [
          "recruit",
          "candidate_pipeline"
        ],
        "x-token": "recruit.candidate_pipeline.refusal_preview",
        "x-realizes-features": [
          "REC-F03"
        ],
        "x-screens": [
          "REC-S06"
        ],
        "x-touches-entities": [
          "recruit.candidate_pipeline",
          "recruit.candidates",
          "recruit.refusal_reasons",
          "org.templates"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefusalPreviewRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Preview availability and rendered body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RefusalPreview"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/candidate-pipeline-cards/refuse": {
      "post": {
        "operationId": "recruit.candidate_pipeline.refuse",
        "summary": "Atomically refuse selected applications and optional detected duplicates",
        "description": "Refuses 1–100 versioned cards and, when requested, every ongoing card in their identity clusters. Hired/already-refused duplicates are excluded. Mail requires an active template and an email on every affected applicant; otherwise no card changes. Each cascade activity links to its initiating card.\n",
        "tags": [
          "recruit",
          "candidate_pipeline"
        ],
        "x-token": "recruit.candidate_pipeline.refuse",
        "x-realizes-features": [
          "REC-F03"
        ],
        "x-screens": [
          "REC-S06"
        ],
        "x-touches-entities": [
          "recruit.candidate_pipeline",
          "recruit.candidate_activity",
          "recruit.refusal_reasons",
          "org.templates"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "event-driven",
        "x-emits-event": "recruit.candidate.stage_changed",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CandidateRefuseRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Atomic refusal result.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CandidateRefuseResult"
                }
              }
            }
          },
          "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"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/candidate-pipeline-cards/{id}": {
      "get": {
        "operationId": "recruit.candidate_pipeline.get",
        "summary": "Get a pipeline card",
        "tags": [
          "recruit",
          "candidate_pipeline"
        ],
        "x-token": "recruit.candidate_pipeline.get",
        "x-realizes-features": [
          "REC-F03"
        ],
        "x-screens": [
          "REC-S06",
          "REC-S07"
        ],
        "x-touches-entities": [
          "recruit.candidate_pipeline"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Pipeline card.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CandidatePipelineCard"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "recruit.candidate_pipeline.update",
        "summary": "Edit a pipeline card's notes / owner",
        "description": "\"Save note\" and reassignment (fsd 03 §REC-S07): `notes`, `assigned_recruiter_id`. Versioned — requires `If-Match`.",
        "tags": [
          "recruit",
          "candidate_pipeline"
        ],
        "x-token": "recruit.candidate_pipeline.update",
        "x-realizes-features": [
          "REC-F03"
        ],
        "x-screens": [
          "REC-S07"
        ],
        "x-touches-entities": [
          "recruit.candidate_pipeline"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CandidatePipelineUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated pipeline card.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CandidatePipelineCard"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/candidate-pipeline-cards/{id}/activity": {
      "get": {
        "operationId": "recruit.candidate_activity.list",
        "summary": "Read the append-only application activity trail",
        "description": "Includes cascade origin links and queued-mail evidence; payloads never contain applicant contact or rendered mail.",
        "tags": [
          "recruit",
          "candidate_pipeline"
        ],
        "x-token": "recruit.candidate_activity.list",
        "x-realizes-features": [
          "REC-F03"
        ],
        "x-screens": [
          "REC-S07"
        ],
        "x-touches-entities": [
          "recruit.candidate_activity"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": true,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Activity trail.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CandidateActivity"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/candidate-pipeline-cards/{id}/move-stage": {
      "post": {
        "operationId": "recruit.candidate_pipeline.move_stage",
        "summary": "Move a card to another Kanban stage",
        "description": "Drag-and-drop stage move — sets `stage` (+ `previous_stage`, `stage_entered_at`, resets `days_in_stage`) and optionally `rank` (fsd 03 §REC-S06). Emits `recruit.candidate.stage_changed` for the dashboard (`XC-F09`) and search (`XC-F13`).\n\n**A move into the terminal `HIRED` lane also starts guided onboarding, in the SAME transaction** (issue #634). It resolves the hand-off facts from the card (opening → requisition for the legal entity; the ACCEPTED offer, else the onboarding checklist, for the joining date; the HR-typed `recruit.preboarding.work_email` only, never `recruit.candidates.email`), opens **or resumes** the one candidate-linked `people.onboarding_flows` row through People's in-process seam — never a cross-schema write, and a card whose checklist was already worked through `recruit.onboarding_checklist.complete`, or moved back one lane and forward again, links the existing flow rather than opening a second — and emits a **second** event, `recruit.candidate.hired`, carrying `{ card_id, candidate_id, onboarding_flow_id, onboarding_flow_created, onboarding_skipped_reason? }`. Either the card is `HIRED` and the flow exists, or neither happened. **Honest absence:** `people.onboarding_flows.legal_entity_id` is NOT NULL and is reachable only through the card's opening → requisition, so a talent-pool card with no opening opens **no** flow — the move still succeeds and the event still fires, with `onboarding_flow_id: null` and `onboarding_skipped_reason: 'NO_LEGAL_ENTITY'`. Choosing a legal entity on the tenant's behalf would be a payroll/statutory error. `x-emits-event` is a scalar by corpus convention (`00-api-overview-and-conventions.md` §4), so it names the unconditional event only; the conditional second event is documented here and catalogued in `asyncapi/domain-events.asyncapi.yaml`.\n\n**Since issue #800 the same transaction also opens the day-one RUN and can COMPLETE the hire.** Two further halves, each refusing independently and neither able to fail the move. ① It seeds `recruit.onboarding_checklists` and its `recruit.onboarding_tasks` from the matched template, through the body of `recruit.onboarding_checklist.create` itself rather than a second implementation, so both doors produce identical rows and a replay resumes the existing run. It declines — where the HR door still creates on request — with `checklist_skipped_reason` `NO_JOINING_DATE` (every task's `due_date` is `joining_date + offset_days`; `recruit.onboarding_checklist.complete` refuses without the date, no PATCH can add it later, and the dead row would `409` the create door) or `NO_TEMPLATE` (nothing to seed, so the run would carry zero tasks). ② When the flow's placement AND compensation prefill are both complete — which happens only when an ACCEPTED offer supplied the joining date, the CTC and the BASIC split — People completes its own flow here, minting `people.employees` (+ its satellites), `pay.employee_compensation`, the `xc.identities` ESS principal and the tenant's `SELF`-scoped baseline `admin.member_grants` role, each through the owning module's own in-process kernel. Anything less leaves the flow open with `hire_skipped_reason` ∈ `{INCOMPLETE_PREFILL, FLOW_NOT_RESUMABLE, ALREADY_HIRED, PLAN_LIMIT_EXCEEDED}`. **This operation therefore does not declare `402`, and that is deliberate:** at `maxEmployees` the completion records `PLAN_LIMIT_EXCEEDED` and leaves the flow open rather than raising the `402` `people.onboarding.complete` raises, because a payment refusal inside this transaction would abort a legitimate ATS move, and a live flow consumes no seat — the flow is the queue. The `recruit.candidate.hired` payload gains nine keys for all of this: `checklist_id`, `checklist_created`, `checklist_skipped_reason?`, `employee_id`, `employee_created`, `hire_skipped_reason?`, `ess_skipped_reason?`, `ess_role_granted`, `ess_role_skipped_reason?`. A completed hire also writes `people.employee.activated` and `people.employee.ess_account_provisioned` to the outbox, from the owning modules' own kernels.\n",
        "tags": [
          "recruit",
          "candidate_pipeline"
        ],
        "x-token": "recruit.candidate_pipeline.move_stage",
        "x-realizes-features": [
          "REC-F03"
        ],
        "x-screens": [
          "REC-S06"
        ],
        "x-touches-entities": [
          "recruit.candidate_pipeline",
          "people.onboarding_flows",
          "recruit.onboarding_checklists",
          "recruit.onboarding_tasks",
          "people.employees",
          "people.employee_profiles",
          "people.personal_info",
          "people.contacts",
          "pay.employee_compensation",
          "xc.identities",
          "admin.member_grants"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "recruit.candidate.stage_changed",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CandidatePipelineMoveStageRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Card moved.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CandidatePipelineCard"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/candidate-pipeline-cards/{id}/reorder": {
      "post": {
        "operationId": "recruit.candidate_pipeline.reorder",
        "summary": "Reorder a card within its stage column",
        "description": "Drag-to-reorder sets a fractional `rank` between neighbours, no full re-sequencing (fsd 03 §REC-S06, db 04 §3).",
        "tags": [
          "recruit",
          "candidate_pipeline"
        ],
        "x-token": "recruit.candidate_pipeline.reorder",
        "x-realizes-features": [
          "REC-F03"
        ],
        "x-screens": [
          "REC-S06"
        ],
        "x-touches-entities": [
          "recruit.candidate_pipeline"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CandidatePipelineReorderRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Card reordered.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CandidatePipelineCard"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/candidate-pipeline-cards/{id}/reject": {
      "post": {
        "operationId": "recruit.candidate_pipeline.reject",
        "summary": "Reject a candidate to the archive lane",
        "description": "`stage → REJECTED`, `is_rejected = true`; reason required, note required when `rejection_reason = OTHER` (fsd 03 §REC-S06, db 04 §3 check constraint). Retained for the talent pool, not deleted. Emits `recruit.candidate.stage_changed`.\n",
        "tags": [
          "recruit",
          "candidate_pipeline"
        ],
        "x-token": "recruit.candidate_pipeline.reject",
        "x-realizes-features": [
          "REC-F03"
        ],
        "x-screens": [
          "REC-S06"
        ],
        "x-touches-entities": [
          "recruit.candidate_pipeline"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "recruit.candidate.stage_changed",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CandidatePipelineRejectRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Card rejected.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CandidatePipelineCard"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/candidates/{id}/interviews": {
      "post": {
        "operationId": "recruit.interview.create",
        "summary": "Schedule an interview round",
        "description": "Creates a `SCHEDULED` interview round for the candidate — panel, slot, mode (fsd 03 §REC-S07, db 04 §4). Invites/reminders dispatched via `XC-F05`.\n",
        "tags": [
          "recruit",
          "interview"
        ],
        "x-token": "recruit.interview.create",
        "x-realizes-features": [
          "REC-F04"
        ],
        "x-screens": [
          "REC-S07"
        ],
        "x-touches-entities": [
          "recruit.interviews",
          "recruit.candidates"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InterviewCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Interview scheduled.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Interview"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/interviews": {
      "get": {
        "operationId": "recruit.interview.list",
        "summary": "List interview rounds",
        "description": "Round timeline (fsd 03 §REC-S07). Sort whitelist `scheduled_start_at`, `round_no`.",
        "tags": [
          "recruit",
          "interview"
        ],
        "x-token": "recruit.interview.list",
        "x-realizes-features": [
          "REC-F04"
        ],
        "x-screens": [
          "REC-S07"
        ],
        "x-touches-entities": [
          "recruit.interviews"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "name": "candidate_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "job_opening_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "SCHEDULED",
                "RESCHEDULED",
                "IN_PROGRESS",
                "COMPLETED",
                "NO_SHOW",
                "CANCELLED"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of interviews.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Interview"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/interviews/{id}": {
      "get": {
        "operationId": "recruit.interview.get",
        "summary": "Get an interview round",
        "tags": [
          "recruit",
          "interview"
        ],
        "x-token": "recruit.interview.get",
        "x-realizes-features": [
          "REC-F04"
        ],
        "x-screens": [
          "REC-S07"
        ],
        "x-touches-entities": [
          "recruit.interviews"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Interview.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Interview"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/interviews/{id}/reschedule": {
      "post": {
        "operationId": "recruit.interview.reschedule",
        "summary": "Reschedule an interview round",
        "description": "`→ RESCHEDULED` with a new slot/mode/location/link; slot conflicts are checked at write time against panellist calendars (service logic, not a DB constraint) (fsd 03 §REC-S07).",
        "tags": [
          "recruit",
          "interview"
        ],
        "x-token": "recruit.interview.reschedule",
        "x-realizes-features": [
          "REC-F04"
        ],
        "x-screens": [
          "REC-S07"
        ],
        "x-touches-entities": [
          "recruit.interviews"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InterviewRescheduleRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Interview rescheduled.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Interview"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/interviews/{id}/cancel": {
      "post": {
        "operationId": "recruit.interview.cancel",
        "summary": "Cancel an interview round",
        "tags": [
          "recruit",
          "interview"
        ],
        "x-token": "recruit.interview.cancel",
        "x-realizes-features": [
          "REC-F04"
        ],
        "x-screens": [
          "REC-S07"
        ],
        "x-touches-entities": [
          "recruit.interviews"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Interview cancelled.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Interview"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/interviews/{id}/scorecards": {
      "post": {
        "operationId": "recruit.interview_scorecard.create",
        "summary": "Submit an interview scorecard",
        "description": "**Append-only insert** — one card per panellist per round, frozen on submit (`submitted_at`); no edit/delete (`BEFORE UPDATE OR DELETE` trigger, db 04 §4/db-docs 00 §8/§12). Web (fsd 03 §REC-S08) and mobile (§REC-S17) both post here; principal is the **panellist** on `interviews.panel[].employee_id` (`XC-F04` panel-scoped). Rolls up to `interviews.overall_recommendation`, advancing the pipeline (`REC-S06`).\n",
        "tags": [
          "recruit",
          "interview_scorecard"
        ],
        "x-token": "recruit.interview_scorecard.create",
        "x-realizes-features": [
          "REC-F04"
        ],
        "x-screens": [
          "REC-S08",
          "REC-S17"
        ],
        "x-touches-entities": [
          "recruit.interview_scorecards",
          "recruit.interviews"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": true,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InterviewScorecardCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Scorecard submitted (immutable).",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InterviewScorecard"
                }
              }
            }
          },
          "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"
          }
        }
      },
      "get": {
        "operationId": "recruit.interview_scorecard.list",
        "summary": "List submitted scorecards for a round",
        "description": "Feeds the candidate 360 page's scorecard summary (fsd 03 §REC-S07/§REC-S08).",
        "tags": [
          "recruit",
          "interview_scorecard"
        ],
        "x-token": "recruit.interview_scorecard.list",
        "x-realizes-features": [
          "REC-F04"
        ],
        "x-screens": [
          "REC-S07",
          "REC-S08"
        ],
        "x-touches-entities": [
          "recruit.interview_scorecards"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": true,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Page of scorecards.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/InterviewScorecard"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/interview-scorecards/{id}": {
      "get": {
        "operationId": "recruit.interview_scorecard.get",
        "summary": "Get a submitted scorecard",
        "tags": [
          "recruit",
          "interview_scorecard"
        ],
        "x-token": "recruit.interview_scorecard.get",
        "x-realizes-features": [
          "REC-F04"
        ],
        "x-screens": [
          "REC-S08"
        ],
        "x-touches-entities": [
          "recruit.interview_scorecards"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": true,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Scorecard.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InterviewScorecard"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/offers": {
      "get": {
        "operationId": "recruit.offer.list",
        "summary": "List offers",
        "description": "Offers grid landing (fsd 03 §REC-S09). Sort whitelist `created_at`, `valid_until`, `status`.",
        "tags": [
          "recruit",
          "offer"
        ],
        "x-token": "recruit.offer.list",
        "x-realizes-features": [
          "REC-F05"
        ],
        "x-screens": [
          "REC-S09"
        ],
        "x-touches-entities": [
          "recruit.offers"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "name": "candidate_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "job_opening_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "DRAFT",
                "PENDING_APPROVAL",
                "APPROVED",
                "REJECTED",
                "SENT",
                "ACCEPTED",
                "DECLINED",
                "REVOKED",
                "EXPIRED"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of offers.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Offer"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "recruit.offer.create",
        "summary": "Build a compensation offer",
        "description": "Saves a `DRAFT` offer for a candidate at the `OFFER` pipeline stage (fsd 03 §REC-S09, db 04 §5). Freezes `offer_terms` and stamps `pay_structure_version`/`compliance_pack_version` at **submit**, not at draft creation (db 04 §5 notes) — this create captures the working draft only.\n",
        "tags": [
          "recruit",
          "offer"
        ],
        "x-token": "recruit.offer.create",
        "x-realizes-features": [
          "REC-F05"
        ],
        "x-screens": [
          "REC-S09"
        ],
        "x-touches-entities": [
          "recruit.offers"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OfferCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Offer created (`status = 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/Offer"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/offers/{id}": {
      "get": {
        "operationId": "recruit.offer.get",
        "summary": "Get an offer",
        "description": "Offer detail — hosted for the recruiter/HR builder (fsd 03 §REC-S09), the letter lifecycle view (§REC-S10), and the **candidate's own offer review** (§REC-S13, principal = applicant, `self` scope additionally restricts the row to the candidate's own offer).\n",
        "tags": [
          "recruit",
          "offer"
        ],
        "x-token": "recruit.offer.get",
        "x-realizes-features": [
          "REC-F05",
          "REC-F06"
        ],
        "x-screens": [
          "REC-S09",
          "REC-S10",
          "REC-S13"
        ],
        "x-touches-entities": [
          "recruit.offers"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Offer.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Offer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "recruit.offer.update",
        "summary": "Edit a draft offer",
        "description": "Edits grade/pay-structure/CTC/terms/joining-date/validity on a `DRAFT` offer (fsd 03 §REC-S09). Versioned — requires `If-Match`.",
        "tags": [
          "recruit",
          "offer"
        ],
        "x-token": "recruit.offer.update",
        "x-realizes-features": [
          "REC-F05"
        ],
        "x-screens": [
          "REC-S09"
        ],
        "x-touches-entities": [
          "recruit.offers"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OfferUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated offer.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Offer"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/offers/{id}/submit": {
      "post": {
        "operationId": "recruit.offer.submit",
        "summary": "Submit an offer for approval",
        "description": "`DRAFT → PENDING_APPROVAL`, **freezes** `offer_terms` + `pay_structure_version`/`compliance_pack_version`/ `tenant_config_versions` (config-version stamp, db 04 §5/db-docs 00 §8), stamps `submitted_by` (maker); the checker approves/rejects in the unified approvals inbox (`XC-F12`, four-eyes). Money decimal, never float.\n",
        "tags": [
          "recruit",
          "offer"
        ],
        "x-token": "recruit.offer.submit",
        "x-realizes-features": [
          "REC-F05"
        ],
        "x-screens": [
          "REC-S09"
        ],
        "x-touches-entities": [
          "recruit.offers"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "recruit.offer.submitted",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Offer submitted.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Offer"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/offers/{id}/decline": {
      "post": {
        "operationId": "recruit.offer.decline",
        "summary": "Decline an offer (candidate)",
        "description": "`→ DECLINED`, stamps `responded_at` (fsd 03 §REC-S13). Principal: the **applicant** (offer recipient, pre-hire `XC-F03` identity) — this is the candidate-facing decline half of the accept/decline pair (accept is `recruit.offer_letter.sign`).\n**DEFERRED — answers `501` in this build (SGAP-05, #330), and `#1655` narrowed what that 501 MEANS.** A decline itself is NOT blocked: `POST /public/offer-response/{token}` with `{\"decision\":\"DECLINED\"}` already authenticates the candidate by token for the length of one decision and already records it, and HR records one on the candidate's behalf through `recruit.offer.record_response`. What waits on applicant principals is this APPLICANT-PRINCIPAL ROUTE, and — genuinely — the e-sign half (`recruit.offer_letter.sign`): a signature is a claim about who signed, and a one-decision bearer token is not an identity that can carry it. The 501 detail on each of the two routes now names the doors that DO work for its own operation, rather than the single shared sentence that implied a decline was impossible.\n",
        "tags": [
          "recruit",
          "offer"
        ],
        "x-token": "recruit.offer.decline",
        "x-realizes-features": [
          "REC-F06",
          "REC-F05"
        ],
        "x-screens": [
          "REC-S13"
        ],
        "x-touches-entities": [
          "recruit.offers"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "recruit.offer.declined",
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "description": "Optional free-text decline reason (notification only)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Offer declined.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Offer"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/offers/{id}/record-response": {
      "post": {
        "operationId": "recruit.offer.record_response",
        "summary": "Record the candidate's offer response (HR)",
        "description": "Contract ADDITION (2026-08-07, GAP-27): records a candidate's **off-platform** accept/decline on a `SENT` offer — the internal-ATS acceptance door while applicant principals (`XC-F03` pre-hire identities, SGAP-05) and the mobile applicant surfaces (#229/#230) are deferred. `ACCEPTED` stamps `responded_at` and marks the live letter `SIGNED`, stamping `signed_storage_key`/`signed_content_hash` from **the SENT letter's own artifact** — not a fresh render (issue #866: re-rendering a document the candidate never saw and calling it acceptance evidence would be dishonest; the real evidence is the immutable sent letter's own hash plus this call's audit-plane record of who recorded the response, when, and the evidence note) — opens the `preboarding` case and emits `recruit.offer.accepted`; `DECLINED` emits `recruit.offer.declined`. The evidence note and the recording employee land on the append-only audit plane. The applicant self-service pair (`recruit.offer.decline`, `recruit.offer_letter.sign`) supersedes nothing here — both doors coexist once applicants can act for themselves.\n**`#1655` made this the PRIMARY forward action on the offer page, not a fallback.** A recruiter must be able to move a hire without waiting for a candidate to click anything, for EITHER outcome — and the decline half had no working HR surface at all, only an endpoint name.\n**The 200 body now carries WHAT THE ACCEPTANCE DID**, beside the offer's own fields (`#1655`): `preboarding_id` (the case it opened, so the caller can go there rather than be told a case exists somewhere), `onboarding_flow_id`, `joining_employee_id`, `joining_employee_no`, `joining_employee_created`, `onboarding_flow_created` and — critically — `joining_skipped_reason` when the mint refused. Those refusals reached the outbox payload and the audit row and no human; the person who recorded the acceptance is the only one who can act on them. All are absent on a `DECLINED` response. The same vocabulary is described on `Offer.joining_skipped_reason`.\n",
        "tags": [
          "recruit",
          "offer"
        ],
        "x-token": "recruit.offer.record_response",
        "x-realizes-features": [
          "REC-F05",
          "REC-F06"
        ],
        "x-screens": [
          "REC-S09",
          "REC-S10"
        ],
        "x-touches-entities": [
          "recruit.offers",
          "recruit.offer_letters",
          "recruit.preboarding"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "recruit.offer.accepted",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OfferRecordResponseRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Response recorded.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Offer"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/offers/{id}/offer-email-preview": {
      "post": {
        "operationId": "recruit.offer.preview_email",
        "summary": "Preview the candidate offer email (HR)",
        "description": "ADR 0039, issue #867 (recruit leg 7 — the HR-facing half of the candidate magic-link surface; the PUBLIC half lives on `recruit.offer_response.*`). Server-renders the seeded `email.offer` template (`org.templates`, seed_key `email.offer`) against this offer's live data — the exact subject/body `recruit.offer.send_email` would produce — so HR can review it before committing to a real send. Read-shaped: no mutation, no `Idempotency-Key`. `{{offer_response_url}}` resolves to a clearly-marked, non-functional placeholder path (`.../offer-response/<preview>`) — a preview **never** mints a real ADR 0039 response token, because minting is itself a write (it revokes the offer's current live token).\n",
        "tags": [
          "recruit",
          "offer"
        ],
        "x-token": "recruit.offer.preview_email",
        "x-realizes-features": [
          "REC-F05"
        ],
        "x-screens": [
          "REC-S10"
        ],
        "x-touches-entities": [
          "recruit.offers",
          "recruit.offer_letters",
          "recruit.candidates"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Rendered preview of the offer email.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OfferEmailPreview"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "No published `email.offer` template is configured for this workspace, or the template body for the resolved locale cannot be rendered (a missing required merge value or an unresolved placeholder — `Problem`).\n",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/offers/{id}/send-offer-email": {
      "post": {
        "operationId": "recruit.offer.send_email",
        "summary": "Send the candidate offer email (HR)",
        "description": "ADR 0039, issue #867 (recruit leg 7). The HR-facing door that actually delivers the candidate magic link: in ONE transaction, mints a fresh ADR 0039 response token (revoking any predecessor), renders `email.offer` with `{{offer_response_url}}` resolved to the REAL link, attaches the already-`SENT` letter's own PDF (fetched by the jobs-tier dispatcher at send time, never here — see `xc.mail_attachments`), and queues an `xc.mail_messages` row. Requires the offer to be `status = SENT` with a live `SENT` letter carrying a stored artifact (`recruit.offer_letter.send` is the only path that reaches that state) and the candidate to have an email address on file. Optional `subject`/`body_text` overrides REPLACE the rendered content on the mail row only — `org.templates` is never modified — and a `body_text` override must retain the literal `{{offer_response_url}}` placeholder, which is substituted with the real link; an edit that drops it is refused (a mail with no response link is a dead end for the candidate). The response never carries the selector, verifier or URL — only `mail_message_id`, `to_address` and `expires_at`. Both `PUBLIC_LINK_HMAC_SECRET` and `PUBLIC_LINK_BASE_URL` must be configured; if either is unset this fails closed with a `500` rather than mailing a broken or unhashable-recipient link.\n",
        "tags": [
          "recruit",
          "offer"
        ],
        "x-token": "recruit.offer.send_email",
        "x-realizes-features": [
          "REC-F05"
        ],
        "x-screens": [
          "REC-S10"
        ],
        "x-touches-entities": [
          "recruit.offers",
          "recruit.offer_letters",
          "recruit.offer_response_tokens",
          "recruit.candidates",
          "xc.mail_messages",
          "xc.mail_attachments"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "xc.email.requested",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OfferSendEmailRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Offer email queued.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OfferSendEmailResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Specific, honest refusals (this is the HR-facing door — unlike the public candidate surface, which answers a uniform 404): the offer is not `SENT`; the offer has no `SENT` letter with a stored artifact; the candidate has no email address on file; no published `email.offer` template is configured; the template cannot be rendered; or an HR body override dropped the `{{offer_response_url}}` placeholder (`Problem`).\n",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "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"
          },
          "500": {
            "description": "Fail-closed configuration gap: `PUBLIC_LINK_HMAC_SECRET` and/or `PUBLIC_LINK_BASE_URL` are not set for this deployment, so no usable candidate link can be minted. Operator-facing detail text only — never a secret value.\n",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/offers/{id}/response-link": {
      "post": {
        "operationId": "recruit.offer.response_link",
        "summary": "Issue a shareable candidate response link (HR)",
        "description": "Issue #1487, owner decision 3 of the 2026-08-31 recruit pass. The offer email is the only channel this product can put a candidate response link into, and when it fails HR has no way to see the link at all — it is NOT recoverable after the send, by design (only `verifier_hash` is stored; `offer-response-mint.ts` lets the verifier go the moment it reaches the mail body). This is that link's own door: it MINTS A FRESH ADR 0039 token (revoking any predecessor, the same way a resend does — any link the candidate already holds stops working) and returns the full URL **once**, in the response body. There is no read that returns a stored link, because there is no stored link; adding one would mean persisting a bearer credential in plaintext. The URL is for HR to hand over through a channel of their own — copy, or a `wa.me` deep link into the sharer's own WhatsApp. No delivery is performed and none is tracked.\nIts own token, `recruit.offer.response_link`, granted to exactly the roles that hold `recruit.offer.send_email`: it is the same trust boundary — whoever may mail a candidate the link may hand it over — kept as its own catalogue row because this product's matrix is keyed one operation = one token, and the act is audited (`recruit.offer.response_link_issued`) so who obtained a live link, and when, is on the record. Preconditions are the send's, verbatim: offer `SENT`, a live `SENT` letter with a stored artifact, and a candidate email on file (the token's `issued_to_hash` is a keyed digest of the address it is issued against, and that column is `NOT NULL`).\nNO `Idempotency-Key`, deliberately: the product idempotency store persists response bodies, so a replay would both put the credential at rest and hand back a URL the next mint had already revoked. `Cache-Control: no-store` (plus `X-Robots-Tag: noindex, nofollow`) is part of the contract, not polish — the body carries a live secret. The link's STATE afterwards (issued/expires/opened/retired, never the credential) rides `GET /offers/{id}` as `response_link`.\n",
        "tags": [
          "recruit",
          "offer"
        ],
        "x-token": "recruit.offer.response_link",
        "x-realizes-features": [
          "REC-F05"
        ],
        "x-screens": [
          "REC-S10"
        ],
        "x-touches-entities": [
          "recruit.offers",
          "recruit.offer_letters",
          "recruit.offer_response_tokens",
          "recruit.candidates"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "A freshly-minted response link. Returned ONCE — it cannot be read back, and the next call to this operation (or a resend of the offer email) retires it.\n",
            "headers": {
              "Cache-Control": {
                "description": "Always `no-store` — the body carries a live bearer credential.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OfferResponseLinkResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The offer is not `SENT`; it has no `SENT` letter with a stored artifact; or the candidate has no email address on file (`Problem`).\n",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "description": "`#1654` hop 5 — the link would be **born expired**. `expires_at` is `LEAST(offer.valid_until end-of-day, issue + 30d)` (ADR 0039), so an offer whose `valid_until` has already passed used to mint a token that was dead the instant it existed: the candidate saw the public rail's uniform 404 and the offer page reported the link as merely `expired`, which reads as \"it lapsed\" rather than \"it never worked\". On dev the three most recent `recruit.offer_response_tokens` rows for the demo tenant were created `2026-09-10 09:40` with `expires_at = 2026-09-01 23:59:59`. The problem's `errors[]` names `/valid_until` with rule `offer_validity_passed` — the field an operator must change. The same refusal applies to `recruit.offer.send_email` and `recruit.offer_letter.send`, which mint through the same path.\n",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "428": {
            "$ref": "#/components/responses/PreconditionRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "description": "Fail-closed configuration gap: `PUBLIC_LINK_HMAC_SECRET` and/or `PUBLIC_LINK_BASE_URL` are not set for this deployment, so no usable candidate link can be minted. Operator-facing detail text only — never a secret value.\n",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/offers/{id}/retry-handoff": {
      "post": {
        "operationId": "recruit.offer.retry_handoff",
        "summary": "Re-run the hire hand-off for an accepted offer (HR)",
        "description": "Issue `#1655` (owner pass 2026-09-11). Re-runs the hire hand-off for an offer that is ALREADY `ACCEPTED`, after a human has fixed the fact the last attempt named. The acceptance is not re-decided and nothing on the offer changes — no status move, no version bump.\nWHY IT IS NEEDED. `mintJoiningEmployee` refuses by RECORDING, never by throwing: recording an acceptance is a legitimate ATS action and must always succeed, so a candidate with no pipeline card, an opening whose requisition names no legal entity, an offer frozen without a BASIC split, a workspace at its plan cap, or a recorder without `people.employee.create_joining` all leave the acceptance intact and name the reason (`Offer.joining_skipped_reason`). Until this operation the only remedy was to accept the offer again, which is impossible. It is ALSO the only door that mints at all for an offer the candidate accepted through their own public link: that rail is unauthenticated, has no principal to resolve the mint token against, and so opens the pre-boarding case and stops — `HANDOFF_NOT_RUN`.\n**`x-token` is `recruit.offer.record_response`, deliberately NOT a new catalogue row.** It re-runs the acceptance's own hand-off, so it carries the acceptance's own authority: every principal who may record an acceptance may retry it, and no tenant needs an RBAC re-seed before the button works. (The precedent for an operation reusing a sibling's token is `people.employee.status_counts`, `attend.attendance_record.get_sessions` and five others.) The MINT's own authority is unchanged and still resolved separately and permissively against `people.employee.create_joining` before the transaction opens — a caller without it gets `NOT_AUTHORIZED` recorded again rather than a 403, because that is the answer that names the missing grant.\n`If-Match` is required for the reason every other offer decision requires it. The 200 body is the offer plus the hand-off outcome fields described on `recruit.offer.record_response`.\n**It emits `recruit.offer.handoff_retried`, NOT a second `recruit.offer.accepted`** (PR #1756 review). Re-using the acceptance's event type reads as harmless and is not: the mail consumer's exactly-once key is `'<event_type>:<outbox_event_id>[:<suffix>]'`, keyed on the OUTBOX EVENT and never on the pre-boarding case, so a second `recruit.offer.accepted` for the same offer carries a new event id, misses the `ON CONFLICT (tenant_id, dedupe_key)` guard, and `buildOnboardingPackPlans` mints THREE MORE `DRAFT` onboarding-pack mails (welcome / credentials / ESS access) against the same `recruit.preboarding` row. It is also a notification class (`approver: IN_APP`), so the approver would be told again — days late — that an offer was accepted. A retry is a different fact and says so; the payload is identical, and `recruit.offer.accepted` now belongs to the two acceptance doors alone. No consumer subscribes to the new type today, which is the correct blast radius for an operational repair. (The AsyncAPI document is a curated subset, not an exhaustive dump — see its own header and `db-docs/00 §8.2` — so this `x-emits-event` declaration is where the type is recorded.)\n",
        "tags": [
          "recruit",
          "offer"
        ],
        "x-token": "recruit.offer.record_response",
        "x-realizes-features": [
          "REC-F05",
          "REC-F06"
        ],
        "x-screens": [
          "REC-S10"
        ],
        "x-touches-entities": [
          "recruit.offers",
          "recruit.candidate_pipeline",
          "people.onboarding_flows",
          "people.employees"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "recruit.offer.handoff_retried",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "The hand-off ran again. `joining_employee_id` non-null means it succeeded; `joining_skipped_reason` non-null means it refused again, with the CURRENT reason.\n",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Offer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The offer is not `ACCEPTED` — there is no hand-off to re-run (`Problem`).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/offers/{id}/letters": {
      "post": {
        "operationId": "recruit.offer_letter.create",
        "summary": "Generate the offer letter",
        "description": "Enqueues an asynchronous render of the offer letter from an `org.templates` OFFER template (ADR 0023, the same `org.template_renders` rail every other rendered document uses) — only while `offers.status = APPROVED`. The request validates the template and requests the render **in the same transaction** as the insert; the row lands `status = GENERATING` with `render_id` set and `file = null` — there is no artifact yet. The render completes out-of-band: a success stamps the artifact and flips `GENERATING → GENERATED`; a permanent failure flips `GENERATING → VOID` with `render_error` set (freeing the one-live-letter-per-offer slot so this can be called again). Poll `GET /offer-letters/{id}` to observe the transition (fsd 03 §REC-S10, db 04 §5, issue #866).\n",
        "tags": [
          "recruit",
          "offer_letter"
        ],
        "x-token": "recruit.offer_letter.create",
        "x-realizes-features": [
          "REC-F05"
        ],
        "x-screens": [
          "REC-S10"
        ],
        "x-touches-entities": [
          "recruit.offer_letters",
          "recruit.offers"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OfferLetterCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Render enqueued — the letter is created at `status = GENERATING`, `file = null`. This is a 201 (a new `offer_letters` resource now exists at `Location`), not a 202: the resource is real and addressable immediately, only its artifact is still pending.\n",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OfferLetter"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "description": "Field-level validation failed (`ValidationProblem`). Two refusals are specific to this operation (issue #866): `/template_id` — the template does not resolve in this workspace, is not `status = PUBLISHED`, is not `kind = LETTER`, or is not `sub_type = OFFER`; `/joining_date` — the offer has no joining date yet, and the seeded `letter.offer` template's manifest requires `date_of_joining` to render.\n",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationProblem"
                }
              }
            }
          },
          "423": {
            "$ref": "#/components/responses/Locked"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "get": {
        "operationId": "recruit.offer_letter.list",
        "summary": "List letters for an offer",
        "tags": [
          "recruit",
          "offer_letter"
        ],
        "x-token": "recruit.offer_letter.list",
        "x-realizes-features": [
          "REC-F05"
        ],
        "x-screens": [
          "REC-S10"
        ],
        "x-touches-entities": [
          "recruit.offer_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": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Page of letters.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/OfferLetter"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/offer-letters/{id}": {
      "get": {
        "operationId": "recruit.offer_letter.get",
        "summary": "Get an offer letter",
        "description": "Letter status timeline (fsd 03 §REC-S10) and the **candidate's own letter** for review/e-sign (§REC-S13, `self` scope additionally restricts to the candidate's own letter).\n",
        "tags": [
          "recruit",
          "offer_letter"
        ],
        "x-token": "recruit.offer_letter.get",
        "x-realizes-features": [
          "REC-F05",
          "REC-F06"
        ],
        "x-screens": [
          "REC-S10",
          "REC-S13"
        ],
        "x-touches-entities": [
          "recruit.offer_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": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Offer letter.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OfferLetter"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/offer-letters/{id}/send": {
      "post": {
        "operationId": "recruit.offer_letter.send",
        "summary": "Send the offer letter to the candidate",
        "description": "SEND TO CANDIDATE — ONE action, ONE transaction (issue #1486). `GENERATED → SENT`; moves the parent `offers.status APPROVED → SENT` and stamps `sent_at`; mints a fresh ADR 0039 candidate response token (revoking any predecessor); and queues the `email.offer` mail with the letter's own PDF attached and `{{offer_response_url}}` resolved to the real link. Either all of that happens or none of it does. Until #1486 this operation flipped the two status columns and stopped — the candidate received nothing while the page reported \"Sent\", and the `recipient_email` its modal insisted on was discarded because the handler declared no body.\n\n`recipient_email` is OPTIONAL and, when supplied, is the address actually written to instead of the candidate's own — the token's `issued_to_hash` is then the keyed digest of THAT address, so the evidence names who was really mailed. Omitted, the candidate's address on file is used, which is `recruit.offer.send_email`'s contract unchanged.\n\nAUTHORIZATION. The operation keeps its own token (`recruit.offer_letter.send`) — one operation, one token — and the service ADDITIONALLY requires `recruit.offer.send_email`, because this call now performs the act that token names: putting a live candidate credential in an inbox. Both resolve to `[recruiter, hr_admin]` today, so nothing that could call this before is refused now; a caller holding only the letter token is refused with `403` rather than silently getting the old half-step. `recruit.offer.send_email` remains a separate operation for RESENDS.\n\nA letter still `GENERATING` cannot be sent — refused with its own honest `409` detail (\"still being generated\"), distinct from the generic \"only a GENERATED letter can be sent\" refusal for any other non-`GENERATED` state (issue #866). Both `PUBLIC_LINK_HMAC_SECRET` and `PUBLIC_LINK_BASE_URL` must be configured; if either is unset this fails closed with a `500` rather than marking a letter sent that no candidate can open. The e-sign ceremony reference (`esign_request_id → docs.esign_requests`, `DOC-F02`) stays NULL — the acceptance ceremony is the typed name + consent on the candidate's own response page (`recruit.offer_response.submit`).\n",
        "tags": [
          "recruit",
          "offer_letter"
        ],
        "x-token": "recruit.offer_letter.send",
        "x-realizes-features": [
          "REC-F05"
        ],
        "x-screens": [
          "REC-S10"
        ],
        "x-touches-entities": [
          "recruit.offer_letters",
          "recruit.offers",
          "recruit.offer_response_tokens",
          "recruit.candidates",
          "xc.mail_messages",
          "xc.mail_attachments"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "xc.email.requested",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OfferLetterSendRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Letter sent to the candidate; the response link is live and the mail is queued.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OfferLetter"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/offer-letters/{id}/void": {
      "post": {
        "operationId": "recruit.offer_letter.void",
        "summary": "Revoke / void a letter",
        "description": "`→ VOID`; a revised offer renders a new letter (fsd 03 §REC-S10).",
        "tags": [
          "recruit",
          "offer_letter"
        ],
        "x-token": "recruit.offer_letter.void",
        "x-realizes-features": [
          "REC-F05"
        ],
        "x-screens": [
          "REC-S10"
        ],
        "x-touches-entities": [
          "recruit.offer_letters"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Letter voided.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OfferLetter"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/offer-letters/{id}/sign": {
      "post": {
        "operationId": "recruit.offer_letter.sign",
        "summary": "Accept & sign the offer (candidate)",
        "description": "Completes the in-house e-sign ceremony opened at send (`DOC-F02`): `offer_letters.status → SIGNED` (`signed_storage_key`/`signed_content_hash`/`signed_at`), flips the parent `offers.status SENT → ACCEPTED`, and **asynchronously** emits `recruit.offer.accepted` — the event handler creates the `preboarding` row (`status = OFFER_ACCEPTED`); the applicant does not write `preboarding` directly (fsd 03 §REC-S13, *gaps* 10). Only within `offers.valid_until`. Principal: the **applicant** (offer recipient, pre-hire `XC-F03` identity; no `people` row yet).\n**DEFERRED — answers `501` in this build, and after `#1655` this is the half of the old shared deferral that is still true.** An e-signature is a claim about WHO signed, and the one-decision response token is not an identity that can carry it; it waits on `xc.identities` applicant principals (SGAP-05, #330). ACCEPTANCE ITSELF IS NOT BLOCKED: the candidate accepts on their response link (`POST /public/offer-response/{token}`, which runs the typed-name + consent ceremony of `#1486`), or HR records it through `recruit.offer.record_response`, and the SENT letter is stamped `SIGNED` from its own immutable artifact either way.\n",
        "tags": [
          "recruit",
          "offer_letter"
        ],
        "x-token": "recruit.offer_letter.sign",
        "x-realizes-features": [
          "REC-F06",
          "REC-F05"
        ],
        "x-screens": [
          "REC-S13"
        ],
        "x-touches-entities": [
          "recruit.offer_letters",
          "recruit.offers",
          "recruit.preboarding"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "async",
        "x-emits-event": "recruit.offer.accepted",
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OfferLetterSignRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Signature accepted; the offer-accept hand-off (preboarding creation) completes asynchronously.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OfferLetter"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/preboarding-cases": {
      "get": {
        "operationId": "recruit.preboarding.list",
        "summary": "List pre-boarding cases",
        "description": "HR pre-boarding tracker tab (fsd 03 §REC-S11). Sort whitelist `expected_joining_date`, `status`.",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.list",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S11"
        ],
        "x-touches-entities": [
          "recruit.preboarding",
          "people.onboarding_flows"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "OFFER_ACCEPTED",
                "DOCS_PENDING",
                "DOCS_SUBMITTED",
                "CHECKLIST",
                "READY_TO_ONBOARD",
                "WITHDRAWN"
              ]
            }
          },
          {
            "name": "candidate_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of pre-boarding cases.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Preboarding"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/preboarding-cases/{id}": {
      "get": {
        "operationId": "recruit.preboarding.get",
        "summary": "Get a pre-boarding case",
        "description": "HR drawer (fsd 03 §REC-S11) and the applicant's own case for document upload (§REC-S14) and the joining checklist (§REC-S15) — `self` scope additionally restricts to the applicant's own case there.\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.get",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S11",
          "REC-S14",
          "REC-S15"
        ],
        "x-touches-entities": [
          "recruit.preboarding",
          "people.onboarding_flows"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Pre-boarding case.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Preboarding"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "recruit.preboarding.update",
        "summary": "Assign or clear the pre-boarding case's work email (HR)",
        "description": "Sets or clears `work_email` and stamps `work_email_assigned_at`/`work_email_assigned_by` (migration `0125`, bug R6, decisions register #5). The corporate mailbox IT provisioned, typed in by a human — never defaulted, never synthesized from `candidates.email`. Additionally completes any `PENDING`/`IN_PROGRESS` `IT_PROVISIONING` task on the linked onboarding checklist (fsd 03 §REC-S11). `409` on a duplicate work email (case-insensitive, per-tenant — `preboarding_tenant_work_email_key`). Principal: HR (recruiter/hr_admin console — the applicant never sets their own work email).\n\nSince #1475 the address does not stop on the case: a live guided flow for the same candidate takes the value, and the minted employee's `work_email` is filled **only when it is still `NULL`**, which runs the same provisioning seam `people.employee.update` runs and creates the `xc.identities` row an ESS sign-in is built from. An address an identity was already provisioned against is never repointed here — that is an account-takeover shape, not an edit, and belongs to People's own tokens. No invitation is issued by this call, and since #1638 none is issued by anything: the employee adopts their ESS principal by proving control of this very address with an OTP at sign-in, so setting the address IS granting the access.\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.update",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S11"
        ],
        "x-touches-entities": [
          "recruit.preboarding",
          "recruit.onboarding_tasks",
          "people.onboarding_flows",
          "people.employees",
          "xc.identities"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreboardingUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Pre-boarding case updated.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Preboarding"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/preboarding-cases/{id}/documents/upload-url": {
      "post": {
        "operationId": "recruit.preboarding.request_upload_url_for_candidate",
        "summary": "Mint a presigned upload target for one joining document, on the candidate's behalf (HR)",
        "description": "`REC-S20` step 1, HR side (#1473). Documents used to reach a case only through the candidate's own link, so a scan that arrived by email or a photocopy handed over at the desk could not be recorded at all. The object key is still built entirely server-side — from `app.current_tenant()` and the **path** case id (`<tenantId>/preboarding/<caseId>/<docType>/document.<ext>`), never from anything the caller sent — and the doc type must already be on this case's checklist. `200`, not `201`: an ephemeral mint, no row is persisted at this step. Refused on a case that has left the HR-uploadable states (`OFFER_ACCEPTED`, `DOCS_PENDING`, `DOCS_SUBMITTED`, `CHECKLIST`, `READY_TO_ONBOARD` — the last added by #1656; only `WITHDRAWN` is now refused).\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.request_upload_url_for_candidate",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S11",
          "REC-S23"
        ],
        "x-touches-entities": [
          "recruit.preboarding"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreboardingRequestUploadUrlRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Presigned upload target.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreboardingUploadUrlResult"
                }
              }
            }
          },
          "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"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/preboarding-cases/{id}/documents": {
      "post": {
        "operationId": "recruit.preboarding.upload_document_for_candidate",
        "summary": "Register a document uploaded on the candidate's behalf (HR)",
        "description": "`REC-S20` step 2, HR side (#1473). Registers the object a prior `upload-url` call targeted and stamps the checklist item `UPLOADED`, which is the only status `verify_document` will act on. The `storage_key` is re-validated against this case's own `<tenant>/preboarding/<caseId>/<docType>/` prefix and the `content_type` is RE-ASSERTED here rather than trusted from the mint step — the two are separate requests. `replace: true` (the default) supersedes the prior objects for that doc type in place. `uploaded_by_identity` records the BACK-OFFICE identity, and the checklist item additionally carries `uploaded_source: HR` so a reader is never left implying the candidate uploaded it. Writes an `audit.audit_log` row, `preboarding.document.uploaded_by_hr`, naming the case, doc type, storage key and actor. MAKER-CHECKER (spec §6) is SURFACED, not refused: the same identity may still call `verify_document`, and the console warns them prominently on the row — a hard block would strand a single-HR-user workspace with a document nobody may verify.\n\nREOPENING A FINISHED CASE (#1656). `READY_TO_ONBOARD` is an HR-uploadable state: every required document there is already `VERIFIED`, so a replacement clears that document's verification stamps (`stampDocumentUploaded`, F7) and the case is walked back to `DOCS_SUBMITTED` with `checklist_completed_at` cleared and `progress_pct` recomputed, in the SAME transaction. The response carries `case_status` and `reopened_for_reverification` so the caller does not have to infer it from a refresh, and the audit row records `reopened_from`. The case's `version` is deliberately NOT bumped — an upload is not a concurrent edit of the case the caller holds an ETag for, and bumping it would invalidate the open `verify-document` `If-Match` the reader must now use. Excluding the state instead (the pre-#1656 behaviour) made the control vanish on the one screen HR reaches at the end of the flow, which read as \"the product cannot upload documents at all\".\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.upload_document_for_candidate",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S11",
          "REC-S23"
        ],
        "x-touches-entities": [
          "recruit.preboarding_documents",
          "recruit.preboarding",
          "audit.audit_log"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreboardingUploadDocumentRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Document registered.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreboardingDocumentRecord"
                }
              }
            }
          },
          "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"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/preboarding-cases/{id}/invite": {
      "post": {
        "operationId": "recruit.preboarding.send_invite",
        "summary": "Issue (or re-issue) the candidate's pre-boarding invite link (HR)",
        "description": "Mints a `selector.verifier` invite token and mails it to the candidate — the entry point into the Join surface (`REC-S19`, #694/#695, ADR 0039). A re-send **supersedes** (not revokes) whatever link is currently live: the case's prior token moves `ACTIVE → SUPERSEDED`, one live token per case stays a partial-unique invariant, and the case's own `status` advances `OFFER_ACCEPTED → DOCS_PENDING` the first time a link is issued. The raw token is returned to the caller **exactly once** — the row persists only a digest, so a lost link can only be replaced by issuing a new one, never recovered.\n\nSince #1657 the 201 also carries `url`: the same credential with the origin (`PUBLIC_LINK_BASE_URL`) and the workspace segment (`xc.tenant_cache.workspace_slug`) already resolved, so the back office never assembles an origin itself. It is not a second secret — anyone holding `token` can build it — and it is `null` when either half is unconfigured, because a half-built link is worse than none. The console shows it to the person who just chose to issue it, for that session only; nothing persists or re-reads it, and a resend supersedes. Refused with `422` (`/expected_joining_date`, rule `joining_date_passed`) when the joining date plus the grace window has already passed — the token would be born expired (#1657, the #1654 hop-5 lesson).\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.send_invite",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S11"
        ],
        "x-touches-entities": [
          "recruit.preboarding_invite_tokens",
          "recruit.preboarding"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "201": {
            "description": "Invite issued. The response's `tokenId`/`token`/`expiresAt`/`preboardingId`/`candidateId` fields are deliberately camelCase — this is the raw mail-rail payload, handed to the outbound mailer exactly as minted, not the usual snake_case API projection (this is the one response in the product carrying a live credential; never cache it).\n",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreboardingInviteResult"
                }
              }
            }
          },
          "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"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/preboarding-cases/{id}/revoke-invite": {
      "post": {
        "operationId": "recruit.preboarding.revoke_invite",
        "summary": "Kill the candidate's live invite link (HR)",
        "description": "Three kills in one transaction (REC-S11, #695): the live invite token → `REVOKED`; the linked `APPLICANT` identity (if any browser ever exchanged the link) → `DEACTIVATED`; and every live session that identity holds → `REVOKED`. A cookie already sitting in a candidate's browser stops resolving on its very next request, whatever the cookie itself still says.\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.revoke_invite",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S11"
        ],
        "x-touches-entities": [
          "recruit.preboarding_invite_tokens",
          "xc.identities",
          "xc.sessions"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreboardingRevokeInviteRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invite revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreboardingRevokeInviteResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/preboarding-cases/{id}/extend-invite": {
      "post": {
        "operationId": "recruit.preboarding.extend_invite",
        "summary": "Push the candidate's live invite link's expiry out (HR)",
        "description": "Extends the live token's `expires_at` by `days`, bounded by the same policy-configured TTL that set it originally (REC-S11, #695) — an extension can never mint an effectively immortal link.\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.extend_invite",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S11"
        ],
        "x-touches-entities": [
          "recruit.preboarding_invite_tokens"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreboardingExtendInviteRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invite extended.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreboardingExtendInviteResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/preboarding-cases/{id}/documents/{documentId}/view": {
      "get": {
        "operationId": "recruit.preboarding.view_document",
        "summary": "Open one uploaded pre-boarding document (HR, privileged + logged)",
        "description": "Resolves a SHORT-LIVED presigned GET URL for one uploaded document and writes the `audit.access_log` row FIRST, so the console's stated promise (\"Opening an ID document is logged\") holds by construction (REC-S23, #695, design-ess/10 §6/§11). The `data_class` is derived from the document type — `AADHAAR`/`NATIONAL_ID`/`IQAMA`/`BANK` are named explicitly so a compliance query for \"who opened an Aadhaar?\" returns them; everything else is `PII_OTHER`, which is still PII and still logged. The case id is part of the lookup predicate, not merely of the path, so a document id alone cannot open an object belonging to a different case. The URL expires in 120 seconds and the response is `Cache-Control: no-store`, because a presigned URL is a bearer token for the object.\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.view_document",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S23"
        ],
        "x-touches-entities": [
          "recruit.preboarding_documents",
          "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": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "documentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The `recruit.preboarding_documents` row to open."
          }
        ],
        "responses": {
          "200": {
            "description": "A short-lived presigned URL for the document. The access has already been logged.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "doc_type",
                    "url",
                    "expires_at"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "doc_type": {
                      "type": "string"
                    },
                    "file_name": {
                      "type": "string",
                      "nullable": true
                    },
                    "content_type": {
                      "type": "string",
                      "nullable": true
                    },
                    "url": {
                      "type": "string",
                      "description": "Presigned GET URL",
                      "valid 120s. Never cached": null,
                      "never logged.": null
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/preboarding-cases/{id}/verify-document": {
      "post": {
        "operationId": "recruit.preboarding.verify_document",
        "summary": "Verify or reject a submitted joining document (HR)",
        "description": "Stamps the named `required_documents[]` item `VERIFIED` (`verified_by`/`verified_at`) or `REJECTED` (`reject_reason`, required) (fsd 03 §REC-S11, db 04 §6). A reject returns the item to the applicant for re-upload (`REC-S14`). Advances `DOCS_PENDING` as well as `DOCS_SUBMITTED` once every required document is `VERIFIED` (#1656): documents HR entered on the candidate's behalf never pass the candidate's submit door.\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.verify_document",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S11"
        ],
        "x-touches-entities": [
          "recruit.preboarding"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreboardingVerifyDocumentRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document reviewed.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Preboarding"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/preboarding-cases/{id}/checklist": {
      "put": {
        "operationId": "recruit.preboarding.define_checklist",
        "summary": "Shape a case's joining checklist from a template (HR)",
        "description": "`REC-S22` — sets `required_documents[]` and `checklist_items[]` on the case and, when given, `expected_joining_date` (#695, GAP-ESS-35). Re-defining the required-document set **carries forward** any verification already recorded against a `doc_type` that survives into the new set (`status`, `verified_by`, `verified_at`, `reject_reason`) — editing the checklist must not silently re-open a document HR already approved. A withdrawn case has no checklist to define.\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.define_checklist",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S11"
        ],
        "x-touches-entities": [
          "recruit.preboarding"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreboardingDefineChecklistRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Checklist defined.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Preboarding"
                }
              }
            }
          },
          "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"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/preboarding-cases/{id}/trigger-prefill": {
      "post": {
        "operationId": "recruit.preboarding.trigger_prefill",
        "summary": "Carry verified pre-boarding data onto the joining flow (HR, server-side)",
        "description": "`PPL-S31` — HR-held and server-side; a candidate can neither call this nor influence its timing (#696, GAP-ESS-36). Only fields from the `PERSONAL` candidate-data section that survive the shared prefill allow-list are carried, and only once the case is `CHECKLIST` or `READY_TO_ONBOARD` — prefill from an unverified case would carry unreviewed statutory identifiers into an employee record before HR has checked them. Opens or resumes the one live `people.onboarding_flows` row for the candidate — a candidate with no flow gets one opened from the same hire facts the `recruit.candidate.hired` auto-feed uses, then filled (#1474). `skipped_reason` explains a no-op prefill, and each value names a different absence: `stage_passed` and `already_populated` are the two never-overwrite refusals on a flow that exists; `nothing_verified` is a case with no verified personal data to carry, and opens nothing; `already_hired` is #800's duplicate-mint guard — the candidate is an employee already, so `flow_id` is their COMPLETED flow and no second one is minted; `no_open_flow` means only that no pipeline card resolves an opening whose requisition names a legal entity, so no flow could be opened honestly. No cross-schema write — this calls People's own onboarding writer in-process.\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.trigger_prefill",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S11"
        ],
        "x-touches-entities": [
          "recruit.preboarding",
          "recruit.preboarding_candidate_data",
          "recruit.candidate_pipeline"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Prefill triggered (or explained as a no-op via `skipped_reason`).",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreboardingPrefillResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/preboarding/me": {
      "get": {
        "operationId": "recruit.preboarding.get_by_invite",
        "summary": "Get the caller's own pre-boarding case (candidate)",
        "description": "`REC-S19` — the whole landing in one aggregate read, no fan-out waterfall: this surface opens on the worst devices and connections in the product's population. The projection is candidate-safe and hand-listed, never `SELECT *` — the candidate sees their own checklist, their own offer's role and dates, and nothing else (no recruiter notes, no scorecards, no other candidate, no `verifier_hash`). Never cached by an intermediary (`Cache-Control: no-store`).\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.get_by_invite",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S19"
        ],
        "x-touches-entities": [
          "recruit.preboarding",
          "recruit.preboarding_documents",
          "recruit.preboarding_candidate_data",
          "recruit.preboarding_invite_tokens"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "The caller's own pre-boarding case.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreboardingOwnCase"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/preboarding/me/data/{section}": {
      "put": {
        "operationId": "recruit.preboarding.save_candidate_data",
        "summary": "Autosave one candidate-data form step (candidate)",
        "description": "`REC-S21` — the section (`PERSONAL` or `BANK`) is the save unit, so a dropped connection loses at most one step. The payload is validated against the same shared field allow-list `trigger_prefill` later projects from — a field that cannot be carried to day one cannot be collected here. Saving the `PERSONAL` section's `identity` block requires `consent_given: true` on this call or a prior save that already recorded consent (DPDP) — refused outright rather than silently dropped. Upserts per `(tenant_id, preboarding_id, section)`; a returning candidate is shown back their own prior answers.\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.save_candidate_data",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S21"
        ],
        "x-touches-entities": [
          "recruit.preboarding_candidate_data"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "section",
            "in": "path",
            "required": true,
            "description": "The candidate-data form step being saved.",
            "schema": {
              "$ref": "#/components/schemas/PreboardingDataSection"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreboardingSaveCandidateDataRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Step saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreboardingCandidateDataSaveResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/preboarding/me/documents/upload-url": {
      "post": {
        "operationId": "recruit.preboarding.request_upload_url",
        "summary": "Mint a presigned upload target for one joining document (candidate)",
        "description": "`REC-S20` step 1. The object key is built entirely server-side from the SESSION's own tenant and case (`<tenantId>/preboarding/<caseId>/<docType>/<uuid><ext>`) — never from anything the caller sent — so a candidate cannot steer an upload into another tenant's prefix. `200`, not `201`: an ephemeral mint, no row is persisted at this step (`register`, below, records the upload). Refused once the case has left the candidate-workable states (`DOCS_PENDING`, `DOCS_SUBMITTED`, `CHECKLIST`).\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.request_upload_url",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S20"
        ],
        "x-touches-entities": [
          "recruit.preboarding"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreboardingRequestUploadUrlRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Presigned upload target.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreboardingUploadUrlResult"
                }
              }
            }
          },
          "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"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/preboarding/me/documents": {
      "post": {
        "operationId": "recruit.preboarding.upload_document",
        "summary": "Register an uploaded joining document against the checklist (candidate)",
        "description": "`REC-S20` step 2. Registers the object a prior `request_upload_url` call targeted; the `storage_key` is re-validated against this case's own prefix before it is stored, so a candidate cannot register an arbitrary key they learned elsewhere and cause a privileged HR reader to later fetch it (the confused-deputy shape this surface must not have). Uploads are **replaceable** until submitted and after a return — re-registering a `doc_type` (`replace: true`, the default) supersedes the prior objects in place rather than erroring. Refused once the case has left the candidate-workable states.\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.upload_document",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S20"
        ],
        "x-touches-entities": [
          "recruit.preboarding_documents",
          "recruit.preboarding"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreboardingUploadDocumentRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Document registered.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreboardingDocumentRecord"
                }
              }
            }
          },
          "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"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/preboarding/me/submit": {
      "post": {
        "operationId": "recruit.preboarding.submit_documents",
        "summary": "Submit the case for HR review (candidate)",
        "description": "`REC-S19` submit — the button submits the whole CASE, not a single form: `status DOCS_PENDING → DOCS_SUBMITTED`, stamps `documents_submitted_at` (idempotent — resubmitting an already-`DOCS_SUBMITTED` case is a no-op) and marks every saved `preboarding_candidate_data` section `submitted_at`. HR then verifies per-document on `REC-S11` (`verify_document`). Refused once the case has left the candidate-workable states.\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.submit_documents",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S19"
        ],
        "x-touches-entities": [
          "recruit.preboarding",
          "recruit.preboarding_candidate_data"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Case submitted for review.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreboardingSubmitResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/preboarding/me/checklist-items/complete": {
      "post": {
        "operationId": "recruit.preboarding.complete_checklist_item",
        "summary": "Mark a non-document joining checklist item done (candidate)",
        "description": "Sets the named `checklist_items[]` entry `DONE`; when all required items clear, `status CHECKLIST → READY_TO_ONBOARD` and `checklist_completed_at` is stamped — the gate into onboarding (`REC-F07`). Refused once the case has left the candidate-workable states.\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.complete_checklist_item",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S19"
        ],
        "x-touches-entities": [
          "recruit.preboarding"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreboardingCompleteChecklistItemRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Checklist item completed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreboardingCompleteChecklistResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/public/preboarding/exchange": {
      "post": {
        "operationId": "recruit.preboarding.exchange_invite",
        "summary": "Exchange an invite token for a limited APPLICANT session (unauthenticated)",
        "description": "The ONE unauthenticated route of the Join surface. `POST`, not `GET`, deliberately: the emailed URL is opened as a browser navigation and the web tier turns that page load into this call, so the token never sits in a server access log as a query string and an email-scanner prefetching the link cannot silently mint a session. The token travels in the BODY for the same reason. The verifier is compared in constant time BEFORE any state is read, and the tenant is read OFF THE TOKEN ROW — never the URL — so nothing about the request influences which tenant is used. **Every failure — unknown selector, verifier mismatch, expired, revoked, superseded, or a withdrawn case — answers the SAME indistinguishable `404`** (ADR 0039); a client cannot tell \"that link is dead\" from \"you sent nonsense\" from \"wrong tenant\". Success sets the session cookie (`Set-Cookie`, HttpOnly · Secure · SameSite=Lax) — the response body is deliberately thin (no candidate PII in the one response an unauthenticated caller can provoke) — and every response, success or failure, sets `Cache-Control: no-store`, `X-Robots-Tag: noindex, nofollow` and `Referrer-Policy: no-referrer` so a URL carrying a secret is never cached, indexed, or leaked through a `Referer` header.\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.exchange_invite",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S19"
        ],
        "x-touches-entities": [
          "recruit.preboarding_invite_tokens",
          "recruit.preboarding",
          "xc.identities",
          "xc.sessions"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicPreboardingExchangeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Exchanged; the session cookie is set.",
            "headers": {
              "Set-Cookie": {
                "description": "`<name>=<opaque handle>; Path=/; HttpOnly; SameSite=Lax; Max-Age=<seconds until the token expires>` — plus `Secure` off localhost. A LIMITED APPLICANT session scoped to exactly this one case.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicPreboardingExchangeResult"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/preboarding-cases/{id}/emails": {
      "get": {
        "operationId": "recruit.preboarding.list_emails",
        "summary": "List the onboarding email drafts/messages for a pre-boarding case (HR)",
        "description": "The `xc.mail_messages` rows related to this pre-boarding record (fsd 03 §REC-S11) — the welcome, credentials and ESS-access drafts the `recruit.offer.accepted` consumer mints, plus their send history. `is_sendable` and `blocked_reason` project the send-guard state (not `DRAFT`, or an unresolved `{{placeholder}}` in `body_text`) so the panel can grey the button honestly instead of letting a 409 be the first the caller hears of it. The credentials draft's `body_text` structurally never carries a password — no such template variable exists. Nothing on this surface auto-sends.\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.list_emails",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S11"
        ],
        "x-touches-entities": [
          "recruit.preboarding",
          "xc.mail_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": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Onboarding email drafts/messages for the case.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreboardingEmailList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/preboarding-cases/{id}/emails/{mail_id}/send": {
      "post": {
        "operationId": "recruit.preboarding.send_email",
        "summary": "Release one onboarding email draft into the outbound mail rail (HR)",
        "description": "`DRAFT → QUEUED` (fsd 03 §REC-S11). HR reviews and presses send — nothing about this surface ever auto-sends (decisions register #5). `409` when the row is not `DRAFT` (the double-send guard) and `409` when `body_text` still holds an unresolved `{{placeholder}}`. Emits `xc.email.requested` to wake the jobs-tier dispatcher, exactly like `recruit.offer.send_email`.\n",
        "tags": [
          "recruit",
          "preboarding"
        ],
        "x-token": "recruit.preboarding.send_email",
        "x-realizes-features": [
          "REC-F06"
        ],
        "x-screens": [
          "REC-S11"
        ],
        "x-touches-entities": [
          "recruit.preboarding",
          "xc.mail_messages",
          "xc.outbox"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "xc.email.requested",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "mail_id",
            "in": "path",
            "required": true,
            "description": "The `xc.mail_messages.id` to release — one of the ids returned by `recruit.preboarding.list_emails`.",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "Email queued for delivery.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreboardingEmail"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/onboarding-checklists": {
      "get": {
        "operationId": "recruit.onboarding_checklist.list",
        "summary": "List onboarding checklists",
        "description": "Onboarding / Completed tabs (fsd 03 §REC-S11). Sort whitelist `joining_date`, `status`.",
        "tags": [
          "recruit",
          "onboarding_checklist"
        ],
        "x-token": "recruit.onboarding_checklist.list",
        "x-realizes-features": [
          "REC-F07"
        ],
        "x-screens": [
          "REC-S11"
        ],
        "x-touches-entities": [
          "recruit.onboarding_checklists"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "PENDING",
                "IN_PROGRESS",
                "EMPLOYEE_CREATED",
                "COMPLETED",
                "CANCELLED"
              ]
            }
          },
          {
            "name": "candidate_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of onboarding checklists.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/OnboardingChecklist"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "recruit.onboarding_checklist.create",
        "summary": "Instantiate an onboarding checklist",
        "description": "Opens the day-one onboarding run for a `READY_TO_ONBOARD` pre-boarding case and **copies** the matched `onboarding_templates`/`onboarding_template_tasks` into `onboarding_tasks` (copy-at-create — a later template edit never rewrites a live run, db 04 §6/db-docs 00 §8) (fsd 03 §REC-S11).\n",
        "tags": [
          "recruit",
          "onboarding_checklist"
        ],
        "x-token": "recruit.onboarding_checklist.create",
        "x-realizes-features": [
          "REC-F07"
        ],
        "x-screens": [
          "REC-S11"
        ],
        "x-touches-entities": [
          "recruit.onboarding_checklists",
          "recruit.onboarding_tasks",
          "recruit.onboarding_templates",
          "recruit.preboarding"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "recruit.onboarding_checklist.created",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OnboardingChecklistCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Onboarding checklist instantiated.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OnboardingChecklist"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/onboarding-checklists/{id}": {
      "get": {
        "operationId": "recruit.onboarding_checklist.get",
        "summary": "Get an onboarding checklist",
        "tags": [
          "recruit",
          "onboarding_checklist"
        ],
        "x-token": "recruit.onboarding_checklist.get",
        "x-realizes-features": [
          "REC-F07"
        ],
        "x-screens": [
          "REC-S11"
        ],
        "x-touches-entities": [
          "recruit.onboarding_checklists"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Onboarding checklist.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OnboardingChecklist"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/onboarding-checklists/{id}/complete": {
      "post": {
        "operationId": "recruit.onboarding_checklist.complete",
        "summary": "Complete onboarding — finish the hire",
        "description": "The END of the recruiter's path (#1659). Was `/onboarding-checklists/{id}/provision` under `recruit.onboarding_checklist.provision` until that issue, and it is a RENAME, not an alias: the old operation opened a second, differently-shaped People guided flow and sent the operator to `/people/onboarding/{flow_id}` to finish the hire there, which is the behaviour the owner reported as \"provision access does nothing\". Nothing ever wrote `onboarding_checklists.status='EMPLOYEE_CREATED'`, so the recount could never reach `COMPLETED`, `recruit.onboarding.completed` never fired, and the recruiter's Completed tab was permanently empty.\n\n**What it does now, in ONE transaction.** The same preconditions, verbatim — joining date set, every `is_blocking` task `DONE`/`SKIPPED`, a linked pre-boarding case at `READY_TO_ONBOARD`, a linked offer at `ACCEPTED` — plus the **work email** on the pre-boarding case (#1658), which the ESS identity is built from and which the old path passed as `null` with nothing blocking or prompting. It then opens or enriches the one candidate-linked `people.onboarding_flows` row exactly as before and calls People's own completion seam, which mints the `pay.employee_compensation` row, the `xc.identities` ESS row and the baseline `EMPLOYEE` role and flips `people.employees.status` `JOINING → ACTIVE`. Recruit writes no People table (architecture-docs/03-domain-modules §4).\n\n**Every refusal names the missing fact.** `NO_JOINING_DATE` and `NO_WORK_EMAIL` are `422`s under `/joining_date` and `/work_email`; `BLOCKING_TASKS_OPEN`, `DOCUMENTS_UNVERIFIED` and `OFFER_NOT_ACCEPTED` are `409`s whose `detail` opens with the name. `INSUFFICIENT_AUTHORITY` is a `403`: the completion puts a live salary, a sign-in and a role grant on a person, so the caller must hold `people.employee.create` **and** `pay.employee_compensation.create` (and `people.employee.create_joining` when the hire has no employee record yet). The seeded `RECRUITER` role holds neither completion token — an HR admin finishes a hire (ADR 0024, the #800 security review).\n\n**A non-completion that is not a refusal is a named OUTCOME on the `200`**, in the response's `completion` object, with the flow link: `FLOW_NOT_RESUMABLE` (a colleague walked the flow past `OFFER` by hand — finish it in People), `PLAN_LIMIT_EXCEEDED`, `INCOMPLETE_PREFILL`. `ALREADY_HIRED` is not one of them: a flow already `COMPLETED` means the hire happened elsewhere and the only thing left undone is this row, so it takes the same terminal write and the case closes.\n",
        "tags": [
          "recruit",
          "onboarding_checklist"
        ],
        "x-token": "recruit.onboarding_checklist.complete",
        "x-realizes-features": [
          "REC-F07"
        ],
        "x-screens": [
          "REC-S11"
        ],
        "x-touches-entities": [
          "recruit.onboarding_checklists",
          "people.onboarding_flows",
          "people.employees"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "recruit.onboarding.completed",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "The checklist row, plus the API-only `completion` object stating what the hire actually did. `status` is `EMPLOYEE_CREATED`, or `COMPLETED` when every task was already done.\n",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OnboardingChecklistCompletion"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/onboarding-tasks": {
      "get": {
        "operationId": "recruit.onboarding_task.list",
        "summary": "List onboarding tasks",
        "description": "HR checklist drawer (fsd 03 §REC-S11) and the new joiner's own task list (§REC-S16, filtered to `assigned_to = self`). Sort whitelist `sequence`, `due_date`.\n",
        "tags": [
          "recruit",
          "onboarding_task"
        ],
        "x-token": "recruit.onboarding_task.list",
        "x-realizes-features": [
          "REC-F07"
        ],
        "x-screens": [
          "REC-S11",
          "REC-S16"
        ],
        "x-touches-entities": [
          "recruit.onboarding_tasks"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "name": "checklist_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "PENDING",
                "IN_PROGRESS",
                "DONE",
                "BLOCKED",
                "SKIPPED"
              ]
            }
          },
          {
            "name": "assigned_to",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "DOCUMENTATION",
                "IT_PROVISIONING",
                "ASSET",
                "STATUTORY",
                "ORIENTATION",
                "GENERAL"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of onboarding tasks.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/OnboardingTask"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/onboarding-tasks/{id}": {
      "get": {
        "operationId": "recruit.onboarding_task.get",
        "summary": "Get an onboarding task",
        "tags": [
          "recruit",
          "onboarding_task"
        ],
        "x-token": "recruit.onboarding_task.get",
        "x-realizes-features": [
          "REC-F07"
        ],
        "x-screens": [
          "REC-S11",
          "REC-S16"
        ],
        "x-touches-entities": [
          "recruit.onboarding_tasks"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Onboarding task.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OnboardingTask"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/onboarding-tasks/{id}/status": {
      "post": {
        "operationId": "recruit.onboarding_task.update_status",
        "summary": "Update an onboarding task's status",
        "description": "HR task-completion action (fsd 03 §REC-S11) and the new joiner's self-service \"Mark done\" (§REC-S16). When all `is_blocking` tasks reach `DONE`/`SKIPPED`, the parent checklist may move to `COMPLETED`.\n\n**AST-F02's inbound trigger.** An `ASSET`-category task moving to `IN_PROGRESS` — and only that combination — additionally emits `recruit.onboarding_task.asset_requested`, which the assets-owned consumer turns into the assignment, stamping `assets.asset_assignments.onboarding_task_ref` back to this task (db 04 §6, db 10 §3.2). The task's own `external_ref` is filled by the return hop when the assignment exists; neither ref is settable through this or any other request body, by design.\n",
        "tags": [
          "recruit",
          "onboarding_task"
        ],
        "x-token": "recruit.onboarding_task.update_status",
        "x-realizes-features": [
          "REC-F07"
        ],
        "x-screens": [
          "REC-S11",
          "REC-S16"
        ],
        "x-touches-entities": [
          "recruit.onboarding_tasks",
          "recruit.onboarding_checklists"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "recruit.onboarding_task.asset_requested",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OnboardingTaskStatusRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Task status updated.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OnboardingTask"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/onboarding-templates": {
      "get": {
        "operationId": "recruit.onboarding_template.list",
        "summary": "List onboarding-checklist templates",
        "description": "Template library grid (fsd 03 §REC-S12). Sort whitelist `name`.",
        "tags": [
          "recruit",
          "onboarding_template"
        ],
        "x-token": "recruit.onboarding_template.list",
        "x-realizes-features": [
          "REC-F07"
        ],
        "x-screens": [
          "REC-S12"
        ],
        "x-touches-entities": [
          "recruit.onboarding_templates"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "$ref": "#/components/parameters/SortParam"
          },
          {
            "name": "legal_entity_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "department_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Uuid"
            }
          },
          {
            "name": "employment_type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "FULL_TIME",
                "PART_TIME",
                "CONTRACT",
                "INTERN",
                "TEMP"
              ]
            }
          },
          {
            "name": "is_active",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "is_default",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of templates.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/OnboardingTemplate"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "recruit.onboarding_template.create",
        "summary": "Author an onboarding-checklist template",
        "description": "Saves the template + its ordered task list in one call (fsd 03 §REC-S12, db 04 §6).",
        "tags": [
          "recruit",
          "onboarding_template"
        ],
        "x-token": "recruit.onboarding_template.create",
        "x-realizes-features": [
          "REC-F07"
        ],
        "x-screens": [
          "REC-S12"
        ],
        "x-touches-entities": [
          "recruit.onboarding_templates",
          "recruit.onboarding_template_tasks"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OnboardingTemplateCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Template 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/OnboardingTemplate"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/onboarding-templates/{id}": {
      "get": {
        "operationId": "recruit.onboarding_template.get",
        "summary": "Get an onboarding-checklist template",
        "tags": [
          "recruit",
          "onboarding_template"
        ],
        "x-token": "recruit.onboarding_template.get",
        "x-realizes-features": [
          "REC-F07"
        ],
        "x-screens": [
          "REC-S12"
        ],
        "x-touches-entities": [
          "recruit.onboarding_templates"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Template.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OnboardingTemplate"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "recruit.onboarding_template.update",
        "summary": "Edit an onboarding-checklist template",
        "description": "Edits template metadata and/or replaces its ordered task list. **Non-retroactive** — live onboarding runs keep their already-copied tasks (copy-at-create, db-docs 00 §8) (fsd 03 §REC-S12). Versioned — requires `If-Match`.\n",
        "tags": [
          "recruit",
          "onboarding_template"
        ],
        "x-token": "recruit.onboarding_template.update",
        "x-realizes-features": [
          "REC-F07"
        ],
        "x-screens": [
          "REC-S12"
        ],
        "x-touches-entities": [
          "recruit.onboarding_templates",
          "recruit.onboarding_template_tasks"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [
          {
            "bearerJWT": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OnboardingTemplateUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated template.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OnboardingTemplate"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/public/offer-response/{token}": {
      "get": {
        "operationId": "recruit.offer_response.get",
        "summary": "Open a candidate offer-response link (unauthenticated)",
        "description": "The candidate-safe projection behind an emailed magic link (ADR 0039). Principal: **unauthenticated candidate**, identified solely by the token. Returns the offer summary, the publishable decline reasons, and a per-request, short-lived presigned URL for the offer letter PDF — and no internal identifiers. Answers a uniform `404` for every invalid-token class and `429` + `Retry-After` when the per-IP or per-selector window is exhausted.\n",
        "tags": [
          "recruit",
          "offer"
        ],
        "x-token": "recruit.offer_response.get",
        "x-realizes-features": [
          "REC-F05"
        ],
        "x-screens": [
          "REC-S19"
        ],
        "x-touches-entities": [
          "recruit.offer_response_tokens",
          "recruit.offers",
          "recruit.offer_letters",
          "recruit.refusal_reasons"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The magic-link credential, `{selector}.{verifier}` — a 22-character base64url selector, a dot, and a 43-character base64url verifier. Treated as ONE opaque parameter and shape-checked in the handler, so a malformed token and a wrong one produce the identical 404 (a route-level pattern would answer from the router for one and the handler for the other, which is a distinguishable pair).\n",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{22}\\.[A-Za-z0-9_-]{43}$"
            }
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "The candidate-safe offer projection.",
            "headers": {
              "Cache-Control": {
                "description": "Always `no-store` — the URL carries a live credential.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Robots-Tag": {
                "description": "Always `noindex, nofollow`.",
                "schema": {
                  "type": "string"
                }
              },
              "Referrer-Policy": {
                "description": "Always `no-referrer`.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicOfferResponseView"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "recruit.offer_response.submit",
        "summary": "Accept or decline an offer through the candidate link (unauthenticated)",
        "description": "Records the candidate's own decision (ADR 0039), attributed `CANDIDATE_LINK` on `recruit.offers.responded_via` and audited with `actor_type = CANDIDATE`. The token is SINGLE-USE: the claim is an atomic conditional update, so exactly one of any number of concurrent submissions succeeds and the rest receive the uniform `404`.\n\n`ACCEPTED` requires the signature ceremony — a typed `signature_name` and `consent_accepted: true` (issue #1486) — and opens the pre-boarding case, exactly as the HR `recruit.offer.record_response` door does. The SENT letter becomes `SIGNED` carrying an APPENDED acknowledgement page: the letter's exact bytes as a PDF incremental update, plus one page naming the typed name, the acceptance timestamp, the keyed source-IP hash and the letter's own `content_hash`, stored under its own `signed_storage_key` with its own `signed_content_hash`. `storage_key` / `content_hash` are never overwritten, so the letter as sent stays addressable and verifiable beside the stamped copy, and `esign_request_id` stays NULL for a future `DOC-F02` ceremony. If the artifact cannot be fetched, parsed or stored, the acceptance still stands: the letter is marked `SIGNED` from its own key and hash and the reason is recorded on the audit row, never raised at the candidate.\n\nA decline reason, when supplied, must be a `recruit.refusal_reasons` code published via `is_candidate_visible`.\n",
        "tags": [
          "recruit",
          "offer"
        ],
        "x-token": "recruit.offer_response.submit",
        "x-realizes-features": [
          "REC-F05"
        ],
        "x-screens": [
          "REC-S19"
        ],
        "x-touches-entities": [
          "recruit.offer_response_tokens",
          "recruit.offers",
          "recruit.offer_letters",
          "recruit.preboarding"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "recruit.offer.accepted",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "recruit",
        "x-provisional": null,
        "security": [],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The magic-link credential, `{selector}.{verifier}` — a 22-character base64url selector, a dot, and a 43-character base64url verifier. Treated as ONE opaque parameter and shape-checked in the handler, so a malformed token and a wrong one produce the identical 404 (a route-level pattern would answer from the router for one and the handler for the other, which is a distinguishable pair).\n",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{22}\\.[A-Za-z0-9_-]{43}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicOfferResponseRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The decision was recorded; the link is now spent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicOfferResponseResult"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Uuid": {
        "type": "string",
        "format": "uuid",
        "description": "UUIDv7 surrogate primary key (db-docs/00 §3). Never the business identifier."
      },
      "DateOnly": {
        "type": "string",
        "format": "date",
        "description": "Calendar-only value (pay-period date, leave date, due date)."
      },
      "Timestamp": {
        "type": "string",
        "format": "date-time",
        "description": "timestamptz, serialized UTC ISO-8601. Presentation timezone is a client concern."
      },
      "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"
              }
            ]
          }
        }
      },
      "EmploymentType": {
        "type": "string",
        "enum": [
          "FULL_TIME",
          "PART_TIME",
          "CONTRACT",
          "INTERN",
          "TEMP"
        ],
        "description": "db 04 §1 `recruit.employment_type` — shared by `requisitions`, `job_openings`, `onboarding_templates`."
      },
      "RequisitionPriority": {
        "type": "string",
        "enum": [
          "LOW",
          "MEDIUM",
          "HIGH",
          "URGENT"
        ],
        "description": "db 04 §1 `requisitions.priority`."
      },
      "RequisitionStatus": {
        "type": "string",
        "enum": [
          "DRAFT",
          "PENDING_APPROVAL",
          "APPROVED",
          "REJECTED",
          "ON_HOLD",
          "OPEN",
          "FILLED",
          "CANCELLED",
          "CLOSED"
        ],
        "description": "db 04 §1 `requisitions.status` lifecycle."
      },
      "JobOpeningWorkMode": {
        "type": "string",
        "enum": [
          "ONSITE",
          "HYBRID",
          "REMOTE"
        ],
        "description": "db 04 §1 `job_openings.work_mode`."
      },
      "JobOpeningStatus": {
        "type": "string",
        "enum": [
          "DRAFT",
          "OPEN",
          "ON_HOLD",
          "FILLED",
          "CLOSED",
          "CANCELLED"
        ],
        "description": "db 04 §1 `job_openings.status` lifecycle."
      },
      "CareersPostingChannel": {
        "type": "string",
        "enum": [
          "CAREERS_PAGE",
          "LINKEDIN",
          "INDEED",
          "NAUKRI",
          "BAYT",
          "OTHER_BOARD"
        ],
        "description": "db 04 §2 `careers_postings.channel`. `CAREERS_PAGE` is the one AUTOMATIC channel — GroundIT publishes it. `LINKEDIN`/`INDEED`/`NAUKRI`/`BAYT`/`OTHER_BOARD` are MANUAL tracking rows for a posting the recruiter made by hand (#1495): there is no outbound job-board integration and none is planned. `NAUKRI` is the India-market board, `BAYT` the KSA-market board (the market comes from `org.legal_entities.market`); `OTHER_BOARD` carries the long tail, named in `external_ref`.\n"
      },
      "CareersPostingStatus": {
        "type": "string",
        "enum": [
          "DRAFT",
          "PUBLISHED",
          "SYNDICATION_PENDING",
          "UNPUBLISHED",
          "EXPIRED",
          "FAILED"
        ],
        "description": "db 04 §2 `careers_postings.status` lifecycle."
      },
      "CandidateSource": {
        "type": "string",
        "enum": [
          "CAREERS_PAGE",
          "REFERRAL",
          "JOB_BOARD",
          "AGENCY",
          "DIRECT",
          "WALK_IN",
          "INTERNAL"
        ],
        "description": "db 04 §3 `candidates.source`."
      },
      "CandidatePipelineStage": {
        "type": "string",
        "enum": [
          "SOURCED",
          "SCREENED",
          "INTERVIEW",
          "OFFER",
          "HIRED",
          "REJECTED"
        ],
        "description": "db 04 §3 `candidate_pipeline.stage` (`recruit.candidate_stage`) — the Kanban columns."
      },
      "CandidatePipelineRejectionReason": {
        "type": "string",
        "enum": [
          "SKILLS_GAP",
          "COMPENSATION",
          "LOCATION",
          "WITHDREW",
          "POSITION_CLOSED",
          "OTHER"
        ],
        "description": "db 04 §3 `candidate_pipeline.rejection_reason`."
      },
      "InterviewMode": {
        "type": "string",
        "enum": [
          "ONSITE",
          "VIRTUAL",
          "PHONE"
        ],
        "description": "db 04 §4 `interviews.mode`."
      },
      "InterviewStatus": {
        "type": "string",
        "enum": [
          "SCHEDULED",
          "RESCHEDULED",
          "IN_PROGRESS",
          "COMPLETED",
          "NO_SHOW",
          "CANCELLED"
        ],
        "description": "db 04 §4 `interviews.status` lifecycle."
      },
      "InterviewPanelRole": {
        "type": "string",
        "enum": [
          "INTERVIEWER",
          "PANEL_LEAD",
          "OBSERVER"
        ],
        "description": "db 04 §4 `interviews.panel[].role`."
      },
      "ScorecardRecommendation": {
        "type": "string",
        "enum": [
          "STRONG_HIRE",
          "HIRE",
          "NO_HIRE",
          "STRONG_NO_HIRE"
        ],
        "description": "db 04 §4 `recruit.scorecard_recommendation` — `interview_scorecards.recommendation` and the rolled-up `interviews.overall_recommendation`."
      },
      "OfferStatus": {
        "type": "string",
        "enum": [
          "DRAFT",
          "PENDING_APPROVAL",
          "APPROVED",
          "REJECTED",
          "SENT",
          "ACCEPTED",
          "DECLINED",
          "REVOKED",
          "EXPIRED"
        ],
        "description": "db 04 §5 `offers.status` lifecycle."
      },
      "OfferLetterStatus": {
        "type": "string",
        "enum": [
          "GENERATING",
          "GENERATED",
          "SENT",
          "SIGNED",
          "VOID"
        ],
        "description": "db 04 §5 `offer_letters.status` lifecycle. `GENERATING` (added migration `0118`, issue #866) — the render is enqueued and running asynchronously (ADR 0023); `file` is `null` until the letter leaves this state, either to `GENERATED` (rendered) or `VOID` (the render permanently failed — see `render_error`).\n"
      },
      "PreboardingStatus": {
        "type": "string",
        "enum": [
          "OFFER_ACCEPTED",
          "DOCS_PENDING",
          "DOCS_SUBMITTED",
          "CHECKLIST",
          "READY_TO_ONBOARD",
          "WITHDRAWN"
        ],
        "description": "db 04 §6 `preboarding.status` lifecycle."
      },
      "PreboardingDocumentStatus": {
        "type": "string",
        "enum": [
          "PENDING",
          "UPLOADED",
          "VERIFIED",
          "REJECTED"
        ],
        "description": "db 04 §6 `preboarding.required_documents[].status`."
      },
      "PreboardingChecklistItemStatus": {
        "type": "string",
        "enum": [
          "PENDING",
          "DONE",
          "SKIPPED"
        ],
        "description": "db 04 §6 `preboarding.checklist_items[].status` (non-document joining tasks)."
      },
      "OnboardingChecklistStatus": {
        "type": "string",
        "enum": [
          "PENDING",
          "IN_PROGRESS",
          "EMPLOYEE_CREATED",
          "COMPLETED",
          "CANCELLED"
        ],
        "description": "db 04 §6 `onboarding_checklists.status` lifecycle."
      },
      "OnboardingReadiness": {
        "type": "string",
        "enum": [
          "DOCS_PENDING",
          "CHECKLIST",
          "READY"
        ],
        "description": "Derived completion-gate state; never stored. `DOCS_PENDING` means the linked preboarding case is not ready, `CHECKLIST` means joining date or a blocking task remains, and `READY` means Complete onboarding may finish the hire."
      },
      "OnboardingTaskCategory": {
        "type": "string",
        "enum": [
          "DOCUMENTATION",
          "IT_PROVISIONING",
          "ASSET",
          "STATUTORY",
          "ORIENTATION",
          "GENERAL"
        ],
        "description": "db 04 §6 `onboarding_tasks.category` (mirrored by `onboarding_template_tasks.category`)."
      },
      "OnboardingTaskStatus": {
        "type": "string",
        "enum": [
          "PENDING",
          "IN_PROGRESS",
          "DONE",
          "BLOCKED",
          "SKIPPED"
        ],
        "description": "db 04 §6 `onboarding_tasks.status` lifecycle."
      },
      "RecruitDashboardSummary": {
        "type": "object",
        "description": "Read-only projection (fsd 03 §REC-S01) — realizes `XC-F09`, not a `recruit`-written table. Hiring managers see counts scoped to their own requisitions (`XC-F04`).\n",
        "readOnly": true,
        "properties": {
          "open_requisitions": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer",
                "description": "count where status IN ('OPEN','APPROVED')"
              },
              "urgent": {
                "type": "integer",
                "description": "sub-count where priority = 'URGENT'"
              }
            }
          },
          "pending_offers": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer",
                "description": "count where status IN ('PENDING_APPROVAL','SENT') — an offer awaiting a decision, whether the internal four-eyes approval (`REC-S09`) or the candidate's response. Widened from `SENT`-only so the tile cannot contradict the offers screen, which labels `PENDING_APPROVAL` \"pending\".\n"
              }
            }
          },
          "onboarding_pipeline": {
            "type": "object",
            "properties": {
              "preboarding_in_progress": {
                "type": "integer",
                "description": "count of recruit.preboarding where status <> 'WITHDRAWN' (the REC-S11 pre-boarding tab)"
              },
              "onboarding_in_progress": {
                "type": "integer",
                "description": "count of recruit.onboarding_checklists where status IN ('PENDING','IN_PROGRESS') (the REC-S11 onboarding tab)"
              }
            }
          },
          "candidate_funnel": {
            "type": "array",
            "description": "Count by `candidate_pipeline.stage`, `SOURCED`→`HIRED`; each segment deep-links to `REC-S06`.",
            "items": {
              "type": "object",
              "required": [
                "candidate_id",
                "full_name",
                "role_title",
                "joining_date",
                "readiness",
                "flow_id"
              ],
              "properties": {
                "stage": {
                  "$ref": "#/components/schemas/CandidatePipelineStage"
                },
                "count": {
                  "type": "integer"
                }
              }
            }
          },
          "joining_this_month": {
            "type": "array",
            "description": "`recruit.onboarding_checklists` whose `joining_date` falls in the current month and whose status is not `CANCELLED`; name/role resolved via `recruit.candidates` and its opening.\n",
            "items": {
              "type": "object",
              "properties": {
                "candidate_id": {
                  "$ref": "#/components/schemas/Uuid"
                },
                "full_name": {
                  "type": "string"
                },
                "role_title": {
                  "type": "string",
                  "nullable": true,
                  "description": "the candidate's opening title (`en`); null when no opening is linked"
                },
                "joining_date": {
                  "$ref": "#/components/schemas/DateOnly"
                },
                "readiness": {
                  "$ref": "#/components/schemas/OnboardingReadiness"
                },
                "flow_id": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/Uuid"
                    },
                    {
                      "type": "null"
                    }
                  ],
                  "description": "Current or latest candidate-linked `people.onboarding_flows` id; null until Provision opens the guided flow."
                }
              }
            }
          }
        }
      },
      "RecruitApprovalAffordance": {
        "type": "object",
        "readOnly": true,
        "description": "The approval band and its buttons, computed FOR THE CALLER (`#1489`, consumed by `#1490`/`#1485`).\n\nRecruit mints no approve/reject operation of its own — the checker acts in the unified approvals inbox (ADR 0036) — and that inbox's personal lens lists only rows whose `current_approver_id`/`effective_approver_id` is the caller. Since `#1489` made the decision ROLE-eligible, an HR admin or recruiter who may decide a requisition does not see it in their own inbox at all, so the affordance has to travel with the record the page is already showing. Without this block the relaxation would be true at the API and invisible in the product.\n\n`can_decide` is exactly the predicate `POST /approval-inbox/{id}/decide` and `xc.record_approval_decision` apply: an open envelope exists, the caller is not the maker, and the caller is either routed the row or role-eligible for its request type. A button rendered from it cannot 404, which is the defect this replaces.\n\n**The whole block is `null` unless the SOURCE record is `PENDING_APPROVAL`,** and the source status is the authority rather than the envelope's. The two close in separate transactions — the owning module's transition commits first and XC stamps the envelope after, with `xc-approval-decision-reconciler` closing the window if that second write is lost — so there is always an interval, and on a lost stamp an indefinite one, in which the record reads `APPROVED` while its envelope still reads `PENDING`. Offering a decision on an already-decided record is the worse error in both directions: the button `409`s, and the band tells the reader something untrue about the record in front of them. `can_override` is the separate `#1415` route (`POST /approval-inbox/{id}/override`, `xc.approval_inbox.decide_override`, owner/tenant_admin) and is likewise four-eyes-bounded.\n\n`eligible_roles` is DISPLAY COPY — \"Awaiting approval · any of HR admin, recruiter…\" — and never a client-side permission test: `recruit-access.ts` is token-only by design and role names are never consulted there. The two booleans are the only things a client may branch on.\n",
        "required": [
          "inbox_id",
          "status",
          "version",
          "eligible_roles",
          "routed_approver_id",
          "can_decide",
          "can_override",
          "is_maker"
        ],
        "additionalProperties": false,
        "properties": {
          "inbox_id": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              }
            ],
            "description": "`xc.approval_inbox.id` — the row a decision is posted against."
          },
          "status": {
            "type": "string",
            "description": "The envelope status; `PENDING` while a band is shown."
          },
          "version": {
            "type": "integer",
            "minimum": 0,
            "description": "The envelope's optimistic-concurrency counter, to be sent as `If-Match: \"v<version>\"` on `POST /approval-inbox/{id}/decide` or `/override` — both require it unconditionally. Published here because a role-eligible decider who is NOT routed the row has no other read that carries it: `GET /approval-inbox/{id}` is SELF-scoped on the approver/requester lens, and the admin lens needs `xc.approval_inbox.list_admin`. Without it the block would offer a button whose request answers `428`."
          },
          "eligible_roles": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Lower-case `admin.roles.role_key`s any of whose holders may decide this request type, sorted: the owner-decision floor (`hr_admin`, `recruiter`, `tenant_admin`, `owner`) unioned with every `ROLE:` key the tenant's published rule names. Empty for a request type that is not role-eligible."
          },
          "routed_approver_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              },
              {
                "type": "null"
              }
            ],
            "description": "The delegation-resolved approver the envelope is routed to (`effective_approver_id`, falling back to `current_approver_id`). `null` on an unrouted envelope — which is a fact worth showing (\"awaiting approval, routed to nobody\"), not an error."
          },
          "can_decide": {
            "type": "boolean",
            "description": "Open envelope · not the maker · routed or role-eligible."
          },
          "can_override": {
            "type": "boolean",
            "description": "Holds `xc.approval_inbox.decide_override` · not the maker."
          },
          "is_maker": {
            "type": "boolean",
            "description": "The caller is the record’s `submitted_by`."
          }
        }
      },
      "Requisition": {
        "type": "object",
        "description": "db 04 §1 `recruit.requisitions` — headcount request routed through maker-checker approval.",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "requisition_no",
              "title",
              "legal_entity_id",
              "employment_type",
              "headcount",
              "priority",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "requisition_no": {
                "$ref": "#/components/schemas/BusinessNo"
              },
              "title": {
                "type": "string"
              },
              "legal_entity_id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "department_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "grade_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "work_location_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "employment_type": {
                "$ref": "#/components/schemas/EmploymentType"
              },
              "headcount": {
                "type": "integer",
                "minimum": 1
              },
              "headcount_filled": {
                "type": "integer",
                "minimum": 0
              },
              "budget": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Money"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "maps to `budget_amount`/`currency_code` — the approved annual CTC ceiling."
              },
              "hiring_manager_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→people.employees"
              },
              "recruiter_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→people.employees"
              },
              "priority": {
                "$ref": "#/components/schemas/RequisitionPriority"
              },
              "status": {
                "$ref": "#/components/schemas/RequisitionStatus"
              },
              "justification": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "submitted_by": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "maker (ref→people.employees)."
              },
              "approved_by": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "checker (ref→people.employees)."
              },
              "approved_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "target_start_date": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DateOnly"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "approval": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/RecruitApprovalAffordance"
                  },
                  {
                    "type": "null"
                  }
                ],
                "readOnly": true,
                "description": "READ-ONLY, and present ONLY on the single-record read (`GET /requisitions/{id}`; absent from the list and from every write response). `null` unless the record is `PENDING_APPROVAL` **and** an open envelope exists for it — see the schema's own note on why the source status, not the envelope's, decides that."
              },
              "content_locales": {
                "type": [
                  "array",
                  "null"
                ],
                "items": {
                  "type": "string"
                },
                "readOnly": true,
                "description": "READ-ONLY, reads only (`GET /requisitions`, `GET /requisitions/{id}`; absent from write responses). The languages this requisition's `legal_entity_id` publishes recruitment content in — `rules.locales` of the entity's effective compliance pack on today's civil date (org §compliance packs). `null` when no pack binding covers today: unknown policy, not \"one language\". Consumed by the openings publish-confirm locale warning (#1494) so a warning about a missing Arabic body fires only where the entity actually publishes Arabic."
              },
              "legal_entity_market": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "IN",
                  "KSA",
                  null
                ],
                "readOnly": true,
                "description": "READ-ONLY, reads only (`GET /requisitions`, `GET /requisitions/{id}`; absent from write responses). `org.legal_entities.market` for this requisition's `legal_entity_id` — the jurisdiction the employer recruits in. Consumed by the openings Channels tab to pick the job boards this employer actually posts on (#1495), which the web view-model previously guessed from the reader's UI language. `null` when the entity answers nothing today: unknown states nothing rather than guessing a market."
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMeta"
          }
        ]
      },
      "RequisitionCreateRequest": {
        "type": "object",
        "required": [
          "title",
          "legal_entity_id",
          "employment_type",
          "headcount",
          "priority"
        ],
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 2,
            "maxLength": 150
          },
          "legal_entity_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "department_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "grade_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "work_location_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "employment_type": {
            "$ref": "#/components/schemas/EmploymentType"
          },
          "headcount": {
            "type": "integer",
            "minimum": 1
          },
          "budget": {
            "$ref": "#/components/schemas/Money"
          },
          "priority": {
            "$ref": "#/components/schemas/RequisitionPriority"
          },
          "hiring_manager_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "recruiter_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "target_start_date": {
            "$ref": "#/components/schemas/DateOnly"
          },
          "justification": {
            "type": "string"
          }
        }
      },
      "RequisitionUpdateRequest": {
        "type": "object",
        "description": "Editable while `status = DRAFT` (fsd 03 §REC-S02).",
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 2,
            "maxLength": 150
          },
          "department_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "grade_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "work_location_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "employment_type": {
            "$ref": "#/components/schemas/EmploymentType"
          },
          "headcount": {
            "type": "integer",
            "minimum": 1
          },
          "budget": {
            "$ref": "#/components/schemas/Money"
          },
          "priority": {
            "$ref": "#/components/schemas/RequisitionPriority"
          },
          "hiring_manager_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "recruiter_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "target_start_date": {
            "$ref": "#/components/schemas/DateOnly"
          },
          "justification": {
            "type": "string"
          }
        }
      },
      "JobOpening": {
        "type": "object",
        "description": "db 04 §1 `recruit.job_openings` — a published, fillable position derived from an approved requisition.",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "requisition_id",
              "title",
              "employment_type",
              "work_mode",
              "openings_count",
              "status",
              "is_internal"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "requisition_id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "title": {
                "$ref": "#/components/schemas/LocalizedText"
              },
              "description": {
                "$ref": "#/components/schemas/LocalizedText"
              },
              "slug": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "department_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "denormalized from the requisition for display."
              },
              "work_location_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "employment_type": {
                "$ref": "#/components/schemas/EmploymentType"
              },
              "work_mode": {
                "$ref": "#/components/schemas/JobOpeningWorkMode"
              },
              "openings_count": {
                "type": "integer",
                "minimum": 1
              },
              "status": {
                "$ref": "#/components/schemas/JobOpeningStatus"
              },
              "is_internal": {
                "type": "boolean"
              },
              "published_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "closes_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMeta"
          }
        ]
      },
      "JobOpeningCreateRequest": {
        "type": "object",
        "required": [
          "requisition_id",
          "title",
          "work_mode",
          "openings_count"
        ],
        "additionalProperties": false,
        "description": "Converts an `APPROVED`/`OPEN` requisition into a published opening (fsd 03 §REC-S02 \"Convert to opening(s)\", §REC-S03 \"+ Publish opening\").",
        "properties": {
          "requisition_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "title": {
            "$ref": "#/components/schemas/LocalizedText"
          },
          "description": {
            "$ref": "#/components/schemas/LocalizedText"
          },
          "slug": {
            "type": "string",
            "description": "URL-safe; tenant-unique."
          },
          "work_mode": {
            "$ref": "#/components/schemas/JobOpeningWorkMode"
          },
          "openings_count": {
            "type": "integer",
            "minimum": 1
          },
          "is_internal": {
            "type": "boolean",
            "default": false
          },
          "closes_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "JobOpeningUpdateRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "title": {
            "$ref": "#/components/schemas/LocalizedText"
          },
          "description": {
            "$ref": "#/components/schemas/LocalizedText"
          },
          "slug": {
            "type": "string"
          },
          "work_mode": {
            "$ref": "#/components/schemas/JobOpeningWorkMode"
          },
          "openings_count": {
            "type": "integer",
            "minimum": 1
          },
          "is_internal": {
            "type": "boolean"
          },
          "closes_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "CareersPosting": {
        "type": "object",
        "description": "db 04 §2 `recruit.careers_postings` — a channel publication instance of an opening.",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "job_opening_id",
              "channel",
              "status",
              "apply_count"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "job_opening_id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "channel": {
                "$ref": "#/components/schemas/CareersPostingChannel"
              },
              "status": {
                "$ref": "#/components/schemas/CareersPostingStatus"
              },
              "external_ref": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "syndicated posting id returned by the board (channel <> CAREERS_PAGE)."
              },
              "external_url": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri"
              },
              "content_snapshot": {
                "type": "object",
                "description": "Rendered locale-keyed posting content frozen at publish (db 04 §2 JSONB shape); schemaless, not queried.",
                "properties": {
                  "title": {
                    "$ref": "#/components/schemas/LocalizedText"
                  },
                  "description": {
                    "$ref": "#/components/schemas/LocalizedText"
                  },
                  "location": {
                    "type": "string"
                  },
                  "employment_type": {
                    "type": "string"
                  },
                  "rendered_html_ref": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              },
              "apply_count": {
                "type": "integer",
                "minimum": 0
              },
              "published_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "expires_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "last_synced_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMeta"
          }
        ]
      },
      "CareersPostingCreateRequest": {
        "type": "object",
        "required": [
          "channel"
        ],
        "additionalProperties": false,
        "description": "`CAREERS_PAGE` takes `channel` alone — the other three fields are refused on it (`422`), because GroundIT publishes that channel and owns its link, snapshot and date. Every other channel REQUIRES `external_url` (#1495): a board row that names no link records nothing.\n",
        "properties": {
          "channel": {
            "$ref": "#/components/schemas/CareersPostingChannel"
          },
          "external_url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "HTTP(S) link to the posting on that board. Required for every non-`CAREERS_PAGE` channel."
          },
          "external_ref": {
            "type": "string",
            "maxLength": 200,
            "description": "The board's own posting id, or — for `OTHER_BOARD` — the NAME of the board, which is how the long tail is recorded without a per-tenant board registry.\n"
          },
          "published_at": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              }
            ],
            "description": "When the job actually went up on that board. Optional (defaults to now) and BACKDATEABLE, since a manual record is always made after the fact; a future timestamp is refused.\n"
          }
        }
      },
      "CareersPostingUpdateRequest": {
        "type": "object",
        "minProperties": 1,
        "additionalProperties": false,
        "description": "Correction of a hand-recorded posting (#1495). Every field is the recruiter's own; `CAREERS_PAGE` postings take none of them and answer `422`. Blanking `external_url` is refused — an external row with no link is the empty row the create path exists to prevent.\n",
        "properties": {
          "external_url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048
          },
          "external_ref": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 200
          },
          "published_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "CareersListing": {
        "type": "object",
        "description": "Public, unauthenticated projection over a `PUBLISHED`, non-`is_internal` opening's frozen `careers_postings.content_snapshot` (fsd 03 §REC-S04/§REC-S05). Own read-model, not the write model.\n",
        "readOnly": true,
        "properties": {
          "id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "posting_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "title": {
            "$ref": "#/components/schemas/LocalizedText"
          },
          "description": {
            "$ref": "#/components/schemas/LocalizedText"
          },
          "slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "work_mode": {
            "$ref": "#/components/schemas/JobOpeningWorkMode"
          },
          "employment_type": {
            "$ref": "#/components/schemas/EmploymentType"
          },
          "department_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "ref→org.departments, by projection."
          },
          "work_location_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "ref→org.work_locations, by projection."
          },
          "published_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "CandidateApplicationRequest": {
        "type": "object",
        "required": [
          "full_name",
          "email",
          "resume_storage_key"
        ],
        "additionalProperties": false,
        "description": "fsd 03 §REC-S05. Résumé bytes are never posted here — the client uploads to a presigned URL first (`XC-F07`) and references the resulting key/hash.\n",
        "properties": {
          "full_name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "phone": {
            "type": "string"
          },
          "profile_urls": {
            "type": "array",
            "maxItems": 10,
            "description": "HTTP(S) public profile URLs; normalized for person-identity matching.",
            "items": {
              "type": "string",
              "format": "uri",
              "maxLength": 2048
            }
          },
          "resume_storage_key": {
            "type": "string"
          },
          "resume_content_hash": {
            "type": "string",
            "description": "SHA-256 of the résumé (dedupe/integrity)."
          },
          "current_employer": {
            "type": "string"
          },
          "expected_ctc": {
            "$ref": "#/components/schemas/Money"
          },
          "notice_period_days": {
            "type": "integer",
            "minimum": 0
          },
          "other_documents": {
            "type": "array",
            "description": "Non-résumé attachments — object-storage refs (`ref→docs`/`XC-F07`), not a `candidates` column (fsd 03 §REC-S05 *gaps* 9).",
            "items": {
              "type": "object",
              "properties": {
                "storage_key": {
                  "type": "string"
                },
                "file_name": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "CandidateApplicationResult": {
        "type": "object",
        "description": "fsd 03 §REC-S05 success — the created applicant identity and pipeline entry point.",
        "readOnly": true,
        "required": [
          "candidate_id",
          "candidate_no",
          "pipeline_card_id"
        ],
        "properties": {
          "candidate_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "candidate_no": {
            "$ref": "#/components/schemas/BusinessNo"
          },
          "pipeline_card_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "applicant_user_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              },
              {
                "type": "null"
              }
            ],
            "description": "ref→xc.identities — the pre-hire applicant login (XC-F03)."
          }
        }
      },
      "Candidate": {
        "type": "object",
        "description": "db 04 §3 `recruit.candidates` — an applicant identity; **not** a `people` employee until hire.",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "candidate_no",
              "full_name",
              "source"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "candidate_no": {
                "$ref": "#/components/schemas/BusinessNo"
              },
              "job_opening_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "current/primary opening (latest application) convenience pointer; null for talent-pool-only."
              },
              "posting_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "full_name": {
                "type": "string"
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "phone": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_urls": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uri"
                },
                "description": "Canonicalized public profile URLs retained on the person record."
              },
              "applicant_user_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→xc.identities — pre-hire login (XC-F03)."
              },
              "source": {
                "$ref": "#/components/schemas/CandidateSource"
              },
              "resume": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/FileDownload"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Presigned résumé download (XC-F07); bytes never in Postgres."
              },
              "resume_unreadable": {
                "type": "boolean",
                "description": "Optional degradation marker, emitted as `true` only when this candidate has a stored résumé key but its presigned download cannot be minted. `resume` is null; sibling candidates remain readable."
              },
              "current_employer": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "expected_ctc": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Money"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "notice_period_days": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "referred_by": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→people.employees — referring employee (source = REFERRAL)."
              },
              "linked_employee_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→people.employees — set only after hire (REC-F07); null pre-hire."
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMeta"
          }
        ]
      },
      "CandidateCreateRequest": {
        "type": "object",
        "required": [
          "full_name",
          "source"
        ],
        "additionalProperties": false,
        "description": "Internal sourcing door (`recruit.candidate.create`). Résumé bytes are never posted here — the client uploads to a presigned URL first (`XC-F07`) and references the resulting key/hash. `referred_by` is required when `source = REFERRAL` (db 04 §3 check constraint).\n",
        "properties": {
          "full_name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 300
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "phone": {
            "type": "string"
          },
          "profile_urls": {
            "type": "array",
            "maxItems": 10,
            "description": "HTTP(S) public profile URLs. Scheme/www/tracking-query/fragment/trailing-slash differences do not create a second person identity; identity-bearing query values stay.\n",
            "items": {
              "type": "string",
              "format": "uri",
              "maxLength": 2048
            }
          },
          "source": {
            "$ref": "#/components/schemas/CandidateSource"
          },
          "job_opening_id": {
            "$ref": "#/components/schemas/Uuid",
            "description": "Opens the `SOURCED` pipeline card against this opening."
          },
          "resume_storage_key": {
            "type": "string",
            "maxLength": 1024,
            "description": "Tenant-prefixed, traversal-safe object key issued by XC-F07; foreign prefixes, `..`, and backslashes are rejected with `422`."
          },
          "resume_content_hash": {
            "type": "string",
            "description": "SHA-256 of the résumé (dedupe/integrity)."
          },
          "current_employer": {
            "type": "string"
          },
          "expected_ctc": {
            "$ref": "#/components/schemas/Money"
          },
          "notice_period_days": {
            "type": "integer",
            "minimum": 0
          },
          "referred_by": {
            "$ref": "#/components/schemas/Uuid",
            "description": "ref→people.employees — required when source = REFERRAL."
          }
        }
      },
      "CandidateInboundIntakeRequest": {
        "type": "object",
        "required": [
          "recipient",
          "from",
          "subject"
        ],
        "additionalProperties": false,
        "description": "Normalized envelope supplied by the authenticated mail adapter. `text_body` is bounded and parsed in memory; neither it nor `subject` is persisted. Attachments use the existing XC-F07 object upload path, so only the validated résumé key/hash crosses this operation.\n",
        "properties": {
          "recipient": {
            "type": "string",
            "maxLength": 500,
            "description": "Source alias, for example `jobs+linkedin@tenant.inbound.example`."
          },
          "from": {
            "type": "string",
            "maxLength": 500,
            "description": "RFC-5322-like sender mailbox; platform noreply addresses are excluded from candidate contacts."
          },
          "subject": {
            "type": "string",
            "maxLength": 1000
          },
          "text_body": {
            "type": "string",
            "maxLength": 200000
          },
          "job_opening_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "resume_storage_key": {
            "type": "string",
            "maxLength": 1024
          },
          "resume_content_hash": {
            "type": "string",
            "pattern": "^[a-fA-F0-9]{64}$"
          }
        }
      },
      "RefusalReason": {
        "type": "object",
        "required": [
          "id",
          "code",
          "labels",
          "sequence",
          "is_active",
          "version"
        ],
        "properties": {
          "id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "code": {
            "type": "string",
            "pattern": "^[A-Z][A-Z0-9_]{1,63}$"
          },
          "labels": {
            "type": "object",
            "minProperties": 1,
            "additionalProperties": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          "sequence": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1000000
          },
          "mail_template_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              },
              {
                "type": "null"
              }
            ]
          },
          "is_active": {
            "type": "boolean"
          },
          "version": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "RefusalReasonCreateRequest": {
        "type": "object",
        "required": [
          "code",
          "labels"
        ],
        "additionalProperties": false,
        "properties": {
          "code": {
            "type": "string",
            "pattern": "^[A-Z][A-Z0-9_]{1,63}$"
          },
          "labels": {
            "type": "object",
            "minProperties": 1,
            "additionalProperties": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          "sequence": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1000000,
            "default": 0
          },
          "mail_template_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "is_active": {
            "type": "boolean",
            "default": true
          }
        }
      },
      "RefusalReasonUpdateRequest": {
        "type": "object",
        "minProperties": 1,
        "additionalProperties": false,
        "properties": {
          "labels": {
            "type": "object",
            "minProperties": 1,
            "additionalProperties": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          "sequence": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1000000
          },
          "mail_template_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              },
              {
                "type": "null"
              }
            ]
          },
          "is_active": {
            "type": "boolean"
          }
        }
      },
      "RefusalPreviewRequest": {
        "type": "object",
        "required": [
          "card_id",
          "reason_id"
        ],
        "additionalProperties": false,
        "properties": {
          "card_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "reason_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "locale": {
            "type": "string",
            "default": "en"
          },
          "note": {
            "type": "string",
            "maxLength": 4000
          }
        }
      },
      "RefusalPreview": {
        "type": "object",
        "required": [
          "available",
          "recipient",
          "template_id",
          "locale",
          "rendered_body"
        ],
        "properties": {
          "available": {
            "type": "boolean"
          },
          "recipient": {
            "type": [
              "string",
              "null"
            ],
            "format": "email"
          },
          "template_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              },
              {
                "type": "null"
              }
            ]
          },
          "locale": {
            "type": "string"
          },
          "rendered_body": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "CandidateRefuseRequest": {
        "type": "object",
        "required": [
          "applications",
          "reason_id"
        ],
        "additionalProperties": false,
        "properties": {
          "applications": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "uniqueItems": true,
            "items": {
              "type": "object",
              "required": [
                "card_id",
                "version"
              ],
              "additionalProperties": false,
              "properties": {
                "card_id": {
                  "$ref": "#/components/schemas/Uuid"
                },
                "version": {
                  "type": "integer",
                  "minimum": 0
                }
              }
            }
          },
          "reason_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "note": {
            "type": "string",
            "maxLength": 4000
          },
          "send_mail": {
            "type": "boolean",
            "default": false
          },
          "cascade_duplicates": {
            "type": "boolean",
            "default": false
          },
          "locale": {
            "type": "string",
            "default": "en"
          }
        }
      },
      "CandidateRefuseResult": {
        "type": "object",
        "required": [
          "applications",
          "refused_count",
          "cascade_count",
          "mail_queued_count",
          "email_offenders"
        ],
        "properties": {
          "applications": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "candidate_id",
                "stage",
                "version",
                "application_status"
              ],
              "properties": {
                "id": {
                  "$ref": "#/components/schemas/Uuid"
                },
                "candidate_id": {
                  "$ref": "#/components/schemas/Uuid"
                },
                "stage": {
                  "type": "string",
                  "const": "REJECTED"
                },
                "version": {
                  "type": "integer",
                  "minimum": 0
                },
                "application_status": {
                  "type": "string",
                  "const": "REFUSED"
                }
              }
            }
          },
          "refused_count": {
            "type": "integer",
            "minimum": 1
          },
          "cascade_count": {
            "type": "integer",
            "minimum": 0
          },
          "mail_queued_count": {
            "type": "integer",
            "minimum": 0
          },
          "email_offenders": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "card_id",
                "candidate_id",
                "candidate_no",
                "full_name"
              ],
              "properties": {
                "card_id": {
                  "$ref": "#/components/schemas/Uuid"
                },
                "candidate_id": {
                  "$ref": "#/components/schemas/Uuid"
                },
                "candidate_no": {
                  "$ref": "#/components/schemas/BusinessNo"
                },
                "full_name": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "CandidateActivity": {
        "type": "object",
        "readOnly": true,
        "required": [
          "id",
          "card_id",
          "activity_type",
          "origin_card_id",
          "payload",
          "created_at"
        ],
        "properties": {
          "id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "card_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "activity_type": {
            "type": "string",
            "enum": [
              "REFUSED",
              "REFUSAL_MAIL_QUEUED",
              "RESTORED"
            ]
          },
          "origin_card_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              },
              {
                "type": "null"
              }
            ]
          },
          "payload": {
            "type": "object",
            "additionalProperties": true
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "created_by": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "CandidatePipelineCard": {
        "type": "object",
        "description": "db 04 §3 `recruit.candidate_pipeline` — one Kanban board position (one live row per candidate per opening).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "candidate_id",
              "source",
              "source_attribution",
              "stage",
              "stage_entered_at",
              "days_in_stage",
              "is_rejected",
              "application_status",
              "duplicate_count",
              "duplicate_applications"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "candidate_id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "job_opening_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "source": {
                "$ref": "#/components/schemas/CandidateSource",
                "description": "Application-grain source; does not change when the person applies again elsewhere."
              },
              "source_platform": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Matched fixed-registry platform key (`linkedin`/`naukri`) when applicable."
              },
              "source_attribution": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                },
                "description": "Alias-derived UTM attribution; contains no subject/body or candidate contact PII."
              },
              "stage": {
                "$ref": "#/components/schemas/CandidatePipelineStage"
              },
              "previous_stage": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/CandidatePipelineStage"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "stage_entered_at": {
                "$ref": "#/components/schemas/Timestamp"
              },
              "days_in_stage": {
                "type": "integer",
                "minimum": 0
              },
              "is_rejected": {
                "type": "boolean"
              },
              "rejection_reason": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/CandidatePipelineRejectionReason"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "rejection_note": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "free-text detail",
                "required by the UI when rejection_reason = OTHER.": null
              },
              "refusal_reason_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "refusal_reason_label": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": {
                  "type": "string"
                }
              },
              "refused_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "archived_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "application_status": {
                "type": "string",
                "enum": [
                  "REFUSED",
                  "ARCHIVED",
                  "HIRED",
                  "ONGOING"
                ],
                "description": "Reconstructed from immutable stamps/current stage; never stored separately."
              },
              "assigned_recruiter_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→people.employees"
              },
              "rank": {
                "type": [
                  "string",
                  "null"
                ],
                "pattern": "^-?\\d+(\\.\\d{1,6})?$",
                "description": "numeric(9,6) fractional Kanban-column ordering, as a string."
              },
              "notes": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "recruiter-only."
              },
              "duplicate_count": {
                "type": "integer",
                "minimum": 0,
                "description": "Other applications in the same identity cluster, including rejected records."
              },
              "duplicate_applications": {
                "type": "array",
                "description": "Stable cross-links to every other application in the identity cluster.",
                "items": {
                  "$ref": "#/components/schemas/CandidateDuplicateApplication"
                }
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMeta"
          }
        ]
      },
      "CandidateDuplicateApplication": {
        "type": "object",
        "readOnly": true,
        "required": [
          "card_id",
          "candidate_id",
          "candidate_no",
          "job_opening_id",
          "stage",
          "is_rejected",
          "created_at"
        ],
        "properties": {
          "card_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "candidate_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "candidate_no": {
            "$ref": "#/components/schemas/BusinessNo"
          },
          "job_opening_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              },
              {
                "type": "null"
              }
            ]
          },
          "stage": {
            "$ref": "#/components/schemas/CandidatePipelineStage"
          },
          "is_rejected": {
            "type": "boolean"
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "CandidatePipelineUpdateRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "notes": {
            "type": "string"
          },
          "assigned_recruiter_id": {
            "$ref": "#/components/schemas/Uuid"
          }
        }
      },
      "CandidatePipelineMoveStageRequest": {
        "type": "object",
        "required": [
          "stage"
        ],
        "additionalProperties": false,
        "properties": {
          "stage": {
            "$ref": "#/components/schemas/CandidatePipelineStage"
          },
          "rank": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d{1,6})?$",
            "description": "Optional fractional position within the destination column."
          }
        }
      },
      "CandidatePipelineReorderRequest": {
        "type": "object",
        "required": [
          "rank"
        ],
        "additionalProperties": false,
        "properties": {
          "rank": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d{1,6})?$",
            "description": "New fractional rank between neighbours."
          }
        }
      },
      "CandidatePipelineRejectRequest": {
        "type": "object",
        "required": [
          "rejection_reason"
        ],
        "additionalProperties": false,
        "description": "`rejection_note` required when `rejection_reason = OTHER` (db 04 §3 check constraint).",
        "properties": {
          "rejection_reason": {
            "$ref": "#/components/schemas/CandidatePipelineRejectionReason"
          },
          "rejection_note": {
            "type": "string"
          }
        }
      },
      "InterviewPanelMember": {
        "type": "object",
        "required": [
          "employee_id",
          "role"
        ],
        "properties": {
          "employee_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "role": {
            "$ref": "#/components/schemas/InterviewPanelRole"
          },
          "is_required": {
            "type": "boolean",
            "default": true
          }
        }
      },
      "Interview": {
        "type": "object",
        "description": "db 04 §4 `recruit.interviews` — a scheduled interview round.",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "candidate_id",
              "round_no",
              "mode",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "candidate_id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "job_opening_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "round_no": {
                "type": "integer",
                "minimum": 1
              },
              "round_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "mode": {
                "$ref": "#/components/schemas/InterviewMode"
              },
              "status": {
                "$ref": "#/components/schemas/InterviewStatus"
              },
              "scheduled_start_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "scheduled_end_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "location": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "venue, required when mode = ONSITE."
              },
              "meeting_link": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "video link, required when mode = VIRTUAL."
              },
              "panel": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/InterviewPanelMember"
                }
              },
              "overall_recommendation": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/ScorecardRecommendation"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "rolled up once panel scorecards are submitted."
              },
              "feedback_due_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMeta"
          }
        ]
      },
      "InterviewCreateRequest": {
        "type": "object",
        "required": [
          "mode",
          "panel"
        ],
        "additionalProperties": false,
        "properties": {
          "job_opening_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "round_no": {
            "type": "integer",
            "minimum": 1,
            "default": 1
          },
          "round_name": {
            "type": "string"
          },
          "mode": {
            "$ref": "#/components/schemas/InterviewMode"
          },
          "scheduled_start_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "scheduled_end_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "location": {
            "type": "string"
          },
          "meeting_link": {
            "type": "string"
          },
          "panel": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/InterviewPanelMember"
            }
          },
          "feedback_due_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "InterviewRescheduleRequest": {
        "type": "object",
        "required": [
          "scheduled_start_at",
          "scheduled_end_at"
        ],
        "additionalProperties": false,
        "properties": {
          "scheduled_start_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "scheduled_end_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "mode": {
            "$ref": "#/components/schemas/InterviewMode"
          },
          "location": {
            "type": "string"
          },
          "meeting_link": {
            "type": "string"
          }
        }
      },
      "InterviewScorecardCompetencyRating": {
        "type": "object",
        "required": [
          "competency",
          "rating"
        ],
        "properties": {
          "competency": {
            "type": "string"
          },
          "rating": {
            "type": "number"
          },
          "weight": {
            "type": [
              "number",
              "null"
            ]
          },
          "comment": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "InterviewScorecard": {
        "type": "object",
        "description": "db 04 §4 `recruit.interview_scorecards` — **Immutable**: frozen on submit (`submitted_at`), no edit/delete (`BEFORE UPDATE OR DELETE` trigger, db-docs 00 §8/§12); a changed opinion is a new compensating row.\n",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "interview_id",
              "candidate_id",
              "interviewer_id",
              "recommendation",
              "competency_ratings",
              "submitted_at"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "interview_id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "candidate_id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "interviewer_id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "recommendation": {
                "$ref": "#/components/schemas/ScorecardRecommendation"
              },
              "overall_rating": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "competency_ratings": {
                "type": "array",
                "minItems": 1,
                "items": {
                  "$ref": "#/components/schemas/InterviewScorecardCompetencyRating"
                }
              },
              "strengths": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "concerns": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "submitted_at": {
                "$ref": "#/components/schemas/Timestamp"
              }
            }
          },
          {
            "$ref": "#/components/schemas/AppendOnlyMeta"
          }
        ]
      },
      "InterviewScorecardCreateRequest": {
        "type": "object",
        "required": [
          "recommendation",
          "competency_ratings"
        ],
        "additionalProperties": false,
        "properties": {
          "recommendation": {
            "$ref": "#/components/schemas/ScorecardRecommendation"
          },
          "overall_rating": {
            "type": "number"
          },
          "competency_ratings": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/InterviewScorecardCompetencyRating"
            }
          },
          "strengths": {
            "type": "string"
          },
          "concerns": {
            "type": "string"
          }
        }
      },
      "OfferTerms": {
        "type": "object",
        "allOf": [
          {
            "$ref": "#/components/schemas/ConfigVersionStamp"
          }
        ],
        "description": "db 04 §5 `offers.offer_terms` JSONB shape — the frozen CTC breakup + resolved config-version map; schemaless and not queried, with ONE enforced rule: every `components[]` line carries a non-empty `code`. `POST /offers`, `PATCH /offers/{id}` and `POST /offers/{id}/submit` refuse a code-less line with `422 VALIDATION_FAILED` at `/offer_terms/components/{i}/code`, because the hire chain identifies the `BASIC` head by that key to seed `pay.employee_compensation` (issue #1482) — a frozen line that cannot name its own pay head is not a valid record.\n",
        "properties": {
          "components": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "code"
              ],
              "properties": {
                "code": {
                  "type": "string",
                  "minLength": 1,
                  "description": "The pay head's identity — the `component_code` of the `org.pay_structures` line it was authored from. REQUIRED and non-empty; `BASIC` is the head the hire handoff reads.\n"
                },
                "label": {
                  "type": "string"
                },
                "amount": {
                  "type": "string",
                  "pattern": "^-?\\d+(\\.\\d{1,2})?$"
                },
                "frequency": {
                  "type": "string",
                  "enum": [
                    "MONTHLY",
                    "ANNUAL"
                  ],
                  "description": "How the amount is entered. Taken from the STRUCTURE's `frequency` (`org.pay_structures.frequency`), never from a component line — lines have none.\n"
                }
              }
            }
          },
          "gross_annual": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^-?\\d+(\\.\\d{1,2})?$"
          },
          "joining_bonus": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^-?\\d+(\\.\\d{1,2})?$"
          },
          "variable_pay": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^-?\\d+(\\.\\d{1,2})?$"
          },
          "notes": {
            "type": [
              "string",
              "null"
            ]
          },
          "tenant_config_versions": {
            "type": "object",
            "description": "resolved config key→version map read at freeze time (db-docs 00 §8), e.g. `{ \"pay.overtime_policy\": 3 }`.",
            "additionalProperties": {
              "type": "integer"
            }
          }
        }
      },
      "Offer": {
        "type": "object",
        "description": "db 04 §5 `recruit.offers` — a compensation offer. **Freezes its terms** (`offer_terms` + `pay_structure_version`/`compliance_pack_version`) at **submit**, so a later config edit never retroactively rewrites a live offer (db-docs 00 §8).\n",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "offer_no",
              "candidate_id",
              "job_opening_id",
              "ctc",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "offer_no": {
                "$ref": "#/components/schemas/BusinessNo"
              },
              "candidate_id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "job_opening_id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "grade_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→org.grades"
              },
              "pay_structure_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→org.pay_structures"
              },
              "ctc": {
                "$ref": "#/components/schemas/Money"
              },
              "joining_date": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DateOnly"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "offer_terms": {
                "$ref": "#/components/schemas/OfferTerms"
              },
              "pay_structure_version": {
                "type": [
                  "integer",
                  "null"
                ],
                "readOnly": true,
                "description": "stamped at submit."
              },
              "compliance_pack_version": {
                "type": [
                  "integer",
                  "null"
                ],
                "readOnly": true,
                "description": "stamped at submit."
              },
              "status": {
                "$ref": "#/components/schemas/OfferStatus"
              },
              "valid_until": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DateOnly"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "submitted_by": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "maker (ref→people.employees)."
              },
              "approved_by": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "checker (ref→people.employees)."
              },
              "approved_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "sent_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "responded_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "candidate_name": {
                "type": [
                  "string",
                  "null"
                ],
                "readOnly": true,
                "description": "READ-ONLY, reads only (`GET /offers`, `GET /offers/{id}`; absent from write responses). `recruit.candidates.full_name`, JOINED rather than stored — the name belongs to the candidate record and freezing a copy here would repeat the `offer_terms.label` mistake `#1482` declined to make. `null` when the candidate row is soft-deleted or gone, which degrades the label and never fails the read. Added by `#1485`: an offer carried only `candidate_id`, so an approver was asked to approve an offer without being told who it was for."
              },
              "approval": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/RecruitApprovalAffordance"
                  },
                  {
                    "type": "null"
                  }
                ],
                "readOnly": true,
                "description": "READ-ONLY, and present ONLY on the single-record read (`GET /offers/{id}`; absent from the list and from every write response). `null` unless the record is `PENDING_APPROVAL` **and** an open envelope exists for it — see the schema's own note on why the source status, not the envelope's, decides that."
              },
              "response_link": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/OfferResponseLinkState"
                  },
                  {
                    "type": "null"
                  }
                ],
                "readOnly": true,
                "description": "READ-ONLY, single-record read ONLY (`GET /offers/{id}`; absent from the list — a token lookup per row for a banner nobody is reading). `null` when no response token has ever been minted for the offer. Added by `#1487`: the send receipt lived in web component state and vanished on reload, so \"was a link ever issued, and has the candidate opened it?\" had no answer anywhere in the product."
              },
              "joining_skipped_reason": {
                "type": [
                  "string",
                  "null"
                ],
                "readOnly": true,
                "description": "READ-ONLY, single-record read ONLY (`GET /offers/{id}`), and non-null only on an `ACCEPTED` offer. WHY THE HIRE BEHIND THIS ACCEPTANCE DOES NOT EXIST, in the words the refusal was recorded in. Added by `#1655`: `mintJoiningEmployee` refuses by RECORDING rather than throwing — a candidate with no pipeline card, an opening whose requisition names no legal entity, a frozen offer with no BASIC split, a workspace at its plan cap, or a recorder without `people.employee.create_joining` all leave the acceptance intact and named the reason on the outbox payload and the audit row and NOWHERE a human looks. An accepted offer with nothing behind it therefore looked identical to a healthy one.\nDERIVED AT READ TIME — there is no column, deliberately: a stored copy drifts the moment somebody fixes the underlying fact and retries. The read resolves it from `people.onboarding_flows.hire_skipped_reason` (stamped on every refusal since `#1471` §7 and cleared when the mint succeeds), from that row's `employee_id` (an employee IS the absence of a refusal), and from `recruit.candidate_pipeline` for `NO_PIPELINE_CARD`, which is the absence of a recruit row and cannot be stamped on a flow that was never opened.\nValues: `NO_PIPELINE_CARD` · `NO_LEGAL_ENTITY` · `INCOMPLETE_PREFILL` · `FLOW_NOT_RESUMABLE` · `PLAN_LIMIT_EXCEEDED` · `NOT_AUTHORIZED` · `HANDOFF_NOT_RUN`. The last is derived here and is NOT a member of People's enums: it names an acceptance that never ran a hand-off at all, which is the NORMAL state of an offer accepted through the public candidate link — that rail has no principal and so cannot mint. `POST /offers/{id}/retry-handoff` is the door for every one of them."
              },
              "joining_employee_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "readOnly": true,
                "description": "READ-ONLY, single-record read ONLY (`GET /offers/{id}`, `#1655`). The `JOINING` employee this acceptance minted (`ref→people.employees`), or `null` when none was."
              },
              "onboarding_flow_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "readOnly": true,
                "description": "READ-ONLY, single-record read ONLY (`GET /offers/{id}`, `#1655`). The People guided onboarding flow the acceptance opened (`ref→people.onboarding_flows`), or `null`."
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMeta"
          }
        ]
      },
      "OfferCreateRequest": {
        "type": "object",
        "required": [
          "candidate_id",
          "job_opening_id",
          "ctc"
        ],
        "additionalProperties": false,
        "description": "Saves the working `DRAFT`; terms freeze at `recruit.offer.submit`, not here (db 04 §5).",
        "properties": {
          "candidate_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "job_opening_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "grade_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "pay_structure_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "ctc": {
            "$ref": "#/components/schemas/Money"
          },
          "joining_date": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DateOnly"
              },
              {
                "type": "null"
              }
            ]
          },
          "offer_terms": {
            "$ref": "#/components/schemas/OfferTerms"
          },
          "valid_until": {
            "$ref": "#/components/schemas/DateOnly"
          }
        }
      },
      "PublicOfferResponseView": {
        "type": "object",
        "description": "ADR 0039 candidate-safe projection. Deliberately an ALLOW-LIST, not a redacted row: it carries no uuids, no storage keys, no statuses and no other person's name. `candidate_first_name` is the first name only — enough to confirm the link is the recipient's, not enough to be a directory entry if the link is forwarded.\n",
        "required": [
          "company_name",
          "job_title",
          "ctc_amount",
          "currency_code",
          "decline_reasons",
          "responded"
        ],
        "additionalProperties": false,
        "properties": {
          "company_name": {
            "type": "string"
          },
          "legal_entity_name": {
            "type": "string"
          },
          "job_title": {
            "type": "string"
          },
          "candidate_first_name": {
            "type": "string"
          },
          "ctc_amount": {
            "$ref": "#/components/schemas/Money"
          },
          "currency_code": {
            "type": "string",
            "minLength": 3,
            "maxLength": 3
          },
          "joining_date": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "valid_until": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "letter_url": {
            "type": "string",
            "nullable": true,
            "description": "Per-request presigned URL for the offer letter PDF, valid for a few minutes and re-minted on every load. Null when no letter is available (or it was voided). Never a storage key.\n"
          },
          "decline_reasons": {
            "type": "array",
            "description": "Only `recruit.refusal_reasons` rows flagged `is_candidate_visible` — the catalogue is tenant-authored and defaults to private, so an employer's internal vocabulary is never published here.\n",
            "items": {
              "type": "object",
              "required": [
                "code",
                "label"
              ],
              "additionalProperties": false,
              "properties": {
                "code": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                }
              }
            }
          },
          "responded": {
            "type": "boolean"
          },
          "decision": {
            "type": "string",
            "nullable": true,
            "enum": [
              "ACCEPTED",
              "DECLINED"
            ]
          }
        }
      },
      "OfferLetterSendRequest": {
        "type": "object",
        "additionalProperties": false,
        "description": "Optional overrides for `recruit.offer_letter.send` (#1486). The whole body may be omitted, in which case the candidate's own address on file is used.\n",
        "properties": {
          "recipient_email": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "nullable": true,
            "description": "Where to send the offer, INSTEAD of the candidate's address on file. Validated as an email address and refused otherwise — the field used to be collected by the UI and dropped by the API. The token's `issued_to_hash` is the keyed digest of whichever address is actually used, so the evidence names the real recipient.\n"
          }
        }
      },
      "PublicOfferResponseRequest": {
        "type": "object",
        "required": [
          "decision"
        ],
        "additionalProperties": false,
        "description": "The candidate's own decision, with the signature ceremony on an acceptance (issue #1486, owner decision 3 of the #1470 pass).\n\nON `ACCEPTED`, both `signature_name` and `consent_accepted` are REQUIRED: a typed full name plus an explicit tick is the ordinary electronic signature this class of document takes, and there is no implied-consent branch — `consent_accepted` must be literal `true`, and a blank or whitespace-only `signature_name` is refused. Both are REFUSED on a `DECLINED`, exactly as a reason is refused on an `ACCEPTED`: a decline is not a signature and must not carry the shape of one into the record.\n\nA reason applies only to a decline; supplying one alongside `ACCEPTED` is refused rather than silently dropped, so nothing unexplained reaches the audit trail. `reason_code` must be a published (`is_candidate_visible`) refusal-reason code.\n",
        "properties": {
          "decision": {
            "type": "string",
            "enum": [
              "ACCEPTED",
              "DECLINED"
            ]
          },
          "reason_code": {
            "type": "string",
            "maxLength": 64,
            "nullable": true
          },
          "reason_note": {
            "type": "string",
            "maxLength": 2000,
            "nullable": true
          },
          "signature_name": {
            "type": "string",
            "maxLength": 160,
            "nullable": true,
            "description": "The candidate's full name, as they typed it. Required on `ACCEPTED`, refused on `DECLINED`. Stored in the audit row and on the letter's `render_context.acceptance`, and printed on the appended acknowledgement page of the SIGNED artifact where the standard-14 font can show it.\n"
          },
          "consent_accepted": {
            "type": "boolean",
            "nullable": true,
            "description": "Confirmation that the candidate read the offer letter and accepts its terms. Must be `true` on an `ACCEPTED`; absent, `null` or `false` is a form that was not completed.\n"
          }
        }
      },
      "PublicOfferResponseResult": {
        "type": "object",
        "required": [
          "decision",
          "recorded_at"
        ],
        "additionalProperties": false,
        "properties": {
          "decision": {
            "type": "string",
            "enum": [
              "ACCEPTED",
              "DECLINED"
            ]
          },
          "recorded_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "OfferRecordResponseRequest": {
        "type": "object",
        "required": [
          "decision"
        ],
        "additionalProperties": false,
        "description": "GAP-27 — HR records the candidate's off-platform response. `evidence_note` (what the recording is based on — e-mail reference, signed hardcopy, call) lands on the append-only audit plane only; it is never echoed into list payloads.\n",
        "properties": {
          "decision": {
            "type": "string",
            "enum": [
              "ACCEPTED",
              "DECLINED"
            ]
          },
          "evidence_note": {
            "type": "string",
            "maxLength": 2000
          }
        }
      },
      "OfferUpdateRequest": {
        "type": "object",
        "description": "Editable while `status = DRAFT` (fsd 03 §REC-S09).",
        "additionalProperties": false,
        "properties": {
          "grade_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "pay_structure_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "ctc": {
            "$ref": "#/components/schemas/Money"
          },
          "joining_date": {
            "$ref": "#/components/schemas/DateOnly"
          },
          "offer_terms": {
            "$ref": "#/components/schemas/OfferTerms"
          },
          "valid_until": {
            "$ref": "#/components/schemas/DateOnly"
          }
        }
      },
      "OfferEmailAttachmentPreview": {
        "type": "object",
        "readOnly": true,
        "nullable": true,
        "description": "What `recruit.offer.send_email` would attach — filename only. `byte_size` is `null` in both the preview and the queued mail row: the actual byte count is unknown until the jobs-tier dispatcher fetches the object from storage at send time (`apps/jobs/src/jobs/mail-jobs.ts`), where the 8 MB cap is actually enforced. `null` (not an object) when the offer has no live `SENT` letter yet.\n",
        "required": [
          "filename",
          "byte_size"
        ],
        "properties": {
          "filename": {
            "type": "string"
          },
          "byte_size": {
            "type": [
              "integer",
              "null"
            ]
          }
        }
      },
      "OfferEmailPreview": {
        "type": "object",
        "readOnly": true,
        "description": "`recruit.offer.preview_email`'s response — the rendered `email.offer` template, exactly as `recruit.offer.send_email` would produce it, except `variables.offer_response_url` (and its occurrence in `body_text`/`body_html`) is a clearly-marked, non-functional placeholder — no real ADR 0039 token is ever minted by a preview.\n",
        "required": [
          "subject",
          "body_text",
          "body_html",
          "to_address",
          "attachment",
          "variables"
        ],
        "properties": {
          "subject": {
            "type": "string"
          },
          "body_text": {
            "type": "string"
          },
          "body_html": {
            "type": "string"
          },
          "to_address": {
            "anyOf": [
              {
                "type": "string",
                "format": "email"
              },
              {
                "type": "null"
              }
            ],
            "description": "The candidate's email on file, or `null` when there is none."
          },
          "attachment": {
            "$ref": "#/components/schemas/OfferEmailAttachmentPreview"
          },
          "variables": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "The full `email.offer` merge-value map used to render the preview above, including the placeholder `offer_response_url`.\n"
          }
        }
      },
      "OfferSendEmailRequest": {
        "type": "object",
        "additionalProperties": false,
        "description": "Both fields are optional; when supplied they REPLACE the rendered subject/body on the queued `xc.mail_messages` row only — the `org.templates` `email.offer` row is never modified. `body_text` is NOT re-run through the `{{var}}` merge pipeline (it is finished prose, not template syntax) and must retain the literal `{{offer_response_url}}` placeholder, which is substituted with the real, freshly-minted link before the mail is queued; an edit that drops it is refused with a `409`.\n",
        "properties": {
          "subject": {
            "type": "string",
            "maxLength": 200
          },
          "body_text": {
            "type": "string",
            "maxLength": 100000
          }
        }
      },
      "OfferSendEmailResponse": {
        "type": "object",
        "readOnly": true,
        "description": "Deliberately minimal: the selector, verifier and full response URL are NEVER returned — the same posture the public candidate surface holds toward every other secret it handles.\n",
        "required": [
          "mail_message_id",
          "to_address",
          "expires_at"
        ],
        "properties": {
          "mail_message_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "to_address": {
            "type": "string",
            "format": "email"
          },
          "expires_at": {
            "$ref": "#/components/schemas/Timestamp",
            "description": "When the freshly-minted ADR 0039 response token (and so the mailed link) expires."
          }
        }
      },
      "OfferResponseLinkResponse": {
        "type": "object",
        "readOnly": true,
        "description": "Issue #1487. The ONE response in this contract that carries a live ADR 0039 response link. It is returned once and never again: nothing stores the verifier, so this URL cannot be re-read, and the next `recruit.offer.response_link` call — or a resend of the offer email — revokes it. Treat it as a credential: `Cache-Control: no-store`, never logged, never echoed into a shared surface.\n",
        "required": [
          "url",
          "issued_at",
          "expires_at"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "`PUBLIC_LINK_BASE_URL` + `/offer-response/<selector>.<verifier>` — the same URL the offer email would carry, for a token minted by this call.\n"
          },
          "issued_at": {
            "$ref": "#/components/schemas/Timestamp",
            "description": "The token row's `created_at`, so the receipt read back on the offer matches."
          },
          "expires_at": {
            "$ref": "#/components/schemas/Timestamp",
            "description": "Capped by the offer's `valid_until` and the ADR 0039 30-day ceiling, whichever is sooner.\n"
          }
        }
      },
      "OfferResponseLinkState": {
        "type": "object",
        "readOnly": true,
        "description": "Issue #1487 — the offer's candidate response link as a STATE, never as a credential. The property list IS the security argument: issued/expires/opened/retired, and nothing else. No selector, no `verifier_hash`, no `issued_to_hash`. Enough to say \"link issued 30 Aug, expires 29 Sep, not yet opened\" and to survive a page reload, which the send receipt (component state in the web tier) never did. Reflects the NEWEST token row for the offer whether or not it is still live — a superseded row is exactly what \"you issued a link, then issued another\" looks like, and hiding it would make the banner lie by omission.\n",
        "required": [
          "issued_at",
          "expires_at",
          "used_at",
          "revoked_at",
          "revoked_reason"
        ],
        "properties": {
          "issued_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ]
          },
          "expires_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ]
          },
          "used_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the candidate opened/consumed the link; `null` while unopened."
          },
          "revoked_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ]
          },
          "revoked_reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "SUPERSEDED",
              "OFFER_REVOKED",
              "OFFER_EXPIRED",
              "LETTER_VOID",
              "RESPONDED",
              null
            ],
            "description": "`recruit.offer_response_token_revoked_reason`; `null` while the link is live."
          }
        }
      },
      "OfferLetterRenderContext": {
        "type": "object",
        "readOnly": true,
        "allOf": [
          {
            "$ref": "#/components/schemas/ConfigVersionStamp"
          }
        ],
        "description": "db 04 §5 `offer_letters.render_context` JSONB shape — the frozen, string-formatted merge values handed to the render (`org.templates` `letter.offer`, migration `0117`); schemaless, not queried. *(rev. 2026-08-14, issue #866: replaces the pre-async placeholder shape with the actual keys the seeded template declares.)* `department` and `signatory_title` are `''` when there is nothing to put there rather than omitted. The config-version stamp is copied from the approved offer and remains immutable with these merge values.\n",
        "properties": {
          "issue_date": {
            "type": "string"
          },
          "candidate_name": {
            "type": "string"
          },
          "job_title": {
            "type": "string"
          },
          "department": {
            "type": "string"
          },
          "company_name": {
            "type": "string"
          },
          "legal_entity_name": {
            "type": "string"
          },
          "date_of_joining": {
            "type": "string"
          },
          "ctc_amount": {
            "type": "string"
          },
          "currency_code": {
            "type": "string"
          },
          "signatory_name": {
            "type": "string"
          },
          "signatory_title": {
            "type": "string"
          }
        }
      },
      "OfferLetterFile": {
        "type": "object",
        "readOnly": true,
        "description": "Presigned rendered-PDF download for an offer letter (db-docs/00 §14). Deliberately not the shared `FileDownload` shape — this presign path (offer.service.ts `presignOrNull`) never carries a `file_id`/`file_name`, only the URL, its expiry, and the tamper-evidence hash.\n",
        "required": [
          "url",
          "expires_at"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Time-limited presigned URL."
          },
          "expires_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "content_hash": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "SHA-256 tamper-evidence."
          }
        }
      },
      "OfferLetter": {
        "type": "object",
        "description": "db 04 §5 `recruit.offer_letters` — the generated offer-letter document (metadata + storage reference only; bytes never in Postgres, db-docs 00 §14).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "offer_id",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "offer_id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "template_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→org.templates — required since migration `0118`."
              },
              "render_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→org.template_renders — the render this letter is waiting on / was produced by (added migration `0118`, issue #866). Not polled directly by clients — `org.template.render_status` is `hr_admin`-only; poll this letter's own `GET /offer-letters/{id}` instead."
              },
              "render_error": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Permanent render-failure reason, set together with a `GENERATING → VOID` transition (added migration `0118`, issue #866)."
              },
              "file": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/OfferLetterFile"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Presigned rendered-PDF download; `null` while `status = GENERATING` or on a `VOID` letter that never rendered."
              },
              "render_context": {
                "$ref": "#/components/schemas/OfferLetterRenderContext"
              },
              "pay_structure_version": {
                "type": [
                  "integer",
                  "null"
                ],
                "readOnly": true
              },
              "compliance_pack_version": {
                "type": [
                  "integer",
                  "null"
                ],
                "readOnly": true
              },
              "status": {
                "$ref": "#/components/schemas/OfferLetterStatus"
              },
              "esign_request_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→docs.esign_requests (DOC-F02)."
              },
              "signed_file": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/OfferLetterFile"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Presigned signed-PDF download; `content_hash` carries tamper-evidence. Since issue #866 this is the SENT letter's own artifact stamped on acceptance, never a second render."
              },
              "signed_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMeta"
          }
        ]
      },
      "OfferLetterCreateRequest": {
        "type": "object",
        "required": [
          "template_id"
        ],
        "additionalProperties": false,
        "properties": {
          "template_id": {
            "$ref": "#/components/schemas/Uuid",
            "description": "Must resolve to a PUBLISHED `org.templates` row of `kind = LETTER` and `sub_type = OFFER` — see the `422` response."
          }
        }
      },
      "OfferLetterSignRequest": {
        "type": "object",
        "required": [
          "consent"
        ],
        "additionalProperties": false,
        "description": "Completes the in-house e-sign ceremony (`DOC-F02`); acceptance **is** the signature (fsd 03 §REC-S13). `signature_metadata` mirrors `docs.esign_signatures.signature_metadata` capture evidence (db 10 §4).\n",
        "properties": {
          "consent": {
            "type": "boolean",
            "description": "Must be true — explicit e-sign consent."
          },
          "signature_metadata": {
            "type": "object",
            "properties": {
              "device": {
                "type": "string"
              },
              "user_agent": {
                "type": "string"
              },
              "consent_text_version": {
                "type": "string"
              }
            }
          }
        }
      },
      "PreboardingRequiredDocument": {
        "type": "object",
        "required": [
          "doc_type",
          "label",
          "is_required",
          "status"
        ],
        "properties": {
          "doc_type": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "is_required": {
            "type": "boolean"
          },
          "status": {
            "$ref": "#/components/schemas/PreboardingDocumentStatus"
          },
          "document": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FileDownload"
              },
              {
                "type": "null"
              }
            ]
          },
          "document_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The live `recruit.preboarding_documents` row behind this item (#1656), projected onto the HR case read by `decoratePreboardingCases` — newest sequence per doc type, superseded and deleted rows excluded. It is the id `recruit.preboarding.view_document` takes, and the only thing that tells a console a View control is real. An id, never a URL or a storage key: this read is gated on `recruit.preboarding.list`/`.get`, a strictly weaker grant than opening the bytes.\n"
          },
          "document_file_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Display metadata; never part of the stored object key."
          },
          "document_uploaded_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ]
          },
          "verified_by": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              },
              {
                "type": "null"
              }
            ],
            "description": "ref→people.employees"
          },
          "verified_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ]
          },
          "reject_reason": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "PreboardingChecklistItem": {
        "type": "object",
        "required": [
          "item_key",
          "label",
          "is_required",
          "status"
        ],
        "properties": {
          "item_key": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "is_required": {
            "type": "boolean"
          },
          "status": {
            "$ref": "#/components/schemas/PreboardingChecklistItemStatus"
          },
          "completed_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "Preboarding": {
        "type": "object",
        "description": "db 04 §6 `recruit.preboarding` — the accepted candidate's pre-joining workflow (one row per accepted offer).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "candidate_id",
              "offer_id",
              "status",
              "progress_pct"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "candidate_id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "offer_id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "status": {
                "$ref": "#/components/schemas/PreboardingStatus"
              },
              "offer_accepted_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "documents_submitted_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "checklist_completed_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "expected_joining_date": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DateOnly"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "required_documents": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PreboardingRequiredDocument"
                }
              },
              "checklist_items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PreboardingChecklistItem"
                }
              },
              "progress_pct": {
                "type": "number",
                "minimum": 0,
                "maximum": 100
              },
              "work_email": {
                "description": "The corporate mailbox IT provisioned, HR-entered — never defaulted, never synthesized from `candidates.email` (bug R6; decisions register #5). migration `0125`.\n",
                "anyOf": [
                  {
                    "type": "string",
                    "format": "email",
                    "minLength": 3,
                    "maxLength": 320
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "work_email_assigned_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "work_email_assigned_by": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "flow_id": {
                "description": "API-only seam field (#1475), projected on `recruit.preboarding.list`/`.get` and on `recruit.preboarding.update`'s response. The People guided-onboarding flow this candidate's hire runs in, derived through the `candidate_id` hand-off key — no duplicate recruit foreign key is stored, exactly as for `OnboardingChecklist.flow_id`. `null` when no flow is open.\n",
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "employee_id": {
                "description": "API-only seam field (#1475), same projection as `flow_id`. The `people.employees` row this hire has already minted. NOT the same fact as `OnboardingChecklist.created_employee_id`: since the offer-acceptance mint the employee exists in `JOINING` long before the guided flow completes, and a case may carry no checklist at all. `null` until the mint.\n",
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMeta"
          }
        ]
      },
      "PreboardingUploadDocumentRequest": {
        "type": "object",
        "required": [
          "doc_type",
          "storage_key",
          "content_type"
        ],
        "additionalProperties": false,
        "properties": {
          "doc_type": {
            "type": "string",
            "description": "identifies the `required_documents[]` item."
          },
          "storage_key": {
            "type": "string",
            "description": "Object key minted by a prior `request_upload_url` call; re-validated server-side against this case's own tenant/case/doc_type prefix."
          },
          "file_name": {
            "type": "string",
            "description": "Display metadata only — it never reaches the stored object key."
          },
          "content_type": {
            "type": "string",
            "enum": [
              "application/pdf",
              "image/jpeg",
              "image/png",
              "image/heic",
              "image/heif",
              "image/webp"
            ],
            "description": "REQUIRED and allow-listed (#694 security review, F2). A pre-boarding document is a scan or a photo; active-content types (text/html, image/svg+xml) and unknown blobs are refused because the reader is a privileged HR reviewer. Re-validated at BOTH request_upload_url and upload_document — the two are separate requests, so the registered value is not taken on trust. The stored object key's extension is derived from THIS value, never from file_name."
          },
          "size_bytes": {
            "type": "integer",
            "minimum": 0
          },
          "content_hash": {
            "type": "string"
          },
          "replace": {
            "type": "boolean",
            "default": true,
            "description": "Supersede any prior object(s) already registered for this `doc_type`. Default `true`."
          }
        }
      },
      "PreboardingDocumentRecord": {
        "type": "object",
        "description": "The registered upload row (`recruit.preboarding_documents`) — the `register` half of the two-step upload.",
        "required": [
          "id",
          "doc_type",
          "sequence",
          "uploaded_at"
        ],
        "properties": {
          "id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "doc_type": {
            "type": "string"
          },
          "file_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "sequence": {
            "type": "integer",
            "minimum": 0,
            "description": "Per-`doc_type` replace counter — increments each time the same doc_type is re-registered."
          },
          "uploaded_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "uploaded_source": {
            "type": "string",
            "enum": [
              "CANDIDATE",
              "HR"
            ],
            "description": "Which side of the desk entered the document (#1473). Present on the HR-side register (`upload_document_for_candidate`); the checklist item carries the same value, so a console never implies the candidate uploaded a file HR entered on their behalf."
          },
          "uploaded_by": {
            "$ref": "#/components/schemas/Uuid"
          }
        }
      },
      "PreboardingSubmitResult": {
        "type": "object",
        "required": [
          "id",
          "status",
          "progress_pct"
        ],
        "properties": {
          "id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "status": {
            "$ref": "#/components/schemas/PreboardingStatus"
          },
          "documents_submitted_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ]
          },
          "progress_pct": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          }
        }
      },
      "PreboardingCompleteChecklistResult": {
        "type": "object",
        "required": [
          "id",
          "checklist_items",
          "progress_pct"
        ],
        "properties": {
          "id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "checklist_items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PreboardingChecklistItem"
            }
          },
          "progress_pct": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          }
        }
      },
      "PreboardingDataSection": {
        "type": "string",
        "enum": [
          "PERSONAL",
          "BANK"
        ],
        "description": "db 04 §6 `preboarding_candidate_data.section` — one candidate-data form step."
      },
      "PreboardingUploadedDocument": {
        "type": "object",
        "description": "One registered upload row, as returned in the candidate's own landing read (`get_by_invite`).",
        "required": [
          "doc_type",
          "sequence",
          "uploaded_at"
        ],
        "properties": {
          "doc_type": {
            "type": "string"
          },
          "file_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "content_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "size_bytes": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0
              },
              {
                "type": "null"
              }
            ]
          },
          "sequence": {
            "type": "integer",
            "minimum": 0
          },
          "uploaded_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "PreboardingCandidateDataSection": {
        "type": "object",
        "description": "One saved form step, as returned in the candidate's own landing read (`get_by_invite`) so a returning candidate sees what they already typed.",
        "required": [
          "section",
          "payload"
        ],
        "properties": {
          "section": {
            "$ref": "#/components/schemas/PreboardingDataSection"
          },
          "payload": {
            "type": "object",
            "description": "The saved step's validated field set (shared allow-list — the same one `trigger_prefill` projects from)."
          },
          "consent_given_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ]
          },
          "submitted_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "PreboardingOwnCase": {
        "type": "object",
        "description": "`REC-S19`'s landing read — the candidate-safe projection of their own `recruit.preboarding` case plus its registered uploads, saved candidate-data steps and live invite expiry. Hand-listed, never a raw table dump: no recruiter notes, no scorecards, no other candidate, no `verifier_hash`.\n",
        "required": [
          "id",
          "status",
          "progress_pct",
          "required_documents",
          "checklist_items"
        ],
        "properties": {
          "id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "status": {
            "$ref": "#/components/schemas/PreboardingStatus"
          },
          "progress_pct": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "expected_joining_date": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DateOnly"
              },
              {
                "type": "null"
              }
            ]
          },
          "required_documents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PreboardingRequiredDocument"
            }
          },
          "checklist_items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PreboardingChecklistItem"
            }
          },
          "documents_submitted_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ]
          },
          "candidate_name": {
            "type": "string"
          },
          "role_title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "joining_date": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DateOnly"
              },
              {
                "type": "null"
              }
            ]
          },
          "offer_no": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "offer_accepted_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ]
          },
          "uploaded_documents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PreboardingUploadedDocument"
            }
          },
          "candidate_data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PreboardingCandidateDataSection"
            }
          },
          "link_expires_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ],
            "description": "The caller's own live invite token's expiry."
          }
        }
      },
      "PreboardingSaveCandidateDataRequest": {
        "type": "object",
        "required": [
          "payload"
        ],
        "additionalProperties": false,
        "properties": {
          "payload": {
            "type": "object",
            "description": "The step's field set, validated against the section's shared allow-list (`PERSONAL` vs `BANK`)."
          },
          "consent_given": {
            "type": "boolean",
            "default": false,
            "description": "Required `true` on this call (or already recorded on a prior save) before a `PERSONAL` section's `identity` block may be written (DPDP consent gate)."
          }
        }
      },
      "PreboardingCandidateDataSaveResult": {
        "type": "object",
        "required": [
          "id",
          "section"
        ],
        "properties": {
          "id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "section": {
            "$ref": "#/components/schemas/PreboardingDataSection"
          },
          "consent_given_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ]
          },
          "updated_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "PreboardingRequestUploadUrlRequest": {
        "type": "object",
        "required": [
          "doc_type",
          "file_name",
          "content_type"
        ],
        "additionalProperties": false,
        "properties": {
          "doc_type": {
            "type": "string",
            "description": "identifies the `required_documents[]` item."
          },
          "file_name": {
            "type": "string",
            "description": "Display metadata only — it never reaches the stored object key."
          },
          "content_type": {
            "type": "string",
            "enum": [
              "application/pdf",
              "image/jpeg",
              "image/png",
              "image/heic",
              "image/heif",
              "image/webp"
            ],
            "description": "REQUIRED and allow-listed (#694 security review, F2). A pre-boarding document is a scan or a photo; active-content types (text/html, image/svg+xml) and unknown blobs are refused because the reader is a privileged HR reviewer. Re-validated at BOTH request_upload_url and upload_document — the two are separate requests, so the registered value is not taken on trust. The stored object key's extension is derived from THIS value, never from file_name."
          },
          "size_bytes": {
            "type": "integer",
            "minimum": 0,
            "description": "Rejected above the 15 MB upload limit."
          }
        }
      },
      "PreboardingUploadUrlResult": {
        "type": "object",
        "required": [
          "storage_key",
          "upload_url",
          "expires_at"
        ],
        "properties": {
          "storage_key": {
            "type": "string",
            "description": "Tenant/case/doc_type-prefixed object key; pass back unchanged to `upload_document`."
          },
          "upload_url": {
            "type": "string",
            "format": "uri"
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Headers the client MUST send with the presigned PUT."
          },
          "expires_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "PreboardingInviteResult": {
        "type": "object",
        "description": "The raw mail-rail payload `send_invite` mints — returned to the caller exactly once, since the stored row keeps only a digest. Deliberately camelCase (unlike the rest of this file's snake_case responses): this is the literal object handed to the outbound mailer, not a normalized API projection.\n",
        "required": [
          "tokenId",
          "token",
          "expiresAt",
          "preboardingId",
          "candidateId"
        ],
        "properties": {
          "tokenId": {
            "$ref": "#/components/schemas/Uuid"
          },
          "token": {
            "type": "string",
            "description": "`selector.verifier` — hand to the mail rail; never store, never log, never re-read (unrecoverable after this response)."
          },
          "url": {
            "type": [
              "string",
              "null"
            ],
            "description": "`{PUBLIC_LINK_BASE_URL}/{workspace}/join/{token}` (#1657) — the same credential, assembled, so the caller never has to guess an origin. `null` when `PUBLIC_LINK_BASE_URL` is unset or the tenant has no `xc.tenant_cache.workspace_slug`. Shown once, for the session that issued it; never persisted, never logged, never placed in a back-office URL.\n"
          },
          "expiresAt": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "preboardingId": {
            "$ref": "#/components/schemas/Uuid"
          },
          "candidateId": {
            "$ref": "#/components/schemas/Uuid"
          }
        }
      },
      "PreboardingRevokeInviteRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "reason": {
            "type": "string",
            "maxLength": 500
          }
        }
      },
      "PreboardingRevokeInviteResult": {
        "type": "object",
        "required": [
          "id",
          "invite_status"
        ],
        "properties": {
          "id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "invite_status": {
            "type": "string",
            "enum": [
              "REVOKED"
            ]
          }
        }
      },
      "PreboardingExtendInviteRequest": {
        "type": "object",
        "required": [
          "days"
        ],
        "additionalProperties": false,
        "properties": {
          "days": {
            "type": "integer",
            "minimum": 1,
            "description": "Bounded by the tenant's configured invite TTL policy."
          }
        }
      },
      "PreboardingExtendInviteResult": {
        "type": "object",
        "required": [
          "id",
          "expires_at"
        ],
        "properties": {
          "id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "expires_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "PreboardingRequiredDocumentInput": {
        "type": "object",
        "required": [
          "doc_type"
        ],
        "additionalProperties": false,
        "properties": {
          "doc_type": {
            "type": "string"
          },
          "is_required": {
            "type": "boolean",
            "default": true
          },
          "description": {
            "type": "string",
            "maxLength": 500
          }
        }
      },
      "PreboardingChecklistItemInput": {
        "type": "object",
        "required": [
          "item_key",
          "label"
        ],
        "additionalProperties": false,
        "properties": {
          "item_key": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "maxLength": 500
          },
          "is_required": {
            "type": "boolean",
            "default": true
          }
        }
      },
      "PreboardingDefineChecklistRequest": {
        "type": "object",
        "required": [
          "required_documents"
        ],
        "additionalProperties": false,
        "properties": {
          "template_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "required_documents": {
            "type": "array",
            "maxItems": 40,
            "items": {
              "$ref": "#/components/schemas/PreboardingRequiredDocumentInput"
            }
          },
          "checklist_items": {
            "type": "array",
            "maxItems": 40,
            "items": {
              "$ref": "#/components/schemas/PreboardingChecklistItemInput"
            }
          },
          "expected_joining_date": {
            "$ref": "#/components/schemas/DateOnly"
          }
        }
      },
      "PreboardingPrefillProvenance": {
        "type": "object",
        "description": "Deliberately camelCase — passed through from the prefill computation unnormalized.",
        "required": [
          "fields"
        ],
        "properties": {
          "fields": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "submittedAt": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ]
          },
          "consentGivenAt": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "PreboardingPrefillResult": {
        "type": "object",
        "required": [
          "flow_id",
          "prefilled_fields",
          "skipped_reason"
        ],
        "properties": {
          "flow_id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              },
              {
                "type": "null"
              }
            ]
          },
          "prefilled_fields": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "skipped_reason": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "no_open_flow",
                  "stage_passed",
                  "already_populated",
                  "nothing_verified",
                  "already_hired"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "provenance": {
            "$ref": "#/components/schemas/PreboardingPrefillProvenance"
          }
        }
      },
      "PublicPreboardingExchangeRequest": {
        "type": "object",
        "required": [
          "token"
        ],
        "additionalProperties": false,
        "properties": {
          "token": {
            "type": "string",
            "description": "`selector.verifier` from the emailed invite link."
          }
        }
      },
      "PublicPreboardingExchangeResult": {
        "type": "object",
        "required": [
          "preboarding_id",
          "expires_at"
        ],
        "properties": {
          "preboarding_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "expires_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "PreboardingVerifyDocumentRequest": {
        "type": "object",
        "required": [
          "doc_type",
          "decision"
        ],
        "additionalProperties": false,
        "description": "`reject_reason` required when `decision = REJECTED` (fsd 03 §REC-S11).",
        "properties": {
          "doc_type": {
            "type": "string"
          },
          "decision": {
            "type": "string",
            "enum": [
              "VERIFIED",
              "REJECTED"
            ]
          },
          "reject_reason": {
            "type": "string"
          }
        }
      },
      "PreboardingCompleteChecklistItemRequest": {
        "type": "object",
        "required": [
          "item_key"
        ],
        "additionalProperties": false,
        "properties": {
          "item_key": {
            "type": "string"
          }
        }
      },
      "PreboardingUpdateRequest": {
        "type": "object",
        "required": [
          "work_email"
        ],
        "additionalProperties": false,
        "description": "`null` clears the assignment (`work_email`, `work_email_assigned_at` and `work_email_assigned_by` all revert to `null` together — db 04 §6 `preboarding_work_email_attribution`). A non-null value assigns it and stamps the pair from the calling actor/clock.\n",
        "properties": {
          "work_email": {
            "anyOf": [
              {
                "type": "string",
                "format": "email",
                "minLength": 3,
                "maxLength": 320
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "PreboardingEmail": {
        "type": "object",
        "description": "One `xc.mail_messages` row related to a pre-boarding case (fsd 03 §REC-S11). `is_sendable` and `blocked_reason` are service projections of the send guard (not `DRAFT`, or an unresolved `{{placeholder}}` in `body_text`), not stored columns.\n",
        "required": [
          "id",
          "kind",
          "status",
          "subject",
          "to_address",
          "to_name",
          "locale",
          "body_text",
          "created_at",
          "version",
          "is_sendable"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "kind": {
            "type": "string",
            "enum": [
              "recruit.onboarding_welcome",
              "recruit.onboarding_credentials",
              "recruit.ess_access"
            ],
            "description": "The credentials draft (`recruit.onboarding_credentials`) structurally carries no password — no such template variable exists in its manifest.\n"
          },
          "status": {
            "type": "string",
            "enum": [
              "DRAFT",
              "QUEUED",
              "SENDING",
              "SENT",
              "FAILED",
              "SUPPRESSED"
            ]
          },
          "subject": {
            "type": "string"
          },
          "to_address": {
            "type": "string",
            "format": "email"
          },
          "to_name": {
            "type": "string"
          },
          "locale": {
            "type": "string",
            "enum": [
              "en",
              "ar"
            ]
          },
          "body_text": {
            "type": "string"
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "queued_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ]
          },
          "sent_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ]
          },
          "version": {
            "type": "integer",
            "description": "Optimistic-lock counter; surfaces as the ETag on `.send_email`."
          },
          "is_sendable": {
            "type": "boolean",
            "description": "True only when `status = DRAFT` and `body_text` has no unresolved `{{placeholder}}`."
          },
          "blocked_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Human-readable reason `is_sendable` is false; `null` when sendable or already past `DRAFT`."
          }
        }
      },
      "PreboardingEmailList": {
        "type": "object",
        "description": "Bounded per-case collection (three drafts plus their resend history) — unpaginated, like `recruit.candidate_activity.list`'s `{data: [...]}` shape on the same neighbouring child-collection pattern in this file; not the tenant-wide `admin.email_settings.list_status` ledger shape.\n",
        "required": [
          "data"
        ],
        "additionalProperties": false,
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PreboardingEmail"
            }
          }
        }
      },
      "OnboardingChecklist": {
        "type": "object",
        "description": "db 04 §6 `recruit.onboarding_checklists` — the day-one run whose readiness gate ends in `recruit.onboarding_checklist.complete` (#1659). `readiness` and `flow_id` are service projections, not columns.\n",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "candidate_id",
              "status",
              "total_tasks",
              "completed_tasks",
              "readiness",
              "flow_id"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "candidate_id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "preboarding_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "offer_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "status": {
                "$ref": "#/components/schemas/OnboardingChecklistStatus"
              },
              "joining_date": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DateOnly"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "total_tasks": {
                "type": "integer",
                "minimum": 0
              },
              "completed_tasks": {
                "type": "integer",
                "minimum": 0
              },
              "employee_created_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "created_employee_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→people.employees — id returned by the people service on creation."
              },
              "readiness": {
                "$ref": "#/components/schemas/OnboardingReadiness"
              },
              "flow_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Derived through candidate_id from the current or latest `people.onboarding_flows` row; no duplicate cross-module FK is stored."
              },
              "completed_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMeta"
          }
        ]
      },
      "OnboardingChecklistCompletion": {
        "type": "object",
        "description": "The checklist row as `recruit.onboarding_checklist.complete` left it, plus `completion` — what the hire actually did, one named fact per key (#1659, the reporting shape PR #1506 gave this surface). `completion` is a service projection, not a column: re-reading the checklist afterwards returns the row without it.\n",
        "allOf": [
          {
            "$ref": "#/components/schemas/OnboardingChecklist"
          },
          {
            "type": "object",
            "required": [
              "completion"
            ],
            "properties": {
              "completion": {
                "type": "object",
                "required": [
                  "completed",
                  "outcome"
                ],
                "properties": {
                  "completed": {
                    "type": "boolean",
                    "description": "True only when THIS call finished the hire."
                  },
                  "outcome": {
                    "type": "string",
                    "enum": [
                      "EMPLOYEE_CREATED",
                      "ALREADY_COMPLETED",
                      "FLOW_NOT_RESUMABLE",
                      "INCOMPLETE_PREFILL",
                      "PLAN_LIMIT_EXCEEDED"
                    ],
                    "description": "`EMPLOYEE_CREATED` — the hire finished here. `ALREADY_COMPLETED` — it had already finished (a replay, or a hire completed through the board move) and this call only closed the case. The other three are the People seam's own refusals, reported rather than thrown: `FLOW_NOT_RESUMABLE` means a human walked the guided flow past `OFFER` and it must be finished in People — `flow_id` is the link.\n"
                  },
                  "employee_id": {
                    "anyOf": [
                      {
                        "$ref": "#/components/schemas/Uuid"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "employee_no": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "compensation_id": {
                    "anyOf": [
                      {
                        "$ref": "#/components/schemas/Uuid"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "ref→pay.employee_compensation — the salary the accepted offer became."
                  },
                  "ess_identity_id": {
                    "anyOf": [
                      {
                        "$ref": "#/components/schemas/Uuid"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "ref→xc.identities — the self-service sign-in, built from the work email. No invitation is minted or mailed (#1638/#1658)."
                  },
                  "ess_skipped_reason": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "baseline_role_granted": {
                    "type": "boolean"
                  },
                  "baseline_role_skipped_reason": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "flow_id": {
                    "anyOf": [
                      {
                        "$ref": "#/components/schemas/Uuid"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                }
              }
            }
          }
        ]
      },
      "OnboardingChecklistCreateRequest": {
        "type": "object",
        "required": [
          "candidate_id"
        ],
        "additionalProperties": false,
        "properties": {
          "candidate_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "preboarding_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "offer_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "joining_date": {
            "$ref": "#/components/schemas/DateOnly"
          },
          "onboarding_template_id": {
            "$ref": "#/components/schemas/Uuid",
            "description": "Explicit template pick; else the best-matching active template is used."
          }
        }
      },
      "OnboardingTask": {
        "type": "object",
        "description": "db 04 §6 `recruit.onboarding_tasks` — an individual onboarding/provisioning task under a checklist.",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "checklist_id",
              "title",
              "category",
              "status",
              "sequence",
              "is_blocking"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "checklist_id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "title": {
                "type": "string"
              },
              "category": {
                "$ref": "#/components/schemas/OnboardingTaskCategory"
              },
              "status": {
                "$ref": "#/components/schemas/OnboardingTaskStatus"
              },
              "assigned_to": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→people.employees"
              },
              "due_date": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DateOnly"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "sequence": {
                "type": "integer",
                "minimum": 0
              },
              "is_blocking": {
                "type": "boolean"
              },
              "external_ref": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→assets.asset_assignments (AST-F02) or provisioning record (soft ref)."
              },
              "completed_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Timestamp"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMeta"
          }
        ]
      },
      "OnboardingTaskStatusRequest": {
        "type": "object",
        "required": [
          "status"
        ],
        "additionalProperties": false,
        "properties": {
          "status": {
            "$ref": "#/components/schemas/OnboardingTaskStatus"
          }
        }
      },
      "OnboardingTemplateTask": {
        "type": "object",
        "required": [
          "title",
          "category",
          "sequence",
          "is_blocking"
        ],
        "properties": {
          "id": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              },
              {
                "type": "null"
              }
            ],
            "readOnly": true
          },
          "title": {
            "type": "string"
          },
          "category": {
            "$ref": "#/components/schemas/OnboardingTaskCategory"
          },
          "default_assignee_role": {
            "type": [
              "string",
              "null"
            ],
            "description": "ownership hint (HR/IT/MANAGER), resolved to a concrete assignee at instantiation."
          },
          "sequence": {
            "type": "integer",
            "minimum": 0
          },
          "is_blocking": {
            "type": "boolean",
            "default": false
          },
          "offset_days": {
            "type": [
              "integer",
              "null"
            ],
            "description": "due_date = joining_date + offset_days; may be negative (pre-joining tasks)."
          }
        }
      },
      "OnboardingTemplate": {
        "type": "object",
        "description": "db 04 §6 `recruit.onboarding_templates` — the reusable onboarding-checklist library, copy-at-create into `onboarding_tasks`.",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "name",
              "is_default",
              "is_active",
              "tasks"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/Uuid"
              },
              "name": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "legal_entity_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→org.legal_entities; null = tenant-wide."
              },
              "department_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/Uuid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "ref→org.departments"
              },
              "employment_type": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/EmploymentType"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "is_default": {
                "type": "boolean"
              },
              "is_active": {
                "type": "boolean"
              },
              "tasks": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/OnboardingTemplateTask"
                }
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMeta"
          }
        ]
      },
      "OnboardingTemplateCreateRequest": {
        "type": "object",
        "required": [
          "name",
          "tasks"
        ],
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "legal_entity_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "department_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "employment_type": {
            "$ref": "#/components/schemas/EmploymentType"
          },
          "is_default": {
            "type": "boolean",
            "default": false
          },
          "is_active": {
            "type": "boolean",
            "default": true
          },
          "tasks": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/OnboardingTemplateTask"
            }
          }
        }
      },
      "OnboardingTemplateUpdateRequest": {
        "type": "object",
        "description": "Non-retroactive — live onboarding runs keep their already-copied tasks (copy-at-create, db-docs 00 §8). `tasks`, if present, replaces the ordered task list.",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "legal_entity_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "department_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "employment_type": {
            "$ref": "#/components/schemas/EmploymentType"
          },
          "is_default": {
            "type": "boolean"
          },
          "is_active": {
            "type": "boolean"
          },
          "tasks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OnboardingTemplateTask"
            }
          }
        }
      },
      "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"
              }
            }
          }
        }
      },
      "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"
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "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"
      },
      "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
            }
          }
        }
      },
      "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"
        ]
      },
      "CurrencyCode": {
        "type": "string",
        "enum": [
          "INR",
          "SAR"
        ],
        "description": "ISO-4217. A legal entity operates in a single currency (db-docs/00 §6)."
      }
    },
    "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"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Per-principal/route rate limit exceeded.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "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"
            }
          }
        }
      },
      "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"
            }
          }
        }
      },
      "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"
            }
          }
        }
      },
      "PreconditionRequired": {
        "description": "If-Match header absent on a mutation of a versioned mutable entity (428).",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      }
    },
    "parameters": {
      "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"
        }
      },
      "SortParam": {
        "name": "sort",
        "in": "query",
        "required": false,
        "description": "Comma-separated sort keys; leading `-` = descending. Each key MUST be in the operation's documented sort whitelist (free-form sort is rejected so the keyset cursor stays stable).\n",
        "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
        }
      },
      "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"
        }
      },
      "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"
        }
      },
      "AcceptLanguage": {
        "name": "Accept-Language",
        "in": "header",
        "required": false,
        "description": "Locale for server-rendered/localized text (LocalizedText resolution, letters, notifications). Active locale set comes from the legal entity's compliance pack; KSA tenants default `ar`.\n",
        "schema": {
          "type": "string",
          "enum": [
            "en",
            "ar"
          ],
          "default": "en"
        }
      }
    },
    "headers": {
      "Location": {
        "description": "URI of the created/affected resource.",
        "schema": {
          "type": "string",
          "format": "uri-reference"
        }
      },
      "ETag": {
        "description": "Strong validator of the row `version` (e.g. `\"v7\"`). Use as `If-Match` on the next mutation.",
        "schema": {
          "type": "string"
        }
      },
      "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"
        }
      }
    }
  }
}