{
  "openapi": "3.1.0",
  "info": {
    "title": "GroundIT — Perform & Learn",
    "version": "0.1.0",
    "license": {
      "name": "Proprietary — GroundIT/Sysmedac internal"
    },
    "description": "The growth surface. `perform.*` runs quick + cascaded goals, the 7-step gated appraisal cycle (goal-set → accept → progress → self-review → manager appraisal → 360 → calibration), 360 multi-rater feedback, calibration/normalization sign-off, and continuous 1:1 check-ins / informal feedback. `learn.*` runs the training catalogue, self-enrolment / manager-nomination (routed through the unified approvals inbox, XC-F12), completion & certificate issuance (object storage, XC-F07; expiry/renewal scanned by the jobs tier, XC-F08), and instructor-led session scheduling on a shared training calendar. See ../../api-docs/00-api-overview-and-conventions.md.\n"
  },
  "servers": [
    {
      "url": "/api/v1"
    }
  ],
  "security": [
    {
      "bearerJWT": []
    }
  ],
  "tags": [
    {
      "name": "perform",
      "description": "Goals, the 7-step gated appraisal cycle, 360 feedback, calibration, continuous check-ins."
    },
    {
      "name": "learn",
      "description": "Training catalogue, enrolment/nomination, completion & certifications, calendar & sessions."
    }
  ],
  "x-reuse-anchors": {
    "parameters": {
      "path_id": {
        "$ref": "#/components/parameters/PathId"
      },
      "page_size": {
        "$ref": "#/components/parameters/PageSize"
      },
      "page_after": {
        "$ref": "#/components/parameters/PageAfter"
      },
      "page_before": {
        "$ref": "#/components/parameters/PageBefore"
      },
      "accept_language": {
        "$ref": "#/components/parameters/AcceptLanguage"
      },
      "idempotency_key": {
        "$ref": "#/components/parameters/IdempotencyKey"
      },
      "if_match": {
        "$ref": "#/components/parameters/IfMatch"
      }
    },
    "responses": {
      "unauthorized": {
        "$ref": "#/components/responses/Unauthorized"
      },
      "forbidden": {
        "$ref": "#/components/responses/Forbidden"
      },
      "not_found": {
        "$ref": "#/components/responses/NotFound"
      },
      "conflict": {
        "$ref": "#/components/responses/Conflict"
      },
      "unprocessable": {
        "$ref": "#/components/responses/UnprocessableEntity"
      },
      "locked": {
        "$ref": "#/components/responses/Locked"
      },
      "too_many": {
        "$ref": "#/components/responses/TooManyRequests"
      },
      "precondition_required": {
        "$ref": "#/components/responses/PreconditionRequired"
      },
      "precondition_failed": {
        "$ref": "#/components/responses/PreconditionFailed"
      }
    },
    "headers": {
      "etag": {
        "$ref": "#/components/headers/ETag"
      },
      "location": {
        "$ref": "#/components/headers/Location"
      },
      "idem_replayed": {
        "$ref": "#/components/headers/IdempotencyReplayed"
      }
    }
  },
  "paths": {
    "/perf-cycles": {
      "get": {
        "operationId": "perform.perf_cycle.list",
        "summary": "List performance cycles (own-visible + HR cockpit)",
        "description": "The cycle-discovery read every employee entry point (PRF-S01 active-cycle banner, PRF-S06 timeline) and the HR cockpit grid (PRF-S12) share — same table, widened to tenant scope since cycle config is shared reference data every scoped employee must read (fsd 08 §M1/§W1, db 09 §1 `perf_cycles`).\n",
        "tags": [
          "perform",
          "perf_cycle"
        ],
        "x-token": "perform.perf_cycle.list",
        "x-realizes-features": [
          "PRF-F01",
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S01",
          "PRF-S06",
          "PRF-S12"
        ],
        "x-touches-entities": [
          "perform.perf_cycles"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "legal_entity_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "department_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/CycleStatus"
            }
          },
          {
            "name": "stage",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/CycleStage"
            }
          },
          {
            "name": "fiscal_year",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `period_start`, `-period_start`, `created_at`, `-created_at`. Default `-period_start`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of performance cycles.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PerfCyclePage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "perform.perf_cycle.create",
        "summary": "Create a performance cycle",
        "description": "HR configures a new review cycle window — period, legal-entity/department scope, stage windows, rating scale, and the self-review/360 toggles (PRF-S12 `PT-WIZARD` S1/S2, db 09 §1 `perf_cycles`). Created `DRAFT`; `perform.perf_cycle.publish` moves it `ACTIVE`.\n",
        "tags": [
          "perform",
          "perf_cycle"
        ],
        "x-token": "perform.perf_cycle.create",
        "x-realizes-features": [
          "PRF-F02",
          "PRF-F01"
        ],
        "x-screens": [
          "PRF-S12"
        ],
        "x-touches-entities": [
          "perform.perf_cycles"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PerfCycleCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created performance cycle.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PerfCycle"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/perf-cycles/{id}": {
      "get": {
        "operationId": "perform.perf_cycle.get",
        "summary": "Get one performance cycle",
        "description": "Full cycle config — period, stage, stage_windows, rating_scale (PRF-S01/S06/S12, db 09 §1).",
        "tags": [
          "perform",
          "perf_cycle"
        ],
        "x-token": "perform.perf_cycle.get",
        "x-realizes-features": [
          "PRF-F01",
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S01",
          "PRF-S06",
          "PRF-S12"
        ],
        "x-touches-entities": [
          "perform.perf_cycles"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The performance cycle.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PerfCycle"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "perform.perf_cycle.update",
        "summary": "Update a performance cycle's config",
        "description": "Edits period, stage windows, rating scale, self-review/360 toggles, or weightage-required (PRF-S12 wizard edit). Concurrent HR edits are plausible — versioned (db 09 §1 `perf_cycles`).\n",
        "tags": [
          "perform",
          "perf_cycle"
        ],
        "x-token": "perform.perf_cycle.update",
        "x-realizes-features": [
          "PRF-F02",
          "PRF-F01"
        ],
        "x-screens": [
          "PRF-S12"
        ],
        "x-touches-entities": [
          "perform.perf_cycles"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PerfCycleUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated performance cycle.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PerfCycle"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/perf-cycles/{id}/publish": {
      "post": {
        "operationId": "perform.perf_cycle.publish",
        "summary": "Publish a cycle (DRAFT → ACTIVE, stage GOAL_SETTING)",
        "description": "PRF-S12 `+ New Appraisal Cycle` publish step — opens the cycle to goal-setting (db 09 §1 Lifecycle). Emits `perform.cycle.stage_changed` for reminders (XC-F05) and the dashboard (XC-F09).",
        "tags": [
          "perform",
          "perf_cycle"
        ],
        "x-token": "perform.perf_cycle.publish",
        "x-realizes-features": [
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S12"
        ],
        "x-touches-entities": [
          "perform.perf_cycles"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "perform.cycle.stage_changed",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Published (now ACTIVE) cycle.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PerfCycle"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/perf-cycles/{id}/close": {
      "post": {
        "operationId": "perform.perf_cycle.close",
        "summary": "Close a cycle into calibration (status → CALIBRATING, stage → CALIBRATION)",
        "description": "PRF-S12 `Close Cycle` action (db 09 §1 Lifecycle). Emits `perform.cycle.stage_changed`.",
        "tags": [
          "perform",
          "perf_cycle"
        ],
        "x-token": "perform.perf_cycle.close",
        "x-realizes-features": [
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S12"
        ],
        "x-touches-entities": [
          "perform.perf_cycles"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "perform.cycle.stage_changed",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Closed (now CALIBRATING) cycle.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PerfCycle"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/perf-cycles/{id}/lock-goals": {
      "post": {
        "operationId": "perform.perf_cycle.lock_goals",
        "summary": "Approve & lock this cycle's goals (advance GOAL_ACCEPTANCE → PROGRESS)",
        "description": "PRF-S13 `Approve & Lock` — gated on every cascaded/mandatory goal reaching `ACCEPTED` (fsd 08 PRF-S13, db 09 §1 `perf_cycles` \"each stage advance is gated\"). Emits `perform.cycle.stage_changed`.\n",
        "tags": [
          "perform",
          "perf_cycle"
        ],
        "x-token": "perform.perf_cycle.lock_goals",
        "x-realizes-features": [
          "PRF-F01",
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S13"
        ],
        "x-touches-entities": [
          "perform.perf_cycles",
          "perform.goals"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "perform.cycle.stage_changed",
        "x-rls-scope": "team",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Cycle advanced to PROGRESS.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PerfCycle"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/perf-cycles/{id}/progress": {
      "get": {
        "operationId": "perform.perf_cycle.progress",
        "summary": "Cycle-stage completion status across the org (HR cockpit)",
        "description": "The live completion counters the `PRF-S12` HR cockpit renders — how many of the cycle's participants have reached each stage (goals accepted, self-review submitted, manager review submitted, 360 closed, rating released), plus the achieved rating-band distribution. Deliberately an AGGREGATE: HR must see org-wide completion without reading anyone's individual review body, so this returns counts only — never a rating, a name, or a response. Reserved to TENANT-scoped HR/leadership (the `perform.calibrations` posture of db 09 §1), which is why it carries its own token rather than riding on `perform.perf_cycle.get` — that one is granted to every authenticated employee for the PRF-S01 banner.\n",
        "tags": [
          "perform",
          "perf_cycle"
        ],
        "x-token": "perform.perf_cycle.progress",
        "x-realizes-features": [
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S12"
        ],
        "x-touches-entities": [
          "perform.perf_cycles",
          "perform.goals",
          "perform.self_reviews",
          "perform.manager_reviews",
          "perform.reviews_360"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "department_id",
            "in": "query",
            "required": false,
            "description": "Narrow the cockpit to one department's participants.",
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cycle-stage completion counters for the cockpit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PerfCycleProgress"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/goals": {
      "get": {
        "operationId": "perform.goal.list",
        "summary": "List my goals (mandatory + personal) for the active cycle",
        "description": "PRF-S01 goal list — mandatory (`CASCADED`/`INDIVIDUAL`/`TEAM`) + up to 2 personal `QUICK` goals (fsd 08 PRF-S01, db 09 §1 `goals`).",
        "tags": [
          "perform",
          "goal"
        ],
        "x-token": "perform.goal.list",
        "x-realizes-features": [
          "PRF-F01",
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S01"
        ],
        "x-touches-entities": [
          "perform.goals"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "perf_cycle_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "goal_type",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/GoalType"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/GoalStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `due_date`, `-due_date`, `created_at`. Default `-created_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the caller's own goals.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GoalPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "perform.goal.create",
        "summary": "Create a personal (quick) goal",
        "description": "PRF-S03 — an employee self-sets a lightweight `QUICK` goal, capped at 2 live per cycle (business rule), weight ≤ 15% informational-only, excluded from the Σ=100% check and the overall-achievement denominator (fsd 08 PRF-S03 §1.1a, db 09 §1 `goals`). Quick goals skip `PENDING_ACCEPTANCE` — no approval gate.\n",
        "tags": [
          "perform",
          "goal"
        ],
        "x-token": "perform.goal.create",
        "x-realizes-features": [
          "PRF-F01"
        ],
        "x-screens": [
          "PRF-S03"
        ],
        "x-touches-entities": [
          "perform.goals"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GoalCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created quick goal.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Goal"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/goals/{id}": {
      "get": {
        "operationId": "perform.goal.get",
        "summary": "Get one goal's detail",
        "description": "PRF-S02 — weight/target/achievement, description, and the gated self/manager ratings (fsd 08 PRF-S02, db 09 §1 `goals`). Manager rating is never populated here while `manager_reviews.rating_status = WITHHELD` (§1.3).",
        "tags": [
          "perform",
          "goal"
        ],
        "x-token": "perform.goal.get",
        "x-realizes-features": [
          "PRF-F01",
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S02"
        ],
        "x-touches-entities": [
          "perform.goals",
          "perform.self_reviews",
          "perform.manager_reviews"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Goal detail with gated rating projection.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GoalDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "perform.goal.update",
        "summary": "Edit a personal (quick) goal",
        "description": "PRF-S03 edit mode — title/category/description/target/weight/due_date, pre-acceptance only (fsd 08 PRF-S03). Single-owner draft row — unversioned, low-contention (00 §4 idempotency doc); no If-Match.",
        "tags": [
          "perform",
          "goal"
        ],
        "x-token": "perform.goal.update",
        "x-realizes-features": [
          "PRF-F01"
        ],
        "x-screens": [
          "PRF-S03"
        ],
        "x-touches-entities": [
          "perform.goals"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GoalUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated goal.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Goal"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/goals/accept": {
      "post": {
        "operationId": "perform.goal.accept",
        "summary": "Accept my weighted mandatory goals (stage GOAL_ACCEPTANCE)",
        "description": "PRF-S01 `Accept Goals` — batch-accepts the caller's cascaded/mandatory goals (`PENDING_ACCEPTANCE → ACCEPTED`), stamping `accepted_at` (fsd 08 PRF-S01, db 09 §1 `goals` Lifecycle). Empty `goal_ids` accepts every pending goal in the active cycle.\n",
        "tags": [
          "perform",
          "goal"
        ],
        "x-token": "perform.goal.accept",
        "x-realizes-features": [
          "PRF-F01",
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S01"
        ],
        "x-touches-entities": [
          "perform.goals"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "perform.goal.accepted",
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GoalAcceptRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Accepted goals.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GoalPage"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/goals/team": {
      "get": {
        "operationId": "perform.goal.list_team",
        "summary": "Goal library — team/tenant goals (manager cascade view)",
        "description": "PRF-S13 goal library grid — the cascade tree (self-FK `parent_goal_id`), weightage sums per employee, status (fsd 08 PRF-S13, db 09 §1 `goals`). Widened `x-rls-scope: team` vs the self-scoped `perform.goal.list`, and read by BOTH personas the screen names: a manager sees themselves plus their direct reports, a TENANT-granted HR admin sees the workspace. Returns `TeamGoalPage` — a `GoalPage` whose rows additionally carry the two DERIVED grid columns, `cascade_depth` and `employee_weightage_total`, because neither can be computed correctly from a filtered page (see `TeamGoal`). Additive: every row is still a valid `Goal`.\n",
        "tags": [
          "perform",
          "goal"
        ],
        "x-token": "perform.goal.list_team",
        "x-realizes-features": [
          "PRF-F01",
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S13"
        ],
        "x-touches-entities": [
          "perform.goals"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "team",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "perf_cycle_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "employee_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "department_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "goal_type",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/GoalType"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/GoalStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `employee_id`, `weightage`, `-weightage`, `created_at`. Default `employee_id`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the team/tenant goal library, with the derived grid columns.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamGoalPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/goals/cascade": {
      "post": {
        "operationId": "perform.goal.cascade",
        "summary": "Cascade a weighted objective to a report",
        "description": "PRF-S13 `+ Cascade goal` — a manager/HR admin assigns a `CASCADED`/`INDIVIDUAL`/`TEAM` goal to a report, optionally aligned to a parent objective in the same cycle via `parent_goal_id` (fsd 08 PRF-S13, db 09 §1 `goals`). Created `PENDING_ACCEPTANCE` with `accepted_at` null; the employee accepts it themselves on `PRF-S01` (`perform.goal.accept`). `goal_type: QUICK` is refused with `422` — a quick goal is the employee's own ungated personal goal (PRF-S03) and cascading one would invert every property of a cascade. WEIGHTAGE: enforced as a CEILING, not an equality. When the cycle sets `goal_weightage_required`, a cascade that would take the owner past Σ 100% of non-`QUICK` weightage is `422`; landing them BELOW 100% is legal and expected, because a goal set is authored one goal at a time — the Σ=100% completeness rule is surfaced by the *weightage-balanced* banner (`perform.goal.list_team`'s `employee_weightage_total`) and gated at `perform.perf_cycle.lock_goals`, not by refusing the first goal of a cycle. An `employee_id` or `parent_goal_id` outside the caller's reach is `422` on that field, not `404` — the body is unprocessable, and distinguishing \"absent\" from \"not yours\" would make this a directory oracle.\n",
        "tags": [
          "perform",
          "goal"
        ],
        "x-token": "perform.goal.cascade",
        "x-realizes-features": [
          "PRF-F01",
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S13"
        ],
        "x-touches-entities": [
          "perform.goals"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "team",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GoalCascadeCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created cascaded goal.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Goal"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/goals/{id}/progress-updates": {
      "get": {
        "operationId": "perform.goal_progress.list",
        "summary": "List a goal's progress-update timeline",
        "description": "PRF-S02 Progress Updates timeline — date, note, %, evidence attachment (fsd 08 PRF-S02, db 09 §1 `goal_progress`).",
        "tags": [
          "perform",
          "goal_progress"
        ],
        "x-token": "perform.goal_progress.list",
        "x-realizes-features": [
          "PRF-F01",
          "PRF-F05"
        ],
        "x-screens": [
          "PRF-S02"
        ],
        "x-touches-entities": [
          "perform.goal_progress"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": true,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `recorded_at`, `-recorded_at`. Default `-recorded_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of progress updates for this goal.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GoalProgressPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "perform.goal_progress.create",
        "summary": "Log a progress update against a goal",
        "description": "PRF-S02 `+ Add progress update` (also written by PRF-S11 1:1 check-ins with `source=CHECK_IN`, `checkin_id` set). Re-rolls the parent `goals.progress_pct`/`current_value` in the same transaction (fsd 08 PRF-S02/§1.1b, db 09 §1 `goal_progress`). `evidence_storage_key` accepts a prior presigned-upload key (XC-F07); resolved to a `FileDownload` on read.\n",
        "tags": [
          "perform",
          "goal_progress"
        ],
        "x-token": "perform.goal_progress.create",
        "x-realizes-features": [
          "PRF-F01",
          "PRF-F05"
        ],
        "x-screens": [
          "PRF-S02",
          "PRF-S11"
        ],
        "x-touches-entities": [
          "perform.goal_progress",
          "perform.goals"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": true,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GoalProgressCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created progress update.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GoalProgress"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/self-reviews": {
      "get": {
        "operationId": "perform.self_review.list",
        "summary": "List my self-reviews",
        "description": "PRF-S04/S05/S07 — the caller's own self-review per cycle (unique per employee/cycle, db 09 §1 `self_reviews`).",
        "tags": [
          "perform",
          "self_review"
        ],
        "x-token": "perform.self_review.list",
        "x-realizes-features": [
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S04",
          "PRF-S05",
          "PRF-S07"
        ],
        "x-touches-entities": [
          "perform.self_reviews"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "perf_cycle_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/SelfReviewStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `created_at`, `-created_at`. Default `-created_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the caller's self-reviews.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SelfReviewPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "perform.self_review.create",
        "summary": "Start a self-review for the active cycle",
        "description": "PRF-S04 entry — creates the `DRAFT` self-review row a goal-by-goal response is then saved into (fsd 08 PRF-S04, db 09 §1 `self_reviews`, unique per `(perf_cycle_id, employee_id)`).",
        "tags": [
          "perform",
          "self_review"
        ],
        "x-token": "perform.self_review.create",
        "x-realizes-features": [
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S04"
        ],
        "x-touches-entities": [
          "perform.self_reviews"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SelfReviewCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created (or replayed existing) DRAFT self-review.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SelfReview"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/self-reviews/{id}": {
      "get": {
        "operationId": "perform.self_review.get",
        "summary": "Get one self-review",
        "description": "PRF-S04/S05/S07 — full per-goal responses, achievements, challenges (fsd 08, db 09 §1 `self_reviews`).",
        "tags": [
          "perform",
          "self_review"
        ],
        "x-token": "perform.self_review.get",
        "x-realizes-features": [
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S04",
          "PRF-S05",
          "PRF-S07"
        ],
        "x-touches-entities": [
          "perform.self_reviews"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The self-review.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SelfReview"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "perform.self_review.update",
        "summary": "Save a self-review response (draft)",
        "description": "PRF-S04 `Save & Next` / `Save Draft` — writes one goal's `self_rating`/`comment` into `responses`, or the review-level `achievements`/`challenges`/`development_needs` (fsd 08 PRF-S04, db 09 §1 `self_reviews`). Editable only while `status = DRAFT` and the self-review window is open. Single-owner draft — unversioned, low-contention; no If-Match.\n",
        "tags": [
          "perform",
          "self_review"
        ],
        "x-token": "perform.self_review.update",
        "x-realizes-features": [
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S04"
        ],
        "x-touches-entities": [
          "perform.self_reviews"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SelfReviewUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated self-review.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SelfReview"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/self-reviews/{id}/submit": {
      "post": {
        "operationId": "perform.self_review.submit",
        "summary": "Submit a self-review (irreversible — gates the manager-review stage)",
        "description": "PRF-S05 confirm sheet `Yes, Submit` — `DRAFT → SUBMITTED`, stamps `submitted_at`, rolls up `overall_self_rating`, gates this employee's cycle-stage advance into `MANAGER_REVIEW` (fsd 08 PRF-S05, db 09 §1 `self_reviews` Lifecycle). Immutable to the employee once submitted. Emits `perform.self_review.submitted` (notifies the manager, XC-F05).\n",
        "tags": [
          "perform",
          "self_review"
        ],
        "x-token": "perform.self_review.submit",
        "x-realizes-features": [
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S05"
        ],
        "x-touches-entities": [
          "perform.self_reviews"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "perform.self_review.submitted",
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Submitted self-review.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SelfReview"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/manager-reviews": {
      "get": {
        "operationId": "perform.manager_review.list",
        "summary": "List my manager-appraisal outcomes (gated)",
        "description": "PRF-S07 — the employee's own manager review(s) across cycles. `final_rating`/`final_band` are **never populated** while `rating_status = WITHHELD`; only `RELEASED` rows expose them (fsd 08 PRF-S07 §1.3, db 09 §1 `manager_reviews`).\n",
        "tags": [
          "perform",
          "manager_review"
        ],
        "x-token": "perform.manager_review.list",
        "x-realizes-features": [
          "PRF-F02",
          "PRF-F04"
        ],
        "x-screens": [
          "PRF-S07"
        ],
        "x-touches-entities": [
          "perform.manager_reviews"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "perf_cycle_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "rating_status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/RatingStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `created_at`, `-created_at`. Default `-created_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the caller's manager reviews (gated projection).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ManagerReviewPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/manager-reviews/{id}": {
      "get": {
        "operationId": "perform.manager_review.get",
        "summary": "Get one manager-appraisal outcome (gated)",
        "description": "PRF-S07 detail — status banner, and the released rating/feedback only once `rating_status = RELEASED` (fsd 08 PRF-S07, db 09 §1 `manager_reviews`).",
        "tags": [
          "perform",
          "manager_review"
        ],
        "x-token": "perform.manager_review.get",
        "x-realizes-features": [
          "PRF-F02",
          "PRF-F04"
        ],
        "x-screens": [
          "PRF-S07"
        ],
        "x-touches-entities": [
          "perform.manager_reviews",
          "perform.self_reviews"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Gated manager-review projection.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ManagerReview"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/manager-reviews/team": {
      "get": {
        "operationId": "perform.manager_review.list_for_appraisal",
        "summary": "Team appraisal queue (manager)",
        "description": "PRF-S08 (§M, design-pending) / PRF-S14 (§W) team grid — report, self-rating reference, status, deadline (fsd 08 PRF-S14, db 09 §1 `manager_reviews`). `employee_id <> manager_id` — no self-appraisal. Confined to the appraisals ASSIGNED to the caller (`manager_id`), which is the assignment of record and not the same set as their `people.employees` direct reports; a TENANT-granted caller sees the workspace. Returns `TeamManagerReviewPage` — a `ManagerReviewPage` whose rows additionally carry the DERIVED self-review reference the grid and the drawer's left panel render (see `TeamManagerReview`). Additive: every row is still a valid `ManagerReview`.\n",
        "tags": [
          "perform",
          "manager_review"
        ],
        "x-token": "perform.manager_review.list_for_appraisal",
        "x-realizes-features": [
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S08",
          "PRF-S14"
        ],
        "x-touches-entities": [
          "perform.manager_reviews",
          "perform.self_reviews"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "team",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "perf_cycle_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/ManagerReviewStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `employee_id`, `status`, `created_at`. Default `employee_id`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the manager's appraisal queue, each row carrying its self-review reference.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamManagerReviewPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/manager-reviews/{id}/submit": {
      "post": {
        "operationId": "perform.manager_review.update_and_submit",
        "summary": "Save + submit a manager appraisal into calibration",
        "description": "PRF-S08 (§M) / PRF-S14 (§W) `Submit` — writes per-goal `responses` (rating/comment/achievement), `proposed_rating`/`proposed_band`, `strengths`/`improvement_areas`, and the `promotion_recommended`/`increment_recommended` recommendation toggles, then flips `DRAFT → SUBMITTED` (`rating_status` stays `WITHHELD`) and stamps `submitted_at` (fsd 08 PRF-S08/PRF-S14, db 09 §1 `manager_reviews`). The score is **never** released here — only `perform.calibration.publish` writes `final_*` and flips the gate. Guarded: `employee_id <> manager_id` (no self-appraisal). Emits `perform.manager_review.submitted`.\n",
        "tags": [
          "perform",
          "manager_review"
        ],
        "x-token": "perform.manager_review.update_and_submit",
        "x-realizes-features": [
          "PRF-F02"
        ],
        "x-screens": [
          "PRF-S08",
          "PRF-S14"
        ],
        "x-touches-entities": [
          "perform.manager_reviews"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "perform.manager_review.submitted",
        "x-rls-scope": "team",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ManagerReviewSubmit"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Submitted manager review (rating still WITHHELD).",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ManagerReview"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/manager-reviews/{id}/acknowledge": {
      "post": {
        "operationId": "perform.manager_review.acknowledge",
        "summary": "Acknowledge a released manager rating",
        "description": "PRF-S07 — the employee acknowledges the released rating, stamping `acknowledged_at` (`RELEASED → ACKNOWLEDGED`, fsd 08 PRF-S07, db 09 §1 `manager_reviews` Lifecycle; acknowledge UI design-pending).",
        "tags": [
          "perform",
          "manager_review"
        ],
        "x-token": "perform.manager_review.acknowledge",
        "x-realizes-features": [
          "PRF-F02",
          "PRF-F04"
        ],
        "x-screens": [
          "PRF-S07"
        ],
        "x-touches-entities": [
          "perform.manager_reviews"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Acknowledged manager review.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ManagerReview"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/manager-reviews/{id}/set-calibrated-band": {
      "post": {
        "operationId": "perform.manager_review.set_calibrated_band",
        "summary": "Stage a 9-box placement (calibrated band + potential) for a manager review (pre-release)",
        "description": "PRF-S16 calibration-board grid — one drag onto the 9-box grid, staged in ONE call. It writes `manager_reviews.final_band` (the horizontal performance axis, the editable \"calibrated band\" dropdown) and, optionally, `manager_reviews.potential_band` (the vertical axis, migration `0178`) — both **before** release, which is permitted because the freeze guard only triggers once `rating_status = RELEASED` (db 09 §1 `manager_reviews` Notes). `final_band` is amber-highlighted on the board when it differs from `proposed_band`; an omitted `potential_band` leaves the row's existing placement untouched (and an unplaced row stays in the board's tray). Refused with `409` once the row's rating is `RELEASED` — the DB trigger `perform.freeze_released_rating()` is the backstop. A placement moves every UNRELEASED calibration covering the employee to `IN_REVIEW` in the same transaction — `DRAFT → IN_REVIEW` is fsd 08 PRF-S16 *Actions & transitions*, `REOPENED → IN_REVIEW` is db 09 §1, and **`SIGNED_OFF → IN_REVIEW` is an edge neither states**: it is served because a board that changes stops being the board that was signed, and because no `unsign` operation exists — a group that signed off and then met `perform.calibration.publish`'s underivable-rating `422` would otherwise have no legal move left. A `RELEASED` group is NOT moved (that act is `perform.calibration.reopen`, and it has its own token). Superseded by `perform.calibration.publish`, which commits `final_rating` and flips the gate for every row in the group.\n",
        "tags": [
          "perform",
          "manager_review"
        ],
        "x-token": "perform.manager_review.set_calibrated_band",
        "x-realizes-features": [
          "PRF-F04"
        ],
        "x-screens": [
          "PRF-S16"
        ],
        "x-touches-entities": [
          "perform.manager_reviews",
          "perform.calibrations"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ManagerReviewSetBand"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Manager review with the staged calibrated band.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ManagerReview"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/reviews-360": {
      "get": {
        "operationId": "perform.review_360.list",
        "summary": "List 360 reviews (HR administration)",
        "description": "PRF-S15 grid — subject, status, raters, due date (fsd 08 PRF-S15, db 09 §1 `reviews_360`).",
        "tags": [
          "perform",
          "review_360"
        ],
        "x-token": "perform.review_360.list",
        "x-realizes-features": [
          "PRF-F03"
        ],
        "x-screens": [
          "PRF-S15"
        ],
        "x-touches-entities": [
          "perform.reviews_360"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "perf_cycle_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/Review360Status"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `due_at`, `-due_at`, `created_at`. Default `-created_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of 360 reviews.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Review360Page"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "perform.review_360.create",
        "summary": "Set up a 360 review for a subject",
        "description": "PRF-S15 setup panel — questionnaire config, min_raters, confidentiality (fsd 08 PRF-S15, db 09 §1 `reviews_360`, unique per `(perf_cycle_id, subject_employee_id)`).",
        "tags": [
          "perform",
          "review_360"
        ],
        "x-token": "perform.review_360.create",
        "x-realizes-features": [
          "PRF-F03"
        ],
        "x-screens": [
          "PRF-S15"
        ],
        "x-touches-entities": [
          "perform.reviews_360"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Review360Create"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created 360 review.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Review360"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/reviews-360/team": {
      "get": {
        "operationId": "perform.review_360.list_team",
        "summary": "360 reviews for my team (nominee-approval view)",
        "description": "PRF-S15 read for the **Manager** persona the screen's Access line names for nominee approval (fsd 08 PRF-S15, db 09 §1 `reviews_360` / `review_360_raters`). Widened `x-rls-scope: team` against the tenant-scoped `perform.review_360.list`, and read by BOTH personas the screen names: a manager sees the 360s of their direct reports, a TENANT-granted HR admin sees the workspace. The org-wide container reads (`perform.review_360.list`/`.get`) are deliberately NOT widened — this operation exists so a manager never needs `.get`. Returns `TeamReview360Page` — a `Review360Page` whose rows additionally carry the DERIVED `rater_counts` roll-up (`nominated`/`approved`/`rejected`/`responded`). That roll-up is the point of the additive shape: deciding one nominee needs the subject, status, `min_raters`, questionnaire, due date AND how far collection has got, and making the caller fetch the panel per row would be exactly the per-row round trip `perform.manager_review.list_for_appraisal` refuses. Additive: every row is still a valid `Review360`, so no consumer breaks.\n",
        "tags": [
          "perform",
          "review_360"
        ],
        "x-token": "perform.review_360.list_team",
        "x-realizes-features": [
          "PRF-F03"
        ],
        "x-screens": [
          "PRF-S15"
        ],
        "x-touches-entities": [
          "perform.reviews_360",
          "perform.review_360_raters"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "team",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "perf_cycle_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/Review360Status"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `due_at`, `-due_at`, `created_at`. Default `-created_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the team's 360 reviews, with the nominee roll-up.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TeamReview360Page"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/reviews-360/{id}": {
      "get": {
        "operationId": "perform.review_360.get",
        "summary": "Get one 360 review",
        "description": "PRF-S15 — questionnaire, nominee/rater state, and the anonymized `aggregate_summary` once `COMPLETED` (fsd 08 PRF-S15, db 09 §1 `reviews_360`).",
        "tags": [
          "perform",
          "review_360"
        ],
        "x-token": "perform.review_360.get",
        "x-realizes-features": [
          "PRF-F03"
        ],
        "x-screens": [
          "PRF-S15"
        ],
        "x-touches-entities": [
          "perform.reviews_360"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The 360 review.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Review360"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "perform.review_360.update",
        "summary": "Update a 360 review's config",
        "description": "PRF-S15 — questionnaire/min_raters/is_confidential edits, pre-close (fsd 08 PRF-S15, db 09 §1 `reviews_360`). Multi-admin editable — versioned.",
        "tags": [
          "perform",
          "review_360"
        ],
        "x-token": "perform.review_360.update",
        "x-realizes-features": [
          "PRF-F03"
        ],
        "x-screens": [
          "PRF-S15"
        ],
        "x-touches-entities": [
          "perform.reviews_360"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Review360Update"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated 360 review.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Review360"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/reviews-360/{id}/raters": {
      "get": {
        "operationId": "perform.review_360_rater.list",
        "summary": "List a 360's nominated raters",
        "description": "PRF-S15 nominee-approval region — the panel as nominated, with each row's decision state (fsd 08 PRF-S15, db 09 §1 `review_360_raters`). NEVER served to the subject of the 360: knowing who was asked de-anonymizes the aggregate that comes back, so the RLS overlay on `perform.review_360_raters` is `reviews_360`'s with the subject arm removed (migration 0176).\n",
        "tags": [
          "perform",
          "review_360"
        ],
        "x-token": "perform.review_360_rater.list",
        "x-realizes-features": [
          "PRF-F03"
        ],
        "x-screens": [
          "PRF-S15"
        ],
        "x-touches-entities": [
          "perform.review_360_raters"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "team",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/Review360RaterStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `created_at`, `-created_at`. Default `created_at` (nomination order).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of nominated raters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Review360RaterPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "perform.review_360_rater.nominate",
        "summary": "Nominate a rater onto a 360",
        "description": "PRF-S15 — nominates one rater, `DRAFT → NOMINATION` on the first nomination (fsd 08 PRF-S15, db 09 §1 `review_360_raters`). The acting principal is recorded as `submitted_by`, the MAKER of the maker≠checker pair, which is why nominate and approve are separate operations rather than one write. Validated against the cycle's `rater_group_config`: an unconfigured group, an exceeded `max`, or an `EXTERNAL` rater on a cycle that does not `allow_external` is a 422.\n",
        "tags": [
          "perform",
          "review_360"
        ],
        "x-token": "perform.review_360_rater.nominate",
        "x-realizes-features": [
          "PRF-F03"
        ],
        "x-screens": [
          "PRF-S15"
        ],
        "x-touches-entities": [
          "perform.review_360_raters"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "team",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Review360RaterNominate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Rater nominated.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Review360Rater"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/reviews-360/{id}/raters/{rater_row_id}/approve": {
      "post": {
        "operationId": "perform.review_360_rater.approve",
        "summary": "Approve one nominated rater (four-eyes)",
        "description": "PRF-S15 nominee approval — `NOMINATED → APPROVED`, stamping the acting principal as `approved_by` and `decided_at` (fsd 08 PRF-S15, db 09 §1 `review_360_raters`). **MC-1 (security-docs/04 §1).** The suffix is a bare `approve`, so the classification default bands this token MC-1 with no override; leg 1 is `MakerCheckerKernel.admit()`, which refuses the nominator approving their own nomination with `403 MAKER_EQUALS_CHECKER`, and leg 2 is the `submitted_by <> approved_by` CHECK on the row (migration 0176). The subject of the 360 is additionally refused — a subject may not curate their own rater panel.\n",
        "tags": [
          "perform",
          "review_360"
        ],
        "x-token": "perform.review_360_rater.approve",
        "x-realizes-features": [
          "PRF-F03"
        ],
        "x-screens": [
          "PRF-S15"
        ],
        "x-touches-entities": [
          "perform.review_360_raters"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "team",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "rater_row_id",
            "in": "path",
            "required": true,
            "description": "The `perform.review_360_raters.id` being decided — a row id, not the rater's employee id.",
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Review360RaterDecision"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rater approved onto the panel.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Review360Rater"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/reviews-360/{id}/raters/{rater_row_id}/reject": {
      "post": {
        "operationId": "perform.review_360_rater.reject",
        "summary": "Reject one nominated rater (four-eyes)",
        "description": "PRF-S15 nominee approval — `NOMINATED → REJECTED` with a mandatory `decision_note` (fsd 08 PRF-S15, db 09 §1 `review_360_raters`). **MC-1**, on the same two legs as `.approve`: `approved_by` is the CHECKER column, not the \"approver\" column, so a rejection stamps it too and the `submitted_by <> approved_by` CHECK covers both verdicts. The note is required by the service (422 when blank), not by the schema — the column is nullable because an approval has nothing to explain.\n",
        "tags": [
          "perform",
          "review_360"
        ],
        "x-token": "perform.review_360_rater.reject",
        "x-realizes-features": [
          "PRF-F03"
        ],
        "x-screens": [
          "PRF-S15"
        ],
        "x-touches-entities": [
          "perform.review_360_raters"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "team",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "rater_row_id",
            "in": "path",
            "required": true,
            "description": "The `perform.review_360_raters.id` being decided — a row id, not the rater's employee id.",
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Review360RaterDecision"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rater rejected from the panel.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Review360Rater"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/reviews-360/{id}/approve-nominees": {
      "post": {
        "operationId": "perform.review_360.approve_nominees",
        "summary": "Approve the 360 nominee list (locks it, opens collection)",
        "description": "PRF-S15 nominee approval — `NOMINATION → COLLECTING`, stamps `nominations_closed_at` (fsd 08 PRF-S15, db 09 §1 `reviews_360` Lifecycle).",
        "tags": [
          "perform",
          "review_360"
        ],
        "x-token": "perform.review_360.approve_nominees",
        "x-realizes-features": [
          "PRF-F03"
        ],
        "x-screens": [
          "PRF-S15"
        ],
        "x-touches-entities": [
          "perform.reviews_360"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "360 review now COLLECTING.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Review360"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/reviews-360/{id}/close": {
      "post": {
        "operationId": "perform.review_360.close",
        "summary": "Close a 360 review (compute the anonymized aggregate)",
        "description": "PRF-S15 `Close` — `COLLECTING → COMPLETED → CLOSED`, computes `aggregate_summary` honouring `min_raters` (fsd 08 PRF-S15, db 09 §1 `reviews_360` Lifecycle). Feeds `perform.manager_review.update_and_submit` and the calibration board. Emits `perform.review_360.completed`.",
        "tags": [
          "perform",
          "review_360"
        ],
        "x-token": "perform.review_360.close",
        "x-realizes-features": [
          "PRF-F03"
        ],
        "x-screens": [
          "PRF-S15"
        ],
        "x-touches-entities": [
          "perform.reviews_360"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "perform.review_360.completed",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Closed 360 review with computed aggregate.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Review360"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/feedback": {
      "get": {
        "operationId": "perform.feedback.list",
        "summary": "My feedback feed (given / received)",
        "description": "PRF-S10 continuous-feedback feed, filtered by visibility (fsd 08 PRF-S10, db 09 §1 `feedback`).",
        "tags": [
          "perform",
          "feedback"
        ],
        "x-token": "perform.feedback.list",
        "x-realizes-features": [
          "PRF-F05",
          "PRF-F03"
        ],
        "x-screens": [
          "PRF-S10"
        ],
        "x-touches-entities": [
          "perform.feedback"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": true,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "context",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/FeedbackContext"
            }
          },
          {
            "name": "feedback_type",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/FeedbackType"
            }
          },
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "description": "`given` (rater = caller) or `received` (subject = caller).",
            "schema": {
              "type": "string",
              "enum": [
                "given",
                "received"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `submitted_at`, `-submitted_at`. Default `-submitted_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of feedback visible to the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedbackPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "perform.feedback.create",
        "summary": "Give / respond to feedback",
        "description": "One polymorphic write for all three contexts (fsd 08 PRF-S09/PRF-S10, db 09 §1 `feedback`): a 360 rater's questionnaire answer (`context=REVIEW_360`, `reviews_360_id` set), a check-in note (`context=CHECK_IN`, `checkin_id` set — usually written via `perform.checkin.update`, but exposed here for standalone notes), or standalone continuous praise/constructive/requested feedback (`context=CONTINUOUS`). Not rating-gated. Emits `perform.feedback.submitted`.\n",
        "tags": [
          "perform",
          "feedback"
        ],
        "x-token": "perform.feedback.create",
        "x-realizes-features": [
          "PRF-F03",
          "PRF-F05"
        ],
        "x-screens": [
          "PRF-S09",
          "PRF-S10"
        ],
        "x-touches-entities": [
          "perform.feedback"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "perform.feedback.submitted",
        "x-rls-scope": "self",
        "x-append-only": true,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedbackCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created feedback response.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Feedback"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/feedback/team": {
      "get": {
        "operationId": "perform.feedback.list_team",
        "summary": "Team feedback oversight (manager / HR)",
        "description": "PRF-S17 team feedback view — `MANAGER_ONLY` + `SHARED` visible to the manager; `PRIVATE` never returned (fsd 08 PRF-S17, db 09 §1 `feedback`).",
        "tags": [
          "perform",
          "feedback"
        ],
        "x-token": "perform.feedback.list_team",
        "x-realizes-features": [
          "PRF-F05"
        ],
        "x-screens": [
          "PRF-S17"
        ],
        "x-touches-entities": [
          "perform.feedback"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "team",
        "x-append-only": true,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "subject_employee_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "feedback_type",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/FeedbackType"
            }
          },
          {
            "name": "visibility",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/FeedbackVisibility"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `submitted_at`, `-submitted_at`. Default `-submitted_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of visibility-scoped team feedback.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedbackPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/checkins": {
      "get": {
        "operationId": "perform.checkin.list",
        "summary": "List my 1:1 check-ins",
        "description": "PRF-S11 list — scheduled/completed, for either participant (fsd 08 PRF-S11, db 09 §1 `checkins`).",
        "tags": [
          "perform",
          "checkin"
        ],
        "x-token": "perform.checkin.list",
        "x-realizes-features": [
          "PRF-F05"
        ],
        "x-screens": [
          "PRF-S11"
        ],
        "x-touches-entities": [
          "perform.checkins"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/CheckinStatus"
            }
          },
          {
            "name": "checkin_type",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/CheckinType"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `scheduled_at`, `-scheduled_at`. Default `-scheduled_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the caller's check-ins.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckinPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "perform.checkin.create",
        "summary": "Schedule a 1:1 check-in",
        "description": "PRF-S11 schedule action (fsd 08 PRF-S11, db 09 §1 `checkins`). `perf_cycle_id` optional — 1:1s run between formal cycles too.",
        "tags": [
          "perform",
          "checkin"
        ],
        "x-token": "perform.checkin.create",
        "x-realizes-features": [
          "PRF-F05"
        ],
        "x-screens": [
          "PRF-S11"
        ],
        "x-touches-entities": [
          "perform.checkins"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckinCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created (scheduled) check-in.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Checkin"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/checkins/{id}": {
      "get": {
        "operationId": "perform.checkin.get",
        "summary": "Get one check-in's detail",
        "description": "PRF-S11 detail — agenda, notes, action items, next due (fsd 08 PRF-S11, db 09 §1 `checkins`).",
        "tags": [
          "perform",
          "checkin"
        ],
        "x-token": "perform.checkin.get",
        "x-realizes-features": [
          "PRF-F05"
        ],
        "x-screens": [
          "PRF-S11"
        ],
        "x-touches-entities": [
          "perform.checkins"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The check-in.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Checkin"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "perform.checkin.update",
        "summary": "Edit a check-in (agenda / notes / action items)",
        "description": "PRF-S11 — either participant may edit before completion (fsd 08 PRF-S11, db 09 §1 `checkins`). Two-party edit surface — versioned.",
        "tags": [
          "perform",
          "checkin"
        ],
        "x-token": "perform.checkin.update",
        "x-realizes-features": [
          "PRF-F05"
        ],
        "x-screens": [
          "PRF-S11"
        ],
        "x-touches-entities": [
          "perform.checkins"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckinUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated check-in.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Checkin"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/checkins/{id}/complete": {
      "post": {
        "operationId": "perform.checkin.complete",
        "summary": "Mark a check-in complete",
        "description": "PRF-S11 `Complete` — `SCHEDULED → COMPLETED`, stamps `completed_at`, sets `next_due_at` by cadence (fsd 08 PRF-S11, db 09 §1 `checkins` Lifecycle). Emits `perform.checkin.completed`.",
        "tags": [
          "perform",
          "checkin"
        ],
        "x-token": "perform.checkin.complete",
        "x-realizes-features": [
          "PRF-F05"
        ],
        "x-screens": [
          "PRF-S11"
        ],
        "x-touches-entities": [
          "perform.checkins"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "perform.checkin.completed",
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Completed check-in.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Checkin"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/checkins/team": {
      "get": {
        "operationId": "perform.checkin.list_team",
        "summary": "1:1 history — manager / HR oversight",
        "description": "PRF-S17 1:1 history grid — per report, last check-in, next due, open action items (fsd 08 PRF-S17, db 09 §1 `checkins`).",
        "tags": [
          "perform",
          "checkin"
        ],
        "x-token": "perform.checkin.list_team",
        "x-realizes-features": [
          "PRF-F05"
        ],
        "x-screens": [
          "PRF-S17"
        ],
        "x-touches-entities": [
          "perform.checkins"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "team",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "employee_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/CheckinStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `next_due_at`, `-next_due_at`. Default `next_due_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the team's 1:1 history.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckinPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/calibrations": {
      "get": {
        "operationId": "perform.calibration.list",
        "summary": "List calibration groups",
        "description": "PRF-S16 group selector — calibration sessions per cycle/department (fsd 08 PRF-S16, db 09 §1 `calibrations`).",
        "tags": [
          "perform",
          "calibration"
        ],
        "x-token": "perform.calibration.list",
        "x-realizes-features": [
          "PRF-F04"
        ],
        "x-screens": [
          "PRF-S16"
        ],
        "x-touches-entities": [
          "perform.calibrations"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "perf_cycle_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "department_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/CalibrationStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `created_at`, `-created_at`. Default `-created_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of calibration groups.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalibrationPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "perform.calibration.create",
        "summary": "Create a calibration group",
        "description": "PRF-S16 — a peer group (e.g. \"Engineering · Grade L4\") with a target `distribution_config` bell-curve (fsd 08 PRF-S16, db 09 §1 `calibrations`).",
        "tags": [
          "perform",
          "calibration"
        ],
        "x-token": "perform.calibration.create",
        "x-realizes-features": [
          "PRF-F04"
        ],
        "x-screens": [
          "PRF-S16"
        ],
        "x-touches-entities": [
          "perform.calibrations"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CalibrationCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created calibration group.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Calibration"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/calibrations/{id}": {
      "get": {
        "operationId": "perform.calibration.get",
        "summary": "Get one calibration group (board + distribution)",
        "description": "PRF-S16 board — the bound `manager_reviews` rows (employee, proposed vs calibrated band, the 9-box placement), `distribution_config` (target) vs `actual_distribution` (computed), facilitator/sign-off state (fsd 08 PRF-S16, db 09 §1 `calibrations`). The board rows are a bounded peer-group projection, embedded rather than separately paginated.\n\n**How a review joins a board.** `manager_reviews.calibration_id` is the binding, and nothing writes it until `perform.calibration.publish` — so before release the membership is the PEER GROUP the calibration describes: the same `perf_cycle_id`, the calibration's `department_id` when it has one (resolved against the employee's `people.employees.department_id` — a soft cross-schema ref, no FK), a `manager_reviews.status` of `SUBMITTED`/`IN_CALIBRATION`, and not already bound to a different calibration. Once the group is `RELEASED` the membership is exactly `calibration_id = {id}`, frozen with the ratings it released. A `REOPENED` group shows both: the frozen rows it already released, and any new compensating rows the peer-group predicate picks up.\n",
        "tags": [
          "perform",
          "calibration"
        ],
        "x-token": "perform.calibration.get",
        "x-realizes-features": [
          "PRF-F04"
        ],
        "x-screens": [
          "PRF-S16"
        ],
        "x-touches-entities": [
          "perform.calibrations",
          "perform.manager_reviews"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Calibration group with its board rows.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalibrationDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "perform.calibration.update",
        "summary": "Update a calibration group's config",
        "description": "PRF-S16 — name/department scope/`distribution_config` edits, pre sign-off (fsd 08 PRF-S16, db 09 §1 `calibrations`). Multi-facilitator editable — versioned.",
        "tags": [
          "perform",
          "calibration"
        ],
        "x-token": "perform.calibration.update",
        "x-realizes-features": [
          "PRF-F04"
        ],
        "x-screens": [
          "PRF-S16"
        ],
        "x-touches-entities": [
          "perform.calibrations"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CalibrationUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated calibration group.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Calibration"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/calibrations/{id}/sign-off": {
      "post": {
        "operationId": "perform.calibration.sign_off",
        "summary": "Sign off a calibration group (IN_REVIEW → SIGNED_OFF)",
        "description": "PRF-S16 `Sign off` — HR/leadership only (`facilitator_id`/`signed_off_by`), stamps `signed_off_at` (fsd 08 PRF-S16, db 09 §1 `calibrations` Lifecycle). Does not yet release ratings — `perform.calibration.publish` does.",
        "tags": [
          "perform",
          "calibration"
        ],
        "x-token": "perform.calibration.sign_off",
        "x-realizes-features": [
          "PRF-F04"
        ],
        "x-screens": [
          "PRF-S16"
        ],
        "x-touches-entities": [
          "perform.calibrations"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Signed-off calibration group.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Calibration"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/calibrations/{id}/publish": {
      "post": {
        "operationId": "perform.calibration.publish",
        "summary": "Publish final ratings (SIGNED_OFF → RELEASED) — irreversible gate release",
        "description": "PRF-S16 `Publish Final Ratings` (red, irreversible, impact-preview `PT-MODAL`). For every bound `manager_reviews` row: writes `final_rating`/`final_band`, flips `rating_status` to `RELEASED` (**frozen** by a `BEFORE UPDATE` guard thereafter — which since migration `0178` covers `potential_band`, the 9-box placement, too), stamps `released_at` + `calibration_id`; computes and stores `actual_distribution`; advances the parent `perf_cycles.stage` to `RELEASED` and stamps its `ratings_released_at` (fsd 08 PRF-S16, db 09 §1 `calibrations`/`manager_reviews` Lifecycle). `final_rating` is CARRIED FORWARD from `proposed_rating` when calibration left the band where the manager put it, and otherwise derived from the midpoint of the cycle's `rating_scale` band config (`RatingBandConfig.min`/`.max`) for the calibrated band; when neither is available the publish is refused with `422` naming the rows rather than inventing a number, because `manager_reviews_released_complete` requires a non-null `final_rating` and a fabricated one would enter the regulated-fairness record. **The parent cycle's stage advance is unconditional**, so in a cycle carrying several calibration groups the FIRST group to publish moves the whole cycle to `RELEASED` — the FSD and db 09 both specify the advance without qualifying it by group, and a per-group gate would need a cycle-level \"all groups published\" rule that no doc states. Fans out across a bounded but potentially large peer group in one transaction — run **async**. Emits **`perform.calibration.signed`**, consumed by `engage` (ENG-F05) for promotions/salary-revision and the dashboard (XC-F09) — this is the only cross-module hand-off, and it is an event, never a cross-schema write (db 09 §1 \"Relationships & hand-off summary\").\n",
        "tags": [
          "perform",
          "calibration"
        ],
        "x-token": "perform.calibration.publish",
        "x-realizes-features": [
          "PRF-F04"
        ],
        "x-screens": [
          "PRF-S16"
        ],
        "x-touches-entities": [
          "perform.calibrations",
          "perform.manager_reviews",
          "perform.perf_cycles"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "async",
        "x-emits-event": "perform.calibration.signed",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Publish accepted — releases and freezes ratings asynchronously; poll `perform.calibration.get` or await `perform.calibration.signed`.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Calibration"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/calibrations/{id}/reopen": {
      "post": {
        "operationId": "perform.calibration.reopen",
        "summary": "Reopen a released calibration (rare)",
        "description": "PRF-S16 `REOPENED` state — `RELEASED → REOPENED`. A reopened calibration's re-release issues **new compensating `manager_reviews` rows**, never edits frozen ones (fsd 08 PRF-S16, db 09 §1 `calibrations` Lifecycle/`manager_reviews` Notes).\n",
        "tags": [
          "perform",
          "calibration"
        ],
        "x-token": "perform.calibration.reopen",
        "x-realizes-features": [
          "PRF-F04"
        ],
        "x-screens": [
          "PRF-S16"
        ],
        "x-touches-entities": [
          "perform.calibrations"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "perform",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Reopened calibration group.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Calibration"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/training-catalogue": {
      "get": {
        "operationId": "learn.catalogue.list",
        "summary": "Browse the training catalogue",
        "description": "LRN-S01 browse/search (published only for the employee browse path) and LRN-S06 admin grid (all statuses) — same table, tenant-wide discovery data (fsd 08 LRN-S01/LRN-S06, db 09 §2 `training_catalogue`).",
        "tags": [
          "learn",
          "catalogue"
        ],
        "x-token": "learn.catalogue.list",
        "x-realizes-features": [
          "LRN-F01"
        ],
        "x-screens": [
          "LRN-S01",
          "LRN-S06"
        ],
        "x-touches-entities": [
          "learn.training_catalogue"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "legal_entity_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "catalogue_type",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/CatalogueType"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/CatalogueStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `display_order`, `-display_order`, `created_at`. Default `display_order`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of catalogue entries.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrainingCataloguePage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "learn.catalogue.create",
        "summary": "Create a catalogue entry",
        "description": "LRN-S06 — a category/programme/learning-path grouping (fsd 08 LRN-S06, db 09 §2 `training_catalogue`).",
        "tags": [
          "learn",
          "catalogue"
        ],
        "x-token": "learn.catalogue.create",
        "x-realizes-features": [
          "LRN-F01"
        ],
        "x-screens": [
          "LRN-S06"
        ],
        "x-touches-entities": [
          "learn.training_catalogue"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CatalogueCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created catalogue entry.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Catalogue"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/training-catalogue/{id}": {
      "get": {
        "operationId": "learn.catalogue.get",
        "summary": "Get one catalogue entry",
        "description": "LRN-S01/LRN-S06 (fsd 08, db 09 §2 `training_catalogue`).",
        "tags": [
          "learn",
          "catalogue"
        ],
        "x-token": "learn.catalogue.get",
        "x-realizes-features": [
          "LRN-F01"
        ],
        "x-screens": [
          "LRN-S01",
          "LRN-S06"
        ],
        "x-touches-entities": [
          "learn.training_catalogue"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The catalogue entry.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Catalogue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "learn.catalogue.update",
        "summary": "Update a catalogue entry",
        "description": "LRN-S06 — title/description/status/display_order edits (fsd 08 LRN-S06, db 09 §2 `training_catalogue`). Multi-admin editable — versioned.",
        "tags": [
          "learn",
          "catalogue"
        ],
        "x-token": "learn.catalogue.update",
        "x-realizes-features": [
          "LRN-F01"
        ],
        "x-screens": [
          "LRN-S06"
        ],
        "x-touches-entities": [
          "learn.training_catalogue"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CatalogueUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated catalogue entry.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Catalogue"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/courses": {
      "get": {
        "operationId": "learn.course.list",
        "summary": "Browse / search courses",
        "description": "LRN-S01 browse (published only) and LRN-S06 admin grid (all statuses, db 09 §2 `courses`).",
        "tags": [
          "learn",
          "course"
        ],
        "x-token": "learn.course.list",
        "x-realizes-features": [
          "LRN-F01"
        ],
        "x-screens": [
          "LRN-S01",
          "LRN-S06"
        ],
        "x-touches-entities": [
          "learn.courses"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "catalogue_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/CourseMode"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/CourseStatus"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Free-text search over `title`/`skill_tags`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `title`, `created_at`, `-created_at`. Default `-created_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of courses.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CoursePage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "learn.course.create",
        "summary": "Create a course / programme",
        "description": "LRN-S06 `+ New Program` — mode, duration, certificate metadata, cost (fsd 08 LRN-S06, db 09 §2 `courses`).",
        "tags": [
          "learn",
          "course"
        ],
        "x-token": "learn.course.create",
        "x-realizes-features": [
          "LRN-F01"
        ],
        "x-screens": [
          "LRN-S06"
        ],
        "x-touches-entities": [
          "learn.courses"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CourseCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created course.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Course"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/courses/{id}": {
      "get": {
        "operationId": "learn.course.get",
        "summary": "Get one course's detail",
        "description": "LRN-S02 course detail (overview, prerequisites, certificate validity) and LRN-S06 admin edit (fsd 08 LRN-S02/LRN-S06, db 09 §2 `courses`).",
        "tags": [
          "learn",
          "course"
        ],
        "x-token": "learn.course.get",
        "x-realizes-features": [
          "LRN-F01",
          "LRN-F02"
        ],
        "x-screens": [
          "LRN-S02",
          "LRN-S06"
        ],
        "x-touches-entities": [
          "learn.courses"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The course.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Course"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "learn.course.update",
        "summary": "Update a course (incl. publish / archive / retire via status)",
        "description": "LRN-S06 — edits mode/duration/provider/cost/certificate metadata and the `status` lifecycle (`DRAFT`·`PUBLISHED`·`ARCHIVED`·`RETIRED`, fsd 08 LRN-S06, db 09 §2 `courses`). Multi-admin editable — versioned.",
        "tags": [
          "learn",
          "course"
        ],
        "x-token": "learn.course.update",
        "x-realizes-features": [
          "LRN-F01"
        ],
        "x-screens": [
          "LRN-S06"
        ],
        "x-touches-entities": [
          "learn.courses"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CourseUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated course.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Course"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/enrolments": {
      "get": {
        "operationId": "learn.enrolment.list",
        "summary": "My enrolments (my learning)",
        "description": "LRN-S03 — enrolled/in-progress/completed courses + progress (fsd 08 LRN-S03, db 09 §2 `enrolments`).",
        "tags": [
          "learn",
          "enrolment"
        ],
        "x-token": "learn.enrolment.list",
        "x-realizes-features": [
          "LRN-F02"
        ],
        "x-screens": [
          "LRN-S03"
        ],
        "x-touches-entities": [
          "learn.enrolments"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "course_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/EnrolmentStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `due_date`, `-due_date`, `enrolled_at`. Default `-enrolled_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the caller's enrolments.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnrolmentPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "learn.enrolment.create",
        "summary": "Self-enrol in a course",
        "description": "LRN-S02 `Enrol` — seat/prerequisite checks; `ENROLLED` or `WAITLISTED` if full; `session_id` for instructor-led (fsd 08 LRN-S02, db 09 §2 `enrolments`, unique live enrolment per `(course_id, employee_id)`). Emits `learn.enrolment.created`.\n",
        "tags": [
          "learn",
          "enrolment"
        ],
        "x-token": "learn.enrolment.create",
        "x-realizes-features": [
          "LRN-F02"
        ],
        "x-screens": [
          "LRN-S02"
        ],
        "x-touches-entities": [
          "learn.enrolments"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "learn.enrolment.created",
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnrolmentCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created enrolment (ENROLLED or WAITLISTED).",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Enrolment"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/enrolments/{id}/drop": {
      "post": {
        "operationId": "learn.enrolment.drop",
        "summary": "Drop an enrolment",
        "description": "LRN-S03 `Drop` — `status → DROPPED` (fsd 08 LRN-S03, db 09 §2 `enrolments` Lifecycle).",
        "tags": [
          "learn",
          "enrolment"
        ],
        "x-token": "learn.enrolment.drop",
        "x-realizes-features": [
          "LRN-F02"
        ],
        "x-screens": [
          "LRN-S03"
        ],
        "x-touches-entities": [
          "learn.enrolments"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Dropped enrolment.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Enrolment"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/enrolments/admin": {
      "get": {
        "operationId": "learn.enrolment.list_admin",
        "summary": "Per-course enrolment roster (L&D / manager)",
        "description": "LRN-S07 roster grid — employee, status, attendance, score, certificate status (fsd 08 LRN-S07, db 09 §2 `enrolments`). Widened `x-rls-scope: team` vs the self-scoped `learn.enrolment.list`.",
        "tags": [
          "learn",
          "enrolment"
        ],
        "x-token": "learn.enrolment.list_admin",
        "x-realizes-features": [
          "LRN-F02"
        ],
        "x-screens": [
          "LRN-S07"
        ],
        "x-touches-entities": [
          "learn.enrolments"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "team",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "course_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "session_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/EnrolmentStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `employee_id`, `status`, `enrolled_at`. Default `enrolled_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the roster.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnrolmentPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/enrolments/{id}": {
      "patch": {
        "operationId": "learn.enrolment.update_admin",
        "summary": "Manage a roster enrolment (add/remove, status)",
        "description": "LRN-S07 roster management — status/source edits (fsd 08 LRN-S07, db 09 §2 `enrolments`). Admin-managed shared roster row — versioned.",
        "tags": [
          "learn",
          "enrolment"
        ],
        "x-token": "learn.enrolment.update_admin",
        "x-realizes-features": [
          "LRN-F02"
        ],
        "x-screens": [
          "LRN-S07"
        ],
        "x-touches-entities": [
          "learn.enrolments"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "team",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnrolmentUpdateAdmin"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated enrolment.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Enrolment"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/nominations": {
      "get": {
        "operationId": "learn.nomination.list",
        "summary": "My nominations (pending / accepted)",
        "description": "LRN-S03 nomination cards — `PENDING_APPROVAL`/`APPROVED` awaiting my accept (fsd 08 LRN-S03, db 09 §2 `nominations`).",
        "tags": [
          "learn",
          "nomination"
        ],
        "x-token": "learn.nomination.list",
        "x-realizes-features": [
          "LRN-F02"
        ],
        "x-screens": [
          "LRN-S03"
        ],
        "x-touches-entities": [
          "learn.nominations"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/NominationStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `created_at`, `-created_at`. Default `-created_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the caller's nominations.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NominationPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "learn.nomination.create",
        "summary": "Nominate an employee into a course",
        "description": "LRN-S07 `Nominate` — routes through the unified approvals inbox (XC-F12), seat/prerequisite checks (fsd 08 LRN-S07, db 09 §2 `nominations`, unique live nomination per `(course_id, nominee_id)`).",
        "tags": [
          "learn",
          "nomination"
        ],
        "x-token": "learn.nomination.create",
        "x-realizes-features": [
          "LRN-F02"
        ],
        "x-screens": [
          "LRN-S07"
        ],
        "x-touches-entities": [
          "learn.nominations"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "team",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NominationCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created nomination (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/Nomination"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/nominations/for-approval": {
      "get": {
        "operationId": "learn.nomination.list_for_approval",
        "summary": "Nomination approvals queue (manager / L&D)",
        "description": "LRN-S07 nomination approvals queue — maker ≠ checker (XC-F12, fsd 08 LRN-S07, db 09 §2 `nominations`).",
        "tags": [
          "learn",
          "nomination"
        ],
        "x-token": "learn.nomination.list_for_approval",
        "x-realizes-features": [
          "LRN-F02"
        ],
        "x-screens": [
          "LRN-S07"
        ],
        "x-touches-entities": [
          "learn.nominations"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "team",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "course_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `created_at`, `-created_at`. Default `created_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of pending nominations.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NominationPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/nominations/{id}/approve": {
      "post": {
        "operationId": "learn.nomination.approve",
        "summary": "Approve a nomination (creates the enrolment)",
        "description": "LRN-S07 — `PENDING_APPROVAL → APPROVED`, creates a `learn.enrolments` row (`source=NOMINATION`) in the same transaction (fsd 08 LRN-S07, db 09 §2 `nominations` Lifecycle). Emits `learn.nomination.approved`, whose payload carries `decided_by`/`decided_at` since `#1646` so `xc-approval-decision-reconciler` closes the `xc.approval_inbox` envelope this decision was taken against. The unified inbox drawer reaches this same method through `ApprovalSourceActionRouter` (`#1325`), so there is one state machine with two entrances; four-eyes (`nominated_by` may not decide) is enforced here either way.",
        "tags": [
          "learn",
          "nomination"
        ],
        "x-token": "learn.nomination.approve",
        "x-realizes-features": [
          "LRN-F02"
        ],
        "x-screens": [
          "LRN-S07"
        ],
        "x-touches-entities": [
          "learn.nominations",
          "learn.enrolments"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "learn.nomination.approved",
        "x-rls-scope": "team",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Approved nomination.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nomination"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/nominations/{id}/reject": {
      "post": {
        "operationId": "learn.nomination.reject",
        "summary": "Reject a nomination",
        "description": "LRN-S07 — `PENDING_APPROVAL → REJECTED` (fsd 08 LRN-S07, db 09 §2 `nominations` Lifecycle). Emits `learn.nomination.rejected` since `#1646` — before that the reject path wrote NO event at all, so a nomination refused here left its `xc.approval_inbox` envelope `PENDING` for ever. The optional `reason` is not stored (`learn.nominations` has no approver-note column); it travels on the event and lands on the envelope's `decision_note`, which is how the person who was refused gets told why.",
        "tags": [
          "learn",
          "nomination"
        ],
        "x-token": "learn.nomination.reject",
        "x-realizes-features": [
          "LRN-F02"
        ],
        "x-screens": [
          "LRN-S07"
        ],
        "x-touches-entities": [
          "learn.nominations"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "learn.nomination.rejected",
        "x-rls-scope": "team",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NominationRejectRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rejected nomination.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nomination"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/nominations/{id}/accept": {
      "post": {
        "operationId": "learn.nomination.accept",
        "summary": "Accept a nomination (creates my enrolment)",
        "description": "LRN-S02 `Accept nomination` — the nominee accepts an `APPROVED` nomination from a notice, progressing `APPROVED → ENROLLED` and creating the `learn.enrolments` row (fsd 08 LRN-S02, db 09 §2 `nominations` Lifecycle). Emits `learn.enrolment.created`.",
        "tags": [
          "learn",
          "nomination"
        ],
        "x-token": "learn.nomination.accept",
        "x-realizes-features": [
          "LRN-F02"
        ],
        "x-screens": [
          "LRN-S02"
        ],
        "x-touches-entities": [
          "learn.nominations",
          "learn.enrolments"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "learn.enrolment.created",
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Accepted nomination with the created enrolment.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Nomination"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/completions": {
      "get": {
        "operationId": "learn.completion.list",
        "summary": "My completion status",
        "description": "LRN-S04 completion status (result, completed_on, score, fsd 08 LRN-S04, db 09 §2 `completions`).",
        "tags": [
          "learn",
          "completion"
        ],
        "x-token": "learn.completion.list",
        "x-realizes-features": [
          "LRN-F03"
        ],
        "x-screens": [
          "LRN-S04"
        ],
        "x-touches-entities": [
          "learn.completions"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": true,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "course_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "result",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/CompletionResult"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `completed_on`, `-completed_on`. Default `-completed_on`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the caller's completions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompletionPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "learn.completion.create",
        "summary": "Record a completion (mark attendance / mark completed)",
        "description": "Covers LRN-S07 `Mark attendance` (`result=ATTENDED`, `source=MANUAL`, `session_id` set) and LRN-S08 `Mark completed` (`result=PASS`/`FAIL`/`COMPLETED`, `source=MANUAL`, `score` where scored) — the same append-only write (fsd 08 LRN-S07/LRN-S08, db 09 §2 `completions`, unique per `enrolment_id` when present). Flips the parent `learn.enrolments` to `COMPLETED`; a certification course issues a `learn.certifications` row in the same transaction. Emits `learn.course.completed`.\n",
        "tags": [
          "learn",
          "completion"
        ],
        "x-token": "learn.completion.create",
        "x-realizes-features": [
          "LRN-F03",
          "LRN-F04"
        ],
        "x-screens": [
          "LRN-S07",
          "LRN-S08"
        ],
        "x-touches-entities": [
          "learn.completions",
          "learn.enrolments",
          "learn.certifications"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "learn.course.completed",
        "x-rls-scope": "team",
        "x-append-only": true,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompletionCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Recorded completion.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Completion"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/certifications": {
      "get": {
        "operationId": "learn.certification.list",
        "summary": "My certificates",
        "description": "LRN-S04 — title, issuer, issued/expiry, status (fsd 08 LRN-S04, db 09 §2 `certifications`).",
        "tags": [
          "learn",
          "certification"
        ],
        "x-token": "learn.certification.list",
        "x-realizes-features": [
          "LRN-F03"
        ],
        "x-screens": [
          "LRN-S04"
        ],
        "x-touches-entities": [
          "learn.certifications"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/CertificationStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `expiry_date`, `-expiry_date`, `issued_date`. Default `-issued_date`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the caller's certificates.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CertificationPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "learn.certification.upload_external",
        "summary": "Upload an external certificate",
        "description": "LRN-S04 `Upload external certificate` — `source=EXTERNAL_UPLOAD`; `storage_key` accepts a prior presigned-upload key (XC-F07), resolved to a `FileDownload` on read (fsd 08 LRN-S04, db 09 §2 `certifications`).",
        "tags": [
          "learn",
          "certification"
        ],
        "x-token": "learn.certification.upload_external",
        "x-realizes-features": [
          "LRN-F03"
        ],
        "x-screens": [
          "LRN-S04"
        ],
        "x-touches-entities": [
          "learn.certifications"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CertificationUploadExternal"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created (uploaded) certificate.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Certification"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/certifications/{id}/download": {
      "get": {
        "operationId": "learn.certification.download",
        "summary": "Get a presigned certificate download",
        "description": "LRN-S04 card tap → download — mints a time-limited presigned URL for the tamper-evident PDF (XC-F07, fsd 08 LRN-S04, db 09 §2 `certifications`). Bytes never transit the API.",
        "tags": [
          "learn",
          "certification"
        ],
        "x-token": "learn.certification.download",
        "x-realizes-features": [
          "LRN-F03"
        ],
        "x-screens": [
          "LRN-S04"
        ],
        "x-touches-entities": [
          "learn.certifications"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "self",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "Presigned download handle.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileDownloadRef"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/certifications/admin": {
      "get": {
        "operationId": "learn.certification.list_admin",
        "summary": "Certificate register (L&D / HR)",
        "description": "LRN-S08 certificate register — holder, course, issued/expiry, status; an expiry tracker fed by the jobs-tier scan (XC-F08, fsd 08 LRN-S08, db 09 §2 `certifications`).",
        "tags": [
          "learn",
          "certification"
        ],
        "x-token": "learn.certification.list_admin",
        "x-realizes-features": [
          "LRN-F03"
        ],
        "x-screens": [
          "LRN-S08"
        ],
        "x-touches-entities": [
          "learn.certifications"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "employee_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "course_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/CertificationStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `expiry_date`, `-expiry_date`. Default `expiry_date`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the certificate register.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CertificationPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "learn.certification.issue",
        "summary": "Issue an internal certificate",
        "description": "LRN-S08 `Issue / generate certificate` — `source=INTERNAL`, PDF minted via XC-F07, `expiry_date` from `courses.certificate_validity_months` (fsd 08 LRN-S08, db 09 §2 `certifications`). Also the automatic issuance path when `learn.completion.create` closes a certification course.",
        "tags": [
          "learn",
          "certification"
        ],
        "x-token": "learn.certification.issue",
        "x-realizes-features": [
          "LRN-F03"
        ],
        "x-screens": [
          "LRN-S08"
        ],
        "x-touches-entities": [
          "learn.certifications"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": "learn.certification.issued",
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CertificationIssue"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Issued certificate.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Certification"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/certifications/{id}/revoke": {
      "post": {
        "operationId": "learn.certification.revoke",
        "summary": "Revoke a certificate",
        "description": "LRN-S08 `Revoke` — `status → REVOKED` (fsd 08 LRN-S08, db 09 §2 `certifications` Lifecycle).",
        "tags": [
          "learn",
          "certification"
        ],
        "x-token": "learn.certification.revoke",
        "x-realizes-features": [
          "LRN-F03"
        ],
        "x-screens": [
          "LRN-S08"
        ],
        "x-touches-entities": [
          "learn.certifications"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Revoked certificate.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Certification"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/certifications/{id}/renew": {
      "post": {
        "operationId": "learn.certification.renew",
        "summary": "Renew a certificate (new row, renewal chain)",
        "description": "LRN-S08 `Renew` — creates a new certificate with `renewed_from_id` set to this one; the superseded row is marked `RENEWED`, untouched otherwise (fsd 08 LRN-S08, db 09 §2 `certifications` self-FK renewal chain).",
        "tags": [
          "learn",
          "certification"
        ],
        "x-token": "learn.certification.renew",
        "x-realizes-features": [
          "LRN-F03"
        ],
        "x-screens": [
          "LRN-S08"
        ],
        "x-touches-entities": [
          "learn.certifications"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CertificationRenewRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new (renewal) certificate.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Certification"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/training-calendars": {
      "get": {
        "operationId": "learn.training_calendar.list",
        "summary": "List training calendars",
        "description": "LRN-S05 (employee upcoming-sessions scope) and LRN-S09 (L&D scheduling scope), per legal entity (fsd 08, db 09 §2 `training_calendar`).",
        "tags": [
          "learn",
          "training_calendar"
        ],
        "x-token": "learn.training_calendar.list",
        "x-realizes-features": [
          "LRN-F04"
        ],
        "x-screens": [
          "LRN-S05",
          "LRN-S09"
        ],
        "x-touches-entities": [
          "learn.training_calendar"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "legal_entity_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/CalendarStatus"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `fiscal_year`, `-fiscal_year`. Default `-fiscal_year`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of training calendars.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrainingCalendarPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "learn.training_calendar.create",
        "summary": "Create a training calendar",
        "description": "LRN-S09 — a per-entity fiscal-year scheduling container (fsd 08 LRN-S09, db 09 §2 `training_calendar`).",
        "tags": [
          "learn",
          "training_calendar"
        ],
        "x-token": "learn.training_calendar.create",
        "x-realizes-features": [
          "LRN-F04"
        ],
        "x-screens": [
          "LRN-S09"
        ],
        "x-touches-entities": [
          "learn.training_calendar"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TrainingCalendarCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created training calendar.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrainingCalendar"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/training-calendars/{id}": {
      "get": {
        "operationId": "learn.training_calendar.get",
        "summary": "Get one training calendar",
        "description": "LRN-S05/LRN-S09 (fsd 08, db 09 §2 `training_calendar`).",
        "tags": [
          "learn",
          "training_calendar"
        ],
        "x-token": "learn.training_calendar.get",
        "x-realizes-features": [
          "LRN-F04"
        ],
        "x-screens": [
          "LRN-S05",
          "LRN-S09"
        ],
        "x-touches-entities": [
          "learn.training_calendar"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The training calendar.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrainingCalendar"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "learn.training_calendar.update",
        "summary": "Update a training calendar",
        "description": "LRN-S09 — name/period/status edits (fsd 08 LRN-S09, db 09 §2 `training_calendar`). Multi-admin editable — versioned.",
        "tags": [
          "learn",
          "training_calendar"
        ],
        "x-token": "learn.training_calendar.update",
        "x-realizes-features": [
          "LRN-F04"
        ],
        "x-screens": [
          "LRN-S09"
        ],
        "x-touches-entities": [
          "learn.training_calendar"
        ],
        "x-idempotent": true,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TrainingCalendarUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated training calendar.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrainingCalendar"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/training-sessions": {
      "get": {
        "operationId": "learn.training_session.list",
        "summary": "Browse instructor-led sessions (shared calendar)",
        "description": "LRN-S02 (a course's upcoming sessions), LRN-S05 (employee calendar + \"My Sessions\" filter), LRN-S09 (L&D calendar grid) — shared discovery data (fsd 08, db 09 §2 `training_sessions`).",
        "tags": [
          "learn",
          "training_session"
        ],
        "x-token": "learn.training_session.list",
        "x-realizes-features": [
          "LRN-F04"
        ],
        "x-screens": [
          "LRN-S02",
          "LRN-S05",
          "LRN-S09"
        ],
        "x-touches-entities": [
          "learn.training_sessions"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "course_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "training_calendar_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/UuidRef"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/SessionStatus"
            }
          },
          {
            "name": "start_at[from]",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/TimestampRef"
            }
          },
          {
            "name": "start_at[to]",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/TimestampRef"
            }
          },
          {
            "name": "mine",
            "in": "query",
            "required": false,
            "description": "When `true`, restrict to sessions the caller is enrolled in (LRN-S05 \"My Sessions\").",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort whitelist: `start_at`, `-start_at`. Default `start_at`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of sessions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrainingSessionPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "learn.training_session.create",
        "summary": "Schedule an instructor-led session",
        "description": "LRN-S09 `+ Schedule session` — clash & capacity checks (fsd 08 LRN-S09, db 09 §2 `training_sessions`).",
        "tags": [
          "learn",
          "training_session"
        ],
        "x-token": "learn.training_session.create",
        "x-realizes-features": [
          "LRN-F04"
        ],
        "x-screens": [
          "LRN-S09"
        ],
        "x-touches-entities": [
          "learn.training_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": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TrainingSessionCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Scheduled session.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrainingSession"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/training-sessions/{id}": {
      "get": {
        "operationId": "learn.training_session.get",
        "summary": "Get one session's detail",
        "description": "LRN-S02/LRN-S05/LRN-S09 (fsd 08, db 09 §2 `training_sessions`).",
        "tags": [
          "learn",
          "training_session"
        ],
        "x-token": "learn.training_session.get",
        "x-realizes-features": [
          "LRN-F04"
        ],
        "x-screens": [
          "LRN-S02",
          "LRN-S05",
          "LRN-S09"
        ],
        "x-touches-entities": [
          "learn.training_sessions"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          }
        ],
        "responses": {
          "200": {
            "description": "The session.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrainingSession"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "learn.training_session.update",
        "summary": "Update a session (incl. reschedule / cancel via status)",
        "description": "LRN-S09 — venue/instructor/time/capacity edits and the `status` lifecycle incl. `CANCELLED`/`RESCHEDULED` (fsd 08 LRN-S09, db 09 §2 `training_sessions`). On `COMPLETED`, attendees without an existing row get an idempotent `learn.completion.create` post. Multi-admin editable — versioned.",
        "tags": [
          "learn",
          "training_session"
        ],
        "x-token": "learn.training_session.update",
        "x-realizes-features": [
          "LRN-F04"
        ],
        "x-screens": [
          "LRN-S09"
        ],
        "x-touches-entities": [
          "learn.training_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": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "$ref": "#/components/parameters/IfMatch"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TrainingSessionUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated session.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrainingSession"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/training-sessions/{id}/roster": {
      "get": {
        "operationId": "learn.training_session.roster",
        "summary": "Get a session's roster",
        "description": "LRN-S09 roster view — the `learn.enrolments` rows for this `session_id`, plus `enrolled_count`/`waitlist_count` (fsd 08 LRN-S09, db 09 §2 `training_sessions`/`enrolments`).",
        "tags": [
          "learn",
          "training_session"
        ],
        "x-token": "learn.training_session.roster",
        "x-realizes-features": [
          "LRN-F04",
          "LRN-F02"
        ],
        "x-screens": [
          "LRN-S09"
        ],
        "x-touches-entities": [
          "learn.training_sessions",
          "learn.enrolments"
        ],
        "x-idempotent": false,
        "x-market": "both",
        "x-sync-async": "sync",
        "x-emits-event": null,
        "x-rls-scope": "tenant",
        "x-append-only": false,
        "x-entitlement": "learn",
        "x-provisional": null,
        "parameters": [
          {
            "$ref": "#/components/parameters/PathId"
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/PageAfter"
          },
          {
            "$ref": "#/components/parameters/PageBefore"
          }
        ],
        "responses": {
          "200": {
            "description": "Page of the session's roster.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnrolmentPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerJWT": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Product session token. Two mint paths, one contract (ADR 0010): employees/managers authenticate against Keycloak (mobile + web); workspace staff arrive from the One portal via bridge-token SSO (`POST /api/sso/exchange` verifies the platform's Ed25519 token and mints the product session). The token carries IDENTITY ONLY — `sub`, `tenantUid`, `principal_class`, MFA level, session ref, `exp`. Roles/permissions are re-resolved server-side per request. Enforcement is layered: gateway (TLS/WAF/routing only — NEVER trusted for auth) → NestJS auth guard (validates token, builds the request auth-context) → entitlement middleware (subscription-status → feature-flag → numeric-limit, ADR 0009) → `SET LOCAL app.tenant_id` / `app.user_id` → Postgres FORCED RLS. `tenantUid` is NEVER a path, query, or body parameter.\n"
      }
    },
    "schemas": {
      "UuidRef": {
        "$ref": "#/components/schemas/Uuid"
      },
      "TimestampRef": {
        "$ref": "#/components/schemas/Timestamp"
      },
      "DateOnlyRef": {
        "$ref": "#/components/schemas/DateOnly"
      },
      "DecimalHoursRef": {
        "$ref": "#/components/schemas/DecimalHours"
      },
      "RateRef": {
        "$ref": "#/components/schemas/Rate"
      },
      "MoneyRef": {
        "$ref": "#/components/schemas/Money"
      },
      "LocalizedTextRef": {
        "$ref": "#/components/schemas/LocalizedText"
      },
      "HijriDisplayRef": {
        "$ref": "#/components/schemas/HijriDisplay"
      },
      "BusinessNoRef": {
        "$ref": "#/components/schemas/BusinessNo"
      },
      "FileDownloadRef": {
        "$ref": "#/components/schemas/FileDownload"
      },
      "AuditMetaRef": {
        "$ref": "#/components/schemas/AuditMeta"
      },
      "AppendOnlyMetaRef": {
        "$ref": "#/components/schemas/AppendOnlyMeta"
      },
      "CursorPageRef": {
        "$ref": "#/components/schemas/CursorPage"
      },
      "CycleType": {
        "type": "string",
        "enum": [
          "ANNUAL",
          "HALF_YEARLY",
          "QUARTERLY",
          "PROBATION",
          "PROJECT"
        ],
        "description": "perform.cycle_type (db 09 §1 perf_cycles)."
      },
      "CycleStage": {
        "type": "string",
        "enum": [
          "GOAL_SETTING",
          "GOAL_ACCEPTANCE",
          "PROGRESS",
          "SELF_REVIEW",
          "MANAGER_REVIEW",
          "REVIEW_360",
          "CALIBRATION",
          "RELEASED"
        ],
        "description": "perform.cycle_stage — the gated 7-step machine (db 09 §1 perf_cycles)."
      },
      "CycleStatus": {
        "type": "string",
        "enum": [
          "DRAFT",
          "ACTIVE",
          "CALIBRATING",
          "RELEASED",
          "CLOSED",
          "CANCELLED"
        ],
        "description": "perform.cycle_status (db 09 §1 perf_cycles)."
      },
      "GoalType": {
        "type": "string",
        "enum": [
          "CASCADED",
          "INDIVIDUAL",
          "QUICK",
          "TEAM"
        ],
        "description": "perform.goal_type (db 09 §1 goals)."
      },
      "GoalStatus": {
        "type": "string",
        "enum": [
          "DRAFT",
          "PENDING_ACCEPTANCE",
          "ACCEPTED",
          "IN_PROGRESS",
          "COMPLETED",
          "CANCELLED",
          "ARCHIVED"
        ],
        "description": "perform.goal_status (db 09 §1 goals)."
      },
      "ProgressSource": {
        "type": "string",
        "enum": [
          "SELF_UPDATE",
          "CHECK_IN",
          "MANAGER",
          "SYSTEM"
        ],
        "description": "perform.progress_source (db 09 §1 goal_progress)."
      },
      "SelfReviewStatus": {
        "type": "string",
        "enum": [
          "DRAFT",
          "SUBMITTED",
          "RETURNED"
        ],
        "description": "perform.self_review_status (db 09 §1 self_reviews)."
      },
      "ManagerReviewStatus": {
        "type": "string",
        "enum": [
          "DRAFT",
          "SUBMITTED",
          "IN_CALIBRATION",
          "RELEASED",
          "ACKNOWLEDGED"
        ],
        "description": "perform.manager_review_status (db 09 §1 manager_reviews)."
      },
      "RatingStatus": {
        "type": "string",
        "enum": [
          "WITHHELD",
          "RELEASED"
        ],
        "description": "perform.rating_status — the gate (db 09 §1 manager_reviews)."
      },
      "RatingBand": {
        "type": "string",
        "enum": [
          "OUTSTANDING",
          "EXCEEDS",
          "MEETS",
          "PARTIALLY_MEETS",
          "BELOW"
        ],
        "description": "perform.rating_band (db 09 §1 manager_reviews)."
      },
      "PotentialBand": {
        "type": "string",
        "enum": [
          "LOW",
          "MEDIUM",
          "HIGH"
        ],
        "description": "perform.potential_band (db 09 §1 `manager_reviews`, migration `0178`) — the VERTICAL axis of the PRF-S16 9-box calibration grid (design-docs/02 §9, \"drag-and-drop 9-box grid (Performance x Potential)\"). Three values because \"9-box\" means 3 x 3: the horizontal axis stays the five-value `RatingBand`, banded into the grid's three columns by the service so `DistributionConfig`'s per-`rating_band` bell-curve targets keep their meaning. Nullable wherever it appears — a review that was never placed on the grid has no potential, and none can be invented for it (the board renders those in a tray).\n"
      },
      "Review360Status": {
        "type": "string",
        "enum": [
          "DRAFT",
          "NOMINATION",
          "COLLECTING",
          "COMPLETED",
          "CLOSED"
        ],
        "description": "perform.review_360_status (db 09 §1 reviews_360)."
      },
      "FeedbackContext": {
        "type": "string",
        "enum": [
          "REVIEW_360",
          "CHECK_IN",
          "CONTINUOUS"
        ],
        "description": "perform.feedback_context (db 09 §1 feedback)."
      },
      "FeedbackType": {
        "type": "string",
        "enum": [
          "PRAISE",
          "CONSTRUCTIVE",
          "REVIEW_360",
          "REQUESTED"
        ],
        "description": "perform.feedback_type (db 09 §1 feedback)."
      },
      "RaterRelationship": {
        "type": "string",
        "enum": [
          "PEER",
          "MANAGER",
          "REPORT",
          "SELF",
          "SKIP_LEVEL",
          "EXTERNAL"
        ],
        "description": "perform.rater_relationship (db 09 §1 feedback)."
      },
      "FeedbackVisibility": {
        "type": "string",
        "enum": [
          "PRIVATE",
          "MANAGER_ONLY",
          "SHARED"
        ],
        "description": "perform.feedback_visibility (db 09 §1 feedback)."
      },
      "CheckinType": {
        "type": "string",
        "enum": [
          "ONE_ON_ONE",
          "QUARTERLY",
          "AD_HOC"
        ],
        "description": "perform.checkin_type (db 09 §1 checkins)."
      },
      "CheckinStatus": {
        "type": "string",
        "enum": [
          "SCHEDULED",
          "COMPLETED",
          "CANCELLED",
          "MISSED"
        ],
        "description": "perform.checkin_status (db 09 §1 checkins)."
      },
      "CalibrationStatus": {
        "type": "string",
        "enum": [
          "DRAFT",
          "IN_REVIEW",
          "SIGNED_OFF",
          "RELEASED",
          "REOPENED"
        ],
        "description": "perform.calibration_status (db 09 §1 calibrations)."
      },
      "CatalogueType": {
        "type": "string",
        "enum": [
          "CATEGORY",
          "PROGRAMME",
          "LEARNING_PATH"
        ],
        "description": "learn.catalogue_type (db 09 §2 training_catalogue)."
      },
      "CatalogueStatus": {
        "type": "string",
        "enum": [
          "DRAFT",
          "PUBLISHED",
          "ARCHIVED"
        ],
        "description": "learn.catalogue_status (db 09 §2 training_catalogue)."
      },
      "CourseMode": {
        "type": "string",
        "enum": [
          "SELF_PACED",
          "INSTRUCTOR_LED",
          "EXTERNAL",
          "BLENDED"
        ],
        "description": "learn.course_mode (db 09 §2 courses)."
      },
      "CourseStatus": {
        "type": "string",
        "enum": [
          "DRAFT",
          "PUBLISHED",
          "ARCHIVED",
          "RETIRED"
        ],
        "description": "learn.course_status (db 09 §2 courses)."
      },
      "EnrolmentSource": {
        "type": "string",
        "enum": [
          "SELF",
          "NOMINATION",
          "MANDATORY"
        ],
        "description": "learn.enrolment_source (db 09 §2 enrolments)."
      },
      "EnrolmentStatus": {
        "type": "string",
        "enum": [
          "WAITLISTED",
          "ENROLLED",
          "IN_PROGRESS",
          "COMPLETED",
          "DROPPED",
          "CANCELLED"
        ],
        "description": "learn.enrolment_status (db 09 §2 enrolments)."
      },
      "NominationStatus": {
        "type": "string",
        "enum": [
          "PENDING_APPROVAL",
          "APPROVED",
          "REJECTED",
          "WITHDRAWN",
          "ENROLLED",
          "EXPIRED"
        ],
        "description": "learn.nomination_status (db 09 §2 nominations)."
      },
      "CompletionResult": {
        "type": "string",
        "enum": [
          "PASS",
          "FAIL",
          "COMPLETED",
          "ATTENDED",
          "INCOMPLETE"
        ],
        "description": "learn.completion_result (db 09 §2 completions)."
      },
      "CompletionSource": {
        "type": "string",
        "enum": [
          "SYSTEM",
          "MANUAL",
          "EXTERNAL"
        ],
        "description": "learn.completion_source (db 09 §2 completions)."
      },
      "CertificationSource": {
        "type": "string",
        "enum": [
          "INTERNAL",
          "EXTERNAL_UPLOAD"
        ],
        "description": "learn.certification_source (db 09 §2 certifications)."
      },
      "CertificationStatus": {
        "type": "string",
        "enum": [
          "ACTIVE",
          "EXPIRING_SOON",
          "EXPIRED",
          "REVOKED",
          "RENEWED",
          "SUPERSEDED"
        ],
        "description": "learn.certification_status (db 09 §2 certifications)."
      },
      "CalendarStatus": {
        "type": "string",
        "enum": [
          "ACTIVE",
          "ARCHIVED"
        ],
        "description": "learn.calendar_status (db 09 §2 training_calendar)."
      },
      "SessionMode": {
        "type": "string",
        "enum": [
          "CLASSROOM",
          "VIRTUAL",
          "HYBRID"
        ],
        "description": "learn.session_mode (db 09 §2 training_sessions)."
      },
      "SessionStatus": {
        "type": "string",
        "enum": [
          "SCHEDULED",
          "OPEN",
          "FULL",
          "IN_PROGRESS",
          "COMPLETED",
          "CANCELLED",
          "RESCHEDULED"
        ],
        "description": "learn.session_status (db 09 §2 training_sessions)."
      },
      "StageWindow": {
        "type": "object",
        "description": "One stage's open/close window (db 09 §1 perf_cycles.stage_windows shape).",
        "properties": {
          "start": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "end": {
            "$ref": "#/components/schemas/DateOnlyRef"
          }
        }
      },
      "StageWindows": {
        "type": "object",
        "description": "perf_cycles.stage_windows — per-stage open/close windows distinct from period_* (db 09 §1, fsd 08 §1.1c).",
        "properties": {
          "goal_setting": {
            "$ref": "#/components/schemas/StageWindow"
          },
          "self_review": {
            "$ref": "#/components/schemas/StageWindow"
          },
          "manager_review": {
            "$ref": "#/components/schemas/StageWindow"
          },
          "review_360": {
            "$ref": "#/components/schemas/StageWindow"
          }
        }
      },
      "RatingBandConfig": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "label": {
            "$ref": "#/components/schemas/LocalizedTextRef"
          },
          "min": {
            "type": "number"
          },
          "max": {
            "type": "number"
          },
          "order": {
            "type": "integer"
          }
        }
      },
      "RatingScale": {
        "type": "object",
        "description": "perf_cycles.rating_scale — the cycle's configured rating bands/labels (db 09 §1).",
        "properties": {
          "bands": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RatingBandConfig"
            }
          },
          "scale_max": {
            "type": "number"
          }
        }
      },
      "PerfCycle": {
        "description": "perform.perf_cycles — the review-cycle window carrying the 7-step stage machine (db 09 §1).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "cycle_no",
              "name",
              "legal_entity_id",
              "cycle_type",
              "fiscal_year",
              "period_start",
              "period_end",
              "stage",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "cycle_no": {
                "$ref": "#/components/schemas/BusinessNoRef"
              },
              "name": {
                "type": "string"
              },
              "legal_entity_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "department_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "cycle_type": {
                "$ref": "#/components/schemas/CycleType"
              },
              "fiscal_year": {
                "type": "integer"
              },
              "period_start": {
                "$ref": "#/components/schemas/DateOnlyRef"
              },
              "period_end": {
                "$ref": "#/components/schemas/DateOnlyRef"
              },
              "period_start_hijri": {
                "$ref": "#/components/schemas/HijriDisplayRef"
              },
              "period_end_hijri": {
                "$ref": "#/components/schemas/HijriDisplayRef"
              },
              "stage": {
                "$ref": "#/components/schemas/CycleStage"
              },
              "status": {
                "$ref": "#/components/schemas/CycleStatus"
              },
              "rating_scale": {
                "$ref": "#/components/schemas/RatingScale"
              },
              "stage_windows": {
                "$ref": "#/components/schemas/StageWindows"
              },
              "rater_group_config": {
                "$ref": "#/components/schemas/RaterGroupConfig"
              },
              "self_review_enabled": {
                "type": "boolean"
              },
              "review_360_enabled": {
                "type": "boolean"
              },
              "goal_weightage_required": {
                "type": "boolean"
              },
              "ratings_released_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "PerfCycleCreate": {
        "type": "object",
        "required": [
          "name",
          "legal_entity_id",
          "cycle_type",
          "fiscal_year",
          "period_start",
          "period_end"
        ],
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string"
          },
          "legal_entity_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "department_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "cycle_type": {
            "$ref": "#/components/schemas/CycleType"
          },
          "fiscal_year": {
            "type": "integer"
          },
          "period_start": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "period_end": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "rating_scale": {
            "$ref": "#/components/schemas/RatingScale"
          },
          "stage_windows": {
            "$ref": "#/components/schemas/StageWindows"
          },
          "rater_group_config": {
            "$ref": "#/components/schemas/RaterGroupConfig"
          },
          "self_review_enabled": {
            "type": "boolean",
            "default": true
          },
          "review_360_enabled": {
            "type": "boolean",
            "default": false
          },
          "goal_weightage_required": {
            "type": "boolean",
            "default": true
          }
        }
      },
      "PerfCycleUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string"
          },
          "department_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "period_start": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "period_end": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "rating_scale": {
            "$ref": "#/components/schemas/RatingScale"
          },
          "stage_windows": {
            "$ref": "#/components/schemas/StageWindows"
          },
          "rater_group_config": {
            "$ref": "#/components/schemas/RaterGroupConfig"
          },
          "self_review_enabled": {
            "type": "boolean"
          },
          "review_360_enabled": {
            "type": "boolean"
          },
          "goal_weightage_required": {
            "type": "boolean"
          }
        }
      },
      "PerfCycleStageCounter": {
        "type": "object",
        "description": "One stage's completion counter — how many participants have cleared it.",
        "required": [
          "stage",
          "completed",
          "total"
        ],
        "properties": {
          "stage": {
            "$ref": "#/components/schemas/CycleStage"
          },
          "completed": {
            "type": "integer"
          },
          "total": {
            "type": "integer"
          }
        }
      },
      "PerfCycleProgress": {
        "type": "object",
        "description": "PRF-S12 cockpit aggregate — counts only, never per-employee detail (see the operation description). `band_distribution` counts `manager_reviews.final_band` for released rows and `proposed_band` for the rest, so the cockpit can show the shape of the curve mid-cycle.\n",
        "required": [
          "perf_cycle_id",
          "stage",
          "status",
          "participant_count",
          "stages",
          "band_distribution"
        ],
        "properties": {
          "perf_cycle_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "stage": {
            "$ref": "#/components/schemas/CycleStage"
          },
          "status": {
            "$ref": "#/components/schemas/CycleStatus"
          },
          "participant_count": {
            "type": "integer"
          },
          "stages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PerfCycleStageCounter"
            }
          },
          "band_distribution": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          },
          "goals_pending_acceptance": {
            "type": "integer"
          },
          "ratings_released_count": {
            "type": "integer"
          }
        }
      },
      "PerfCyclePage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PerfCycle"
                }
              }
            }
          }
        ]
      },
      "Goal": {
        "description": "perform.goals — a SMART objective, cascaded or self-set (db 09 §1).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "perf_cycle_id",
              "employee_id",
              "title",
              "goal_type",
              "progress_pct",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "perf_cycle_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "parent_goal_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "employee_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "title": {
                "type": "string"
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "category": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Tenant-config theme (added for FSD 08 §1.1a)."
              },
              "goal_type": {
                "$ref": "#/components/schemas/GoalType"
              },
              "weightage": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/RateRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Percentage weight as a fraction-of-100 rate string; QUICK goals are informational only (excluded from the Σ=100% check)."
              },
              "target_value": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "current_value": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "metric_unit": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "progress_pct": {
                "$ref": "#/components/schemas/RateRef"
              },
              "status": {
                "$ref": "#/components/schemas/GoalStatus"
              },
              "start_date": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DateOnlyRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "due_date": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DateOnlyRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "accepted_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "GoalRatingProjection": {
        "type": "object",
        "readOnly": true,
        "description": "The gated per-goal self/manager rating pair for `PRF-S02`. `manager_rating` is `null` while the bound `manager_reviews.rating_status = WITHHELD` (fsd 08 PRF-S02 §1.3) — never populated by this or any read operation until calibration releases it.\n",
        "properties": {
          "self_rating": {
            "type": [
              "number",
              "null"
            ]
          },
          "self_comment": {
            "type": [
              "string",
              "null"
            ]
          },
          "manager_rating": {
            "type": [
              "number",
              "null"
            ]
          },
          "manager_rating_released": {
            "type": "boolean",
            "description": "true once rating_status = RELEASED."
          }
        }
      },
      "GoalDetail": {
        "description": "PRF-S02 goal detail — the goal plus the gated self/manager rating projection.",
        "allOf": [
          {
            "$ref": "#/components/schemas/Goal"
          },
          {
            "type": "object",
            "properties": {
              "rating": {
                "$ref": "#/components/schemas/GoalRatingProjection"
              },
              "rating_guide": {
                "$ref": "#/components/schemas/RatingScale"
              }
            }
          }
        ]
      },
      "GoalPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Goal"
                }
              }
            }
          }
        ]
      },
      "TeamGoal": {
        "description": "A `Goal` as the `PRF-S13` goal-library grid renders it — the goal itself plus the two DERIVED columns the screen shows and no single row can carry: its depth in the cascade tree, and its owner's total weightage for the cycle. STRICTLY ADDITIVE: every `TeamGoal` is a valid `Goal`, so a consumer coded against `Goal`/`GoalPage` is unaffected and simply ignores the extras. Both are computed server-side because neither is computable from a page: `parent_goal_id` chains and weightage sums both reach rows the caller's current filter and page window exclude (added in #221 with `perform.goal.list_team`'s implementation).\n",
        "allOf": [
          {
            "$ref": "#/components/schemas/Goal"
          },
          {
            "type": "object",
            "properties": {
              "employee_name": {
                "type": [
                  "string",
                  "null"
                ],
                "readOnly": true,
                "description": "ref→people.employees.full_name (employee_id), by projection (not a join) — the grid is a list of OTHER people's goals, and carried no identity but the uuid (issue #1640). By projection because the operation is stamped `TEAM` for a non-tenant-wide caller, where the employees ownership overlay would blank a join. `null` when the name cannot be resolved."
              },
              "employee_no": {
                "type": [
                  "string",
                  "null"
                ],
                "readOnly": true,
                "description": "ref→people.employees.employee_no (employee_id), by the same projection (issue #1640)."
              },
              "cascade_depth": {
                "type": "integer",
                "readOnly": true,
                "minimum": 0,
                "description": "Ancestors above this goal in the `parent_goal_id` tree — 0 for a top-level objective. Counts only ancestors the CALLER can see; a chain leaving their row visibility stops there."
              },
              "employee_weightage_total": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/RateRef"
                  }
                ],
                "readOnly": true,
                "description": "Σ `weightage` over ALL of this owner's non-`QUICK`, non-`CANCELLED`/`ARCHIVED` goals in this cycle — the figure the *weightage-balanced* banner reads. Independent of the page filters, deliberately."
              }
            }
          }
        ]
      },
      "TeamGoalPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TeamGoal"
                }
              }
            }
          }
        ]
      },
      "GoalCreate": {
        "type": "object",
        "required": [
          "perf_cycle_id",
          "title",
          "category",
          "description"
        ],
        "additionalProperties": false,
        "properties": {
          "perf_cycle_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "title": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "target_value": {
            "type": "string"
          },
          "metric_unit": {
            "type": "string"
          },
          "weightage": {
            "$ref": "#/components/schemas/RateRef"
          },
          "due_date": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "save_as_draft": {
            "type": "boolean",
            "default": false,
            "description": "true → status DRAFT; false → skips PENDING_ACCEPTANCE (quick goals have no approval gate, db 09 §1)."
          }
        }
      },
      "GoalUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "target_value": {
            "type": "string"
          },
          "metric_unit": {
            "type": "string"
          },
          "weightage": {
            "$ref": "#/components/schemas/RateRef"
          },
          "due_date": {
            "$ref": "#/components/schemas/DateOnlyRef"
          }
        }
      },
      "GoalAcceptRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "goal_ids": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UuidRef"
            },
            "description": "Empty or omitted accepts every PENDING_ACCEPTANCE goal in the active cycle."
          }
        }
      },
      "GoalCascadeCreate": {
        "type": "object",
        "required": [
          "perf_cycle_id",
          "employee_id",
          "goal_type",
          "title",
          "weightage"
        ],
        "additionalProperties": false,
        "properties": {
          "perf_cycle_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "parent_goal_id": {
            "$ref": "#/components/schemas/UuidRef",
            "description": "The parent objective this goal aligns to (the cascade self-FK). Must be in the SAME cycle — the library grid and its `cascade_depth` column are cycle-scoped."
          },
          "employee_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "goal_type": {
            "$ref": "#/components/schemas/GoalType",
            "description": "`CASCADED` · `INDIVIDUAL` · `TEAM`. `QUICK` is refused (422): a quick goal is the employee's own ungated personal goal (PRF-S03), excluded from the Σ=100% rule."
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "category": {
            "type": "string",
            "description": "Tenant-config goal category / theme (e.g. Skill Development / Process / Leadership) — the same field `GoalCreate` carries, set at authoring time (fsd 08 §1.1a, db 09 §1 `goals.category`). Added in #221; the cascade body had omitted it."
          },
          "weightage": {
            "$ref": "#/components/schemas/RateRef"
          },
          "target_value": {
            "type": "string"
          },
          "metric_unit": {
            "type": "string"
          },
          "due_date": {
            "$ref": "#/components/schemas/DateOnlyRef"
          }
        }
      },
      "GoalProgress": {
        "description": "perform.goal_progress — a progress update logged against a goal (db 09 §1, append-only).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "goal_id",
              "progress_pct",
              "source",
              "recorded_at"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "goal_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "checkin_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "progress_pct": {
                "$ref": "#/components/schemas/RateRef"
              },
              "progress_value": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "source": {
                "$ref": "#/components/schemas/ProgressSource"
              },
              "note": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "evidence": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/FileDownloadRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Presigned attachment (XC-F07); never a raw storage key."
              },
              "recorded_by": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "recorded_at": {
                "$ref": "#/components/schemas/TimestampRef"
              }
            }
          },
          {
            "$ref": "#/components/schemas/AppendOnlyMetaRef"
          }
        ]
      },
      "GoalProgressPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/GoalProgress"
                }
              }
            }
          }
        ]
      },
      "GoalProgressCreate": {
        "type": "object",
        "required": [
          "progress_pct"
        ],
        "additionalProperties": false,
        "properties": {
          "progress_pct": {
            "$ref": "#/components/schemas/RateRef"
          },
          "progress_value": {
            "type": "string"
          },
          "source": {
            "$ref": "#/components/schemas/ProgressSource"
          },
          "checkin_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "note": {
            "type": "string"
          },
          "evidence_storage_key": {
            "type": [
              "string",
              "null"
            ],
            "description": "Object-storage key returned by a prior presigned-upload flow (XC-F07); the API resolves this to a FileDownload on read."
          }
        }
      },
      "SelfReviewResponseItem": {
        "type": "object",
        "properties": {
          "goal_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "competency": {
            "type": "string"
          },
          "self_rating": {
            "type": "number"
          },
          "comment": {
            "type": "string"
          }
        }
      },
      "SelfReview": {
        "description": "perform.self_reviews — the employee self-appraisal for a cycle (db 09 §1).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "perf_cycle_id",
              "employee_id",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "perf_cycle_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "employee_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "status": {
                "$ref": "#/components/schemas/SelfReviewStatus"
              },
              "overall_self_rating": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "responses": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SelfReviewResponseItem"
                }
              },
              "achievements": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "challenges": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "development_needs": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "submitted_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "SelfReviewPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SelfReview"
                }
              }
            }
          }
        ]
      },
      "SelfReviewCreate": {
        "type": "object",
        "required": [
          "perf_cycle_id"
        ],
        "additionalProperties": false,
        "properties": {
          "perf_cycle_id": {
            "$ref": "#/components/schemas/UuidRef"
          }
        }
      },
      "SelfReviewUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "responses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SelfReviewResponseItem"
            }
          },
          "achievements": {
            "type": "string"
          },
          "challenges": {
            "type": "string"
          },
          "development_needs": {
            "type": "string"
          }
        }
      },
      "ManagerReviewResponseItem": {
        "type": "object",
        "properties": {
          "goal_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "competency": {
            "type": "string"
          },
          "rating": {
            "type": "number"
          },
          "weight": {
            "type": "number"
          },
          "achievement": {
            "type": [
              "string",
              "null"
            ],
            "description": "\"Agreed achievement\" — Not Met · Partially Met · Met · Exceeded · Exceptional (fsd 08 PRF-S14)."
          },
          "comment": {
            "type": "string"
          }
        }
      },
      "ManagerReview": {
        "description": "perform.manager_reviews — the manager's appraisal (db 09 §1). `final_rating`/`final_band` are `null` and `strengths`/`improvement_areas`/`responses` are withheld from a self-scoped read while `rating_status = WITHHELD` — only `RELEASED` rows expose the released fields (fsd 08 PRF-S07 §1.3).\n",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "perf_cycle_id",
              "employee_id",
              "manager_id",
              "status",
              "rating_status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "perf_cycle_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "self_review_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "calibration_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "employee_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "manager_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "status": {
                "$ref": "#/components/schemas/ManagerReviewStatus"
              },
              "proposed_rating": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "proposed_band": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/RatingBand"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "final_rating": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Released & frozen on calibration sign-off; null while WITHHELD."
              },
              "final_band": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/RatingBand"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "potential_band": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/PotentialBand"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "PRF-S16 9-box vertical axis (migration 0178). Staged by perform.manager_review.set_calibrated_band and FROZEN with the rest of the released rating by perform.freeze_released_rating(); null = never placed on the grid."
              },
              "rating_status": {
                "$ref": "#/components/schemas/RatingStatus"
              },
              "responses": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ManagerReviewResponseItem"
                }
              },
              "strengths": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "improvement_areas": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "promotion_recommended": {
                "type": "boolean"
              },
              "increment_recommended": {
                "type": "boolean"
              },
              "submitted_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "released_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "acknowledged_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "ManagerReviewPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ManagerReview"
                }
              }
            }
          }
        ]
      },
      "TeamManagerReview": {
        "description": "A `ManagerReview` as the `PRF-S14` team-appraisal grid renders it — the appraisal itself plus the DERIVED **self-review reference** the screen shows beside it: the grid's \"self rating\" column and the read-only left panel of the 700px drawer (fsd 08 PRF-S14). STRICTLY ADDITIVE: every `TeamManagerReview` is a valid `ManagerReview`, so a consumer coded against `ManagerReview`/`ManagerReviewPage` is unaffected and simply ignores the extras. Read server-side from the bound `perform.self_reviews` row in one query per page (this operation's `x-touches-entities` names it); all seven are `null`/empty when the employee has no self-review on file — a cycle with `self_review_enabled: false`, or one never started. NB the EMPLOYEE's self-rating is not gated (db 09 §1); only the manager's is (added in #222 with `perform.manager_review.list_for_appraisal`'s implementation).\n",
        "allOf": [
          {
            "$ref": "#/components/schemas/ManagerReview"
          },
          {
            "type": "object",
            "properties": {
              "employee_name": {
                "type": [
                  "string",
                  "null"
                ],
                "readOnly": true,
                "description": "ref→people.employees.full_name (employee_id), by projection (not a join) — the appraisal subject. This operation carried no employee read at all, so the grid, its drawer title and its confirm dialog all identified the reviewee by uuid (issue #1640). By projection because the operation is stamped `TEAM` for a non-tenant-wide caller, where the employees ownership overlay would blank a join. `null` when the name cannot be resolved."
              },
              "employee_no": {
                "type": [
                  "string",
                  "null"
                ],
                "readOnly": true,
                "description": "ref→people.employees.employee_no (employee_id), by the same projection (issue #1640)."
              },
              "manager_name": {
                "type": [
                  "string",
                  "null"
                ],
                "readOnly": true,
                "description": "ref→people.employees.full_name (manager_id) — the appraising manager, by the same projection (issue #1640)."
              },
              "self_review_status": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/SelfReviewStatus"
                  },
                  {
                    "type": "null"
                  }
                ],
                "readOnly": true,
                "description": "Status of the reviewee's own self-review for this cycle — the `MG-05` SELF_SUBMITTED label. `null` when there is none."
              },
              "overall_self_rating": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/RateRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "readOnly": true,
                "description": "The reviewee's rolled-up self-rating, as a decimal STRING (`numeric(9,2)`, db 00 §6) — the grid's \"self rating\" column."
              },
              "self_review_submitted_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "readOnly": true
              },
              "self_review_responses": {
                "type": "array",
                "readOnly": true,
                "items": {
                  "$ref": "#/components/schemas/SelfReviewResponseItem"
                },
                "description": "The reviewee's per-goal answers — the drawer's read-only left panel. `[]` when there is no self-review."
              },
              "self_review_achievements": {
                "type": [
                  "string",
                  "null"
                ],
                "readOnly": true
              },
              "self_review_challenges": {
                "type": [
                  "string",
                  "null"
                ],
                "readOnly": true
              },
              "self_review_development_needs": {
                "type": [
                  "string",
                  "null"
                ],
                "readOnly": true
              }
            }
          }
        ]
      },
      "TeamManagerReviewPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TeamManagerReview"
                }
              }
            }
          }
        ]
      },
      "ManagerReviewSubmit": {
        "type": "object",
        "required": [
          "responses",
          "proposed_rating",
          "proposed_band"
        ],
        "additionalProperties": false,
        "properties": {
          "responses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ManagerReviewResponseItem"
            }
          },
          "proposed_rating": {
            "type": "number"
          },
          "proposed_band": {
            "$ref": "#/components/schemas/RatingBand"
          },
          "strengths": {
            "type": "string"
          },
          "improvement_areas": {
            "type": "string"
          },
          "promotion_recommended": {
            "type": "boolean",
            "default": false
          },
          "increment_recommended": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "ManagerReviewSetBand": {
        "type": "object",
        "description": "One 9-box placement, staged in one call — `final_band` is the horizontal (performance) axis and `potential_band` the vertical one (design-docs/02 §9, migration `0178`). `final_band` stays REQUIRED: a drag onto the grid always asserts a performance column, whereas `potential_band` may be omitted (the row keeps whatever placement it already had, and a row that never had one stays unplaced in the board's tray).\n",
        "required": [
          "final_band"
        ],
        "additionalProperties": false,
        "properties": {
          "final_band": {
            "$ref": "#/components/schemas/RatingBand"
          },
          "potential_band": {
            "$ref": "#/components/schemas/PotentialBand"
          }
        }
      },
      "Competency": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "label": {
            "$ref": "#/components/schemas/LocalizedTextRef"
          },
          "scale_max": {
            "type": "number"
          },
          "questions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "Questionnaire": {
        "type": "object",
        "description": "reviews_360.questionnaire shape (db 09 §1).",
        "properties": {
          "competencies": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Competency"
            }
          }
        }
      },
      "AggregateByCompetency": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "avg": {
            "type": "number"
          },
          "distribution": {
            "type": "array",
            "items": {
              "type": "number"
            }
          }
        }
      },
      "AggregateSummary": {
        "type": "object",
        "description": "reviews_360.aggregate_summary — anonymized rollup honouring min_raters (db 09 §1).",
        "readOnly": true,
        "properties": {
          "rater_count": {
            "type": "integer"
          },
          "by_competency": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AggregateByCompetency"
            }
          }
        }
      },
      "Review360": {
        "description": "perform.reviews_360 — the 360 multi-rater review container (db 09 §1).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "perf_cycle_id",
              "subject_employee_id",
              "status",
              "min_raters",
              "is_confidential"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "perf_cycle_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "subject_employee_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "subject_employee_name": {
                "type": [
                  "string",
                  "null"
                ],
                "readOnly": true,
                "description": "ref→people.employees.full_name (subject_employee_id), by projection (not a join) — carried by both list operations (`perform.review_360.list` and `.list_team`) so one resource keeps one shape whichever lens fetched it (issue #1640). By projection rather than a join because the two lenses do not share a scope: `.list` is tenant-wide, while `.list_team` is stamped `TEAM` for a non-tenant-wide caller, where the employees ownership overlay would blank a join. Absent on the single-row reads and the write responses; `null` when the name cannot be resolved. NO RATER identity is carried here — see `Review360RaterCounts`.\n"
              },
              "status": {
                "$ref": "#/components/schemas/Review360Status"
              },
              "questionnaire": {
                "$ref": "#/components/schemas/Questionnaire"
              },
              "min_raters": {
                "type": "integer",
                "minimum": 1
              },
              "is_confidential": {
                "type": "boolean"
              },
              "nominations_closed_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "due_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "aggregate_summary": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/AggregateSummary"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "Review360Page": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Review360"
                }
              }
            }
          }
        ]
      },
      "Review360RaterCounts": {
        "type": "object",
        "description": "The nominee roll-up behind `PRF-S15`'s *raters* column, counted over `perform.review_360_raters` for one 360. `responded` is counted against `perform.feedback` (`context = 'REVIEW_360'`), not against this table — a rater is nominated on one and answers on the other, which is the whole reason the two are separate tables with separate access rules. Counts only; NO rater identity is carried here or anywhere on this page.\n",
        "readOnly": true,
        "properties": {
          "nominated": {
            "type": "integer",
            "minimum": 0,
            "description": "Rows still awaiting a decision (`status = NOMINATED`)."
          },
          "approved": {
            "type": "integer",
            "minimum": 0,
            "description": "Rows on the panel — the count `min_raters` and the list-lock gate are measured against."
          },
          "rejected": {
            "type": "integer",
            "minimum": 0
          },
          "responded": {
            "type": "integer",
            "minimum": 0,
            "description": "Approved raters who have submitted a `perform.feedback` row for this 360."
          }
        }
      },
      "TeamReview360": {
        "description": "A `Review360` as the `PRF-S15` grid renders it for the team read — the 360 itself plus the DERIVED `rater_counts` roll-up the screen's *raters* column and its lifecycle gates gate on. STRICTLY ADDITIVE: every `TeamReview360` is a valid `Review360`, so a consumer coded against `Review360`/`Review360Page` is unaffected and simply ignores the extra. Computed server-side because a page of 360s cannot carry its own nominee panels, and fetching them per row is the round trip this shape exists to avoid (added in #223 with `perform.review_360.list_team`).\n",
        "allOf": [
          {
            "$ref": "#/components/schemas/Review360"
          },
          {
            "type": "object",
            "properties": {
              "rater_counts": {
                "$ref": "#/components/schemas/Review360RaterCounts"
              }
            }
          }
        ]
      },
      "TeamReview360Page": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TeamReview360"
                }
              }
            }
          }
        ]
      },
      "Review360Create": {
        "type": "object",
        "required": [
          "perf_cycle_id",
          "subject_employee_id"
        ],
        "additionalProperties": false,
        "properties": {
          "perf_cycle_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "subject_employee_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "questionnaire": {
            "$ref": "#/components/schemas/Questionnaire"
          },
          "min_raters": {
            "type": "integer",
            "minimum": 1,
            "default": 3
          },
          "is_confidential": {
            "type": "boolean",
            "default": true
          },
          "due_at": {
            "$ref": "#/components/schemas/TimestampRef"
          }
        }
      },
      "Review360Update": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "questionnaire": {
            "$ref": "#/components/schemas/Questionnaire"
          },
          "min_raters": {
            "type": "integer",
            "minimum": 1
          },
          "is_confidential": {
            "type": "boolean"
          },
          "due_at": {
            "$ref": "#/components/schemas/TimestampRef"
          }
        }
      },
      "Review360RaterStatus": {
        "type": "string",
        "enum": [
          "NOMINATED",
          "APPROVED",
          "REJECTED"
        ],
        "description": "perform.review_360_rater_status (db 09 §1 review_360_raters)."
      },
      "Review360Rater": {
        "description": "perform.review_360_raters — one nominated rater on a 360 and the four-eyes record of who nominated them and who decided (db 09 §1). `submitted_by` is the MAKER, `approved_by` the CHECKER — set on reject as well as approve, since what it records is who decided.\n",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "reviews_360_id",
              "rater_id",
              "rater_relationship",
              "status",
              "submitted_by"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "reviews_360_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "rater_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "rater_relationship": {
                "$ref": "#/components/schemas/RaterRelationship"
              },
              "rater_group": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "The `rater_group_config` group code this nomination was admitted under; null when the cycle configures no groups."
              },
              "status": {
                "$ref": "#/components/schemas/Review360RaterStatus"
              },
              "submitted_by": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "approved_by": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "decided_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "decision_note": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "responded": {
                "type": "boolean",
                "readOnly": true,
                "description": "Whether a `perform.feedback` row exists for this rater on this 360. A completion signal only — the response itself never surfaces here, and never reaches the subject at all (db 09 §1 `feedback`).\n"
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "Review360RaterPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Review360Rater"
                }
              }
            }
          }
        ]
      },
      "Review360RaterNominate": {
        "type": "object",
        "required": [
          "rater_id",
          "rater_relationship"
        ],
        "additionalProperties": false,
        "properties": {
          "rater_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "rater_relationship": {
            "$ref": "#/components/schemas/RaterRelationship"
          },
          "rater_group": {
            "type": "string",
            "description": "Optional explicit group code; when omitted the service resolves it from the cycle's `rater_group_config` by `rater_relationship`."
          }
        }
      },
      "Review360RaterDecision": {
        "type": "object",
        "additionalProperties": false,
        "description": "The approve/reject body. `decision_note` is REQUIRED on reject and enforced by the service as a 422 rather than by this schema — one shape serves both verdicts, and an approval has nothing to explain.\n",
        "properties": {
          "decision_note": {
            "type": "string",
            "minLength": 1,
            "maxLength": 500
          }
        }
      },
      "RaterGroupConfigGroup": {
        "type": "object",
        "description": "One eligible rater group on a cycle — a relationship, its display label, and its per-360 count bounds.",
        "properties": {
          "code": {
            "$ref": "#/components/schemas/RaterRelationship"
          },
          "label": {
            "$ref": "#/components/schemas/LocalizedTextRef"
          },
          "min": {
            "type": "integer",
            "minimum": 0
          },
          "max": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "RaterGroupConfig": {
        "type": "object",
        "description": "perf_cycles.rater_group_config — which rater relationships a 360 in this cycle may nominate, and how many of each (db 09 §1, migration 0176). Schemaless config snapshot, not queried (db 00 §7), in the same family as `rating_scale` and `stage_windows`. An EMPTY object means unconfigured: every relationship is eligible and there are no per-group counts, which is the value every cycle predating #223 carries.\n",
        "properties": {
          "groups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RaterGroupConfigGroup"
            }
          },
          "allow_external": {
            "type": "boolean",
            "description": "Whether `EXTERNAL` raters may be nominated at all. Absent/false refuses them with a 422."
          }
        }
      },
      "FeedbackResponseItem": {
        "type": "object",
        "properties": {
          "competency": {
            "type": "string"
          },
          "rating": {
            "type": "number"
          },
          "comment": {
            "type": "string"
          }
        }
      },
      "Feedback": {
        "description": "perform.feedback — one 360 rater answer / check-in note / continuous feedback row (db 09 §1, append-only).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "context",
              "subject_employee_id",
              "feedback_type",
              "visibility",
              "submitted_at"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "context": {
                "$ref": "#/components/schemas/FeedbackContext"
              },
              "reviews_360_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "checkin_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "subject_employee_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "rater_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "null in the response when is_anonymous = true and the caller is not HR."
              },
              "feedback_type": {
                "$ref": "#/components/schemas/FeedbackType"
              },
              "rater_relationship": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/RaterRelationship"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "responses": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/FeedbackResponseItem"
                }
              },
              "body": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "visibility": {
                "$ref": "#/components/schemas/FeedbackVisibility"
              },
              "is_anonymous": {
                "type": "boolean"
              },
              "submitted_at": {
                "$ref": "#/components/schemas/TimestampRef"
              }
            }
          },
          {
            "$ref": "#/components/schemas/AppendOnlyMetaRef"
          }
        ]
      },
      "FeedbackPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Feedback"
                }
              }
            }
          }
        ]
      },
      "FeedbackCreate": {
        "type": "object",
        "required": [
          "context",
          "subject_employee_id",
          "feedback_type"
        ],
        "additionalProperties": false,
        "properties": {
          "context": {
            "$ref": "#/components/schemas/FeedbackContext"
          },
          "reviews_360_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "checkin_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "subject_employee_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "feedback_type": {
            "$ref": "#/components/schemas/FeedbackType"
          },
          "rater_relationship": {
            "$ref": "#/components/schemas/RaterRelationship"
          },
          "responses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FeedbackResponseItem"
            }
          },
          "body": {
            "type": "string"
          },
          "visibility": {
            "$ref": "#/components/schemas/FeedbackVisibility",
            "default": "MANAGER_ONLY"
          },
          "is_anonymous": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "ActionItem": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string"
          },
          "owner_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "due_date": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "done": {
            "type": "boolean"
          }
        }
      },
      "Checkin": {
        "description": "perform.checkins — a 1:1 check-in between employee and manager (db 09 §1).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "employee_id",
              "manager_id",
              "checkin_type",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "perf_cycle_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "employee_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "manager_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "checkin_type": {
                "$ref": "#/components/schemas/CheckinType"
              },
              "status": {
                "$ref": "#/components/schemas/CheckinStatus"
              },
              "scheduled_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "completed_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "agenda": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "notes": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "action_items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ActionItem"
                }
              },
              "next_due_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "CheckinPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Checkin"
                }
              }
            }
          }
        ]
      },
      "CheckinCreate": {
        "type": "object",
        "required": [
          "employee_id",
          "manager_id",
          "checkin_type"
        ],
        "additionalProperties": false,
        "properties": {
          "perf_cycle_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "employee_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "manager_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "checkin_type": {
            "$ref": "#/components/schemas/CheckinType"
          },
          "scheduled_at": {
            "$ref": "#/components/schemas/TimestampRef"
          },
          "agenda": {
            "type": "string"
          }
        }
      },
      "CheckinUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "scheduled_at": {
            "$ref": "#/components/schemas/TimestampRef"
          },
          "agenda": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "action_items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActionItem"
            }
          }
        }
      },
      "DistributionBandTarget": {
        "type": "object",
        "properties": {
          "band": {
            "type": "string"
          },
          "target_pct": {
            "type": "number"
          }
        }
      },
      "DistributionConfig": {
        "type": "object",
        "description": "calibrations.distribution_config shape (db 09 §1).",
        "properties": {
          "bands": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DistributionBandTarget"
            }
          },
          "curve": {
            "type": "string",
            "enum": [
              "NORMAL",
              "CUSTOM"
            ]
          }
        }
      },
      "DistributionBandActual": {
        "type": "object",
        "properties": {
          "band": {
            "type": "string"
          },
          "count": {
            "type": "integer"
          },
          "pct": {
            "type": "number"
          }
        }
      },
      "ActualDistribution": {
        "type": "object",
        "readOnly": true,
        "description": "calibrations.actual_distribution — computed post-normalization (db 09 §1).",
        "properties": {
          "bands": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DistributionBandActual"
            }
          },
          "total": {
            "type": "integer"
          }
        }
      },
      "Calibration": {
        "description": "perform.calibrations — the calibration session that normalizes and releases gated ratings (db 09 §1).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "perf_cycle_id",
              "name",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "perf_cycle_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "name": {
                "type": "string"
              },
              "department_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "status": {
                "$ref": "#/components/schemas/CalibrationStatus"
              },
              "distribution_config": {
                "$ref": "#/components/schemas/DistributionConfig"
              },
              "actual_distribution": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/ActualDistribution"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "facilitator_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "signed_off_by": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "signed_off_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "ratings_released_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "CalibrationBoardRow": {
        "type": "object",
        "readOnly": true,
        "description": "One manager_reviews row projected onto the calibration board (fsd 08 PRF-S16).",
        "properties": {
          "manager_review_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "employee_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "employee_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "ref→people.employees.full_name (employee_id), by join — `perform.calibration.get` is tenant-scoped, so the employees ownership overlay opens unconditionally and the board statement can carry the name itself. Added because a 9-box card that identifies the person being calibrated by a truncated uuid (in its label AND its aria-label) is not a card a facilitator can decide a rating from (issue #1640). `null` when the employee row has been soft-deleted."
          },
          "proposed_rating": {
            "type": [
              "number",
              "null"
            ]
          },
          "proposed_band": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RatingBand"
              },
              {
                "type": "null"
              }
            ]
          },
          "final_band": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RatingBand"
              },
              {
                "type": "null"
              }
            ],
            "description": "Staged calibrated band (set via perform.manager_review.set_calibrated_band), amber on the board when it differs from proposed_band."
          },
          "potential_band": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PotentialBand"
              },
              {
                "type": "null"
              }
            ],
            "description": "The 9-box grid's VERTICAL axis (design-docs/02 §9, migration 0178), staged by the same perform.manager_review.set_calibrated_band call that stages final_band. `null` = never placed on the grid: the board renders those rows in an unplaced tray rather than defaulting them into the middle box, and publish gates on final_band alone."
          },
          "promotion_recommended": {
            "type": "boolean",
            "description": "The appraising manager's pre-calibration recommendation (perform.manager_reviews.promotion_recommended, written by perform.manager_review.update_and_submit). Surfaced here because it is what PRF-S16's publish impact-preview PT-MODAL \"promotions flagged\" state binds to, and because it rides on the perform.calibration.signed payload that engage (ENG-F05) consumes."
          },
          "rating_status": {
            "$ref": "#/components/schemas/RatingStatus"
          }
        }
      },
      "CalibrationDetail": {
        "description": "PRF-S16 board — the calibration group plus its bounded manager_reviews board rows.",
        "allOf": [
          {
            "$ref": "#/components/schemas/Calibration"
          },
          {
            "type": "object",
            "properties": {
              "board_rows": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/CalibrationBoardRow"
                }
              }
            }
          }
        ]
      },
      "CalibrationPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Calibration"
                }
              }
            }
          }
        ]
      },
      "CalibrationCreate": {
        "type": "object",
        "required": [
          "perf_cycle_id",
          "name"
        ],
        "additionalProperties": false,
        "properties": {
          "perf_cycle_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "name": {
            "type": "string"
          },
          "department_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "distribution_config": {
            "$ref": "#/components/schemas/DistributionConfig"
          },
          "facilitator_id": {
            "$ref": "#/components/schemas/UuidRef"
          }
        }
      },
      "CalibrationUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string"
          },
          "department_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "distribution_config": {
            "$ref": "#/components/schemas/DistributionConfig"
          },
          "facilitator_id": {
            "$ref": "#/components/schemas/UuidRef"
          }
        }
      },
      "Catalogue": {
        "description": "learn.training_catalogue — a browsable category/programme/learning-path grouping (db 09 §2).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "catalogue_type",
              "title",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "legal_entity_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "catalogue_type": {
                "$ref": "#/components/schemas/CatalogueType"
              },
              "title": {
                "$ref": "#/components/schemas/LocalizedTextRef"
              },
              "description": {
                "$ref": "#/components/schemas/LocalizedTextRef"
              },
              "status": {
                "$ref": "#/components/schemas/CatalogueStatus"
              },
              "owner_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "skill_tags": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "display_order": {
                "type": "integer",
                "minimum": 0
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "TrainingCataloguePage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Catalogue"
                }
              }
            }
          }
        ]
      },
      "CatalogueCreate": {
        "type": "object",
        "required": [
          "catalogue_type",
          "title"
        ],
        "additionalProperties": false,
        "properties": {
          "legal_entity_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "catalogue_type": {
            "$ref": "#/components/schemas/CatalogueType"
          },
          "title": {
            "$ref": "#/components/schemas/LocalizedTextRef"
          },
          "description": {
            "$ref": "#/components/schemas/LocalizedTextRef"
          },
          "owner_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "skill_tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "display_order": {
            "type": "integer",
            "minimum": 0,
            "default": 0
          }
        }
      },
      "CatalogueUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "title": {
            "$ref": "#/components/schemas/LocalizedTextRef"
          },
          "description": {
            "$ref": "#/components/schemas/LocalizedTextRef"
          },
          "status": {
            "$ref": "#/components/schemas/CatalogueStatus"
          },
          "owner_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "skill_tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "display_order": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "Course": {
        "description": "learn.courses — a course/programme item (db 09 §2).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "course_code",
              "title",
              "mode",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "course_code": {
                "$ref": "#/components/schemas/BusinessNoRef"
              },
              "catalogue_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "title": {
                "$ref": "#/components/schemas/LocalizedTextRef"
              },
              "description": {
                "$ref": "#/components/schemas/LocalizedTextRef"
              },
              "mode": {
                "$ref": "#/components/schemas/CourseMode"
              },
              "status": {
                "$ref": "#/components/schemas/CourseStatus"
              },
              "duration_hours": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DecimalHoursRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "provider": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "prerequisites": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "course_id": {
                      "$ref": "#/components/schemas/UuidRef"
                    },
                    "skill": {
                      "type": "string"
                    }
                  }
                }
              },
              "skill_tags": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "is_certification_course": {
                "type": "boolean"
              },
              "certificate_validity_months": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "seat_capacity": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "cost_amount": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/MoneyRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "CoursePage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Course"
                }
              }
            }
          }
        ]
      },
      "CourseCreate": {
        "type": "object",
        "required": [
          "title",
          "mode"
        ],
        "additionalProperties": false,
        "properties": {
          "catalogue_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "title": {
            "$ref": "#/components/schemas/LocalizedTextRef"
          },
          "description": {
            "$ref": "#/components/schemas/LocalizedTextRef"
          },
          "mode": {
            "$ref": "#/components/schemas/CourseMode"
          },
          "duration_hours": {
            "$ref": "#/components/schemas/DecimalHoursRef"
          },
          "provider": {
            "type": "string",
            "description": "Required when mode=EXTERNAL."
          },
          "prerequisites": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "course_id": {
                  "$ref": "#/components/schemas/UuidRef"
                },
                "skill": {
                  "type": "string"
                }
              }
            }
          },
          "skill_tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "is_certification_course": {
            "type": "boolean",
            "default": false
          },
          "certificate_validity_months": {
            "type": "integer",
            "minimum": 1
          },
          "seat_capacity": {
            "type": "integer",
            "minimum": 1
          },
          "cost_amount": {
            "$ref": "#/components/schemas/MoneyRef"
          },
          "currency_code": {
            "type": "string",
            "pattern": "^[A-Z]{3}$",
            "example": "INR"
          }
        }
      },
      "CourseUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "catalogue_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "title": {
            "$ref": "#/components/schemas/LocalizedTextRef"
          },
          "description": {
            "$ref": "#/components/schemas/LocalizedTextRef"
          },
          "mode": {
            "$ref": "#/components/schemas/CourseMode"
          },
          "status": {
            "$ref": "#/components/schemas/CourseStatus"
          },
          "duration_hours": {
            "$ref": "#/components/schemas/DecimalHoursRef"
          },
          "provider": {
            "type": "string"
          },
          "prerequisites": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "course_id": {
                  "$ref": "#/components/schemas/UuidRef"
                },
                "skill": {
                  "type": "string"
                }
              }
            }
          },
          "skill_tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "is_certification_course": {
            "type": "boolean"
          },
          "certificate_validity_months": {
            "type": "integer",
            "minimum": 1
          },
          "seat_capacity": {
            "type": "integer",
            "minimum": 1
          },
          "cost_amount": {
            "$ref": "#/components/schemas/MoneyRef"
          },
          "currency_code": {
            "type": "string",
            "pattern": "^[A-Z]{3}$",
            "example": "INR"
          }
        }
      },
      "Enrolment": {
        "description": "learn.enrolments — a committed course enrolment (db 09 §2).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "course_id",
              "employee_id",
              "source",
              "status",
              "enrolled_at"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "course_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "employee_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "nomination_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "session_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "source": {
                "$ref": "#/components/schemas/EnrolmentSource"
              },
              "status": {
                "$ref": "#/components/schemas/EnrolmentStatus"
              },
              "enrolled_at": {
                "$ref": "#/components/schemas/TimestampRef"
              },
              "started_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "due_date": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DateOnlyRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "progress_pct": {
                "$ref": "#/components/schemas/RateRef"
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "EnrolmentPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Enrolment"
                }
              }
            }
          }
        ]
      },
      "EnrolmentCreate": {
        "type": "object",
        "required": [
          "course_id"
        ],
        "additionalProperties": false,
        "properties": {
          "course_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "session_id": {
            "$ref": "#/components/schemas/UuidRef"
          }
        }
      },
      "EnrolmentUpdateAdmin": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "status": {
            "$ref": "#/components/schemas/EnrolmentStatus"
          },
          "source": {
            "$ref": "#/components/schemas/EnrolmentSource"
          },
          "session_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "due_date": {
            "$ref": "#/components/schemas/DateOnlyRef"
          }
        }
      },
      "Nomination": {
        "description": "learn.nominations — a manager/L&D nomination routed through the unified approvals inbox (db 09 §2).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "course_id",
              "nominee_id",
              "nominated_by",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "course_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "nominee_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "nominated_by": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "session_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "status": {
                "$ref": "#/components/schemas/NominationStatus"
              },
              "approval_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Soft ref → xc.approval_inbox (XC-F12)."
              },
              "reason": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "approved_by": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "approved_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "NominationPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Nomination"
                }
              }
            }
          }
        ]
      },
      "NominationCreate": {
        "type": "object",
        "required": [
          "course_id",
          "nominee_id"
        ],
        "additionalProperties": false,
        "properties": {
          "course_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "nominee_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "session_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "reason": {
            "type": "string"
          }
        }
      },
      "NominationRejectRequest": {
        "description": "The refusal reason. NOT persisted on `learn.nominations` — it has no approver-note column — but carried on the `learn.nomination.rejected` event and stamped onto the approval envelope's `decision_note` (`#1646`). `note` is accepted as an alias, which is the spelling the unified inbox drawer sends through `ApprovalSourceActionRouter`.",
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "reason": {
            "type": "string"
          },
          "note": {
            "type": "string"
          }
        }
      },
      "Completion": {
        "description": "learn.completions — a recorded course completion (db 09 §2, append-only).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "course_id",
              "employee_id",
              "result",
              "source",
              "completed_on"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "course_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "enrolment_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "employee_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "session_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "result": {
                "$ref": "#/components/schemas/CompletionResult"
              },
              "source": {
                "$ref": "#/components/schemas/CompletionSource"
              },
              "score": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "completed_on": {
                "$ref": "#/components/schemas/DateOnlyRef"
              },
              "marked_by": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "evidence": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/FileDownloadRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Presigned external-provider proof (XC-F07); never a raw storage key."
              }
            }
          },
          {
            "$ref": "#/components/schemas/AppendOnlyMetaRef"
          }
        ]
      },
      "CompletionPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Completion"
                }
              }
            }
          }
        ]
      },
      "CompletionCreate": {
        "type": "object",
        "required": [
          "course_id",
          "employee_id",
          "result",
          "completed_on"
        ],
        "additionalProperties": false,
        "properties": {
          "course_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "enrolment_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "employee_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "session_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "result": {
            "$ref": "#/components/schemas/CompletionResult"
          },
          "source": {
            "$ref": "#/components/schemas/CompletionSource",
            "default": "MANUAL"
          },
          "score": {
            "type": "number"
          },
          "completed_on": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "evidence_storage_key": {
            "type": "string",
            "description": "Required when source=EXTERNAL. Object-storage key from a prior presigned-upload flow (XC-F07)."
          }
        }
      },
      "Certification": {
        "description": "learn.certifications — a certificate/credential with a renewal chain (db 09 §2).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "certification_no",
              "employee_id",
              "source",
              "status",
              "title",
              "issued_date"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "certification_no": {
                "$ref": "#/components/schemas/BusinessNoRef"
              },
              "completion_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "course_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "employee_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "source": {
                "$ref": "#/components/schemas/CertificationSource"
              },
              "status": {
                "$ref": "#/components/schemas/CertificationStatus"
              },
              "title": {
                "type": "string"
              },
              "issuing_authority": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "issued_date": {
                "$ref": "#/components/schemas/DateOnlyRef"
              },
              "expiry_date": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DateOnlyRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "certificate_file": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/FileDownloadRef"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Presigned tamper-evident PDF (XC-F07); never a raw storage key. Fetched via learn.certification.download."
              },
              "renewed_from_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "last_renewal_scan_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "CertificationPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Certification"
                }
              }
            }
          }
        ]
      },
      "CertificationUploadExternal": {
        "type": "object",
        "required": [
          "title",
          "issued_date",
          "storage_key"
        ],
        "additionalProperties": false,
        "properties": {
          "course_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "title": {
            "type": "string"
          },
          "issuing_authority": {
            "type": "string"
          },
          "issued_date": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "expiry_date": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "storage_key": {
            "type": "string",
            "description": "Object-storage key returned by a prior presigned-upload flow (XC-F07); the API resolves this to certificate_file on read."
          },
          "content_hash": {
            "type": "string",
            "description": "SHA-256 of the uploaded PDF."
          }
        }
      },
      "CertificationIssue": {
        "type": "object",
        "required": [
          "employee_id",
          "title",
          "issued_date"
        ],
        "additionalProperties": false,
        "properties": {
          "completion_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "course_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "employee_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "title": {
            "type": "string"
          },
          "issuing_authority": {
            "type": "string"
          },
          "issued_date": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "expiry_date": {
            "$ref": "#/components/schemas/DateOnlyRef"
          }
        }
      },
      "CertificationRenewRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "issued_date": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "expiry_date": {
            "$ref": "#/components/schemas/DateOnlyRef"
          }
        }
      },
      "TrainingCalendar": {
        "description": "learn.training_calendar — a per-entity scheduling container (db 09 §2).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "legal_entity_id",
              "name",
              "status"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "legal_entity_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "name": {
                "type": "string"
              },
              "fiscal_year": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "period_start": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DateOnlyRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "period_end": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/DateOnlyRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "status": {
                "$ref": "#/components/schemas/CalendarStatus"
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "TrainingCalendarPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TrainingCalendar"
                }
              }
            }
          }
        ]
      },
      "TrainingCalendarCreate": {
        "type": "object",
        "required": [
          "legal_entity_id",
          "name"
        ],
        "additionalProperties": false,
        "properties": {
          "legal_entity_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "name": {
            "type": "string"
          },
          "fiscal_year": {
            "type": "integer"
          },
          "period_start": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "period_end": {
            "$ref": "#/components/schemas/DateOnlyRef"
          }
        }
      },
      "TrainingCalendarUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string"
          },
          "period_start": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "period_end": {
            "$ref": "#/components/schemas/DateOnlyRef"
          },
          "status": {
            "$ref": "#/components/schemas/CalendarStatus"
          }
        }
      },
      "TrainingSession": {
        "description": "learn.training_sessions — a scheduled instructor-led session (db 09 §2).",
        "allOf": [
          {
            "type": "object",
            "required": [
              "id",
              "course_id",
              "mode",
              "status",
              "start_at"
            ],
            "properties": {
              "id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "course_id": {
                "$ref": "#/components/schemas/UuidRef"
              },
              "training_calendar_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "title": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "mode": {
                "$ref": "#/components/schemas/SessionMode"
              },
              "status": {
                "$ref": "#/components/schemas/SessionStatus"
              },
              "instructor_id": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/UuidRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "instructor_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "venue": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "meeting_link": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "start_at": {
                "$ref": "#/components/schemas/TimestampRef"
              },
              "end_at": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/TimestampRef"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "capacity": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "enrolled_count": {
                "type": "integer"
              },
              "waitlist_count": {
                "type": "integer"
              }
            }
          },
          {
            "$ref": "#/components/schemas/AuditMetaRef"
          }
        ]
      },
      "TrainingSessionPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CursorPageRef"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TrainingSession"
                }
              }
            }
          }
        ]
      },
      "TrainingSessionCreate": {
        "type": "object",
        "required": [
          "course_id",
          "mode",
          "start_at"
        ],
        "additionalProperties": false,
        "properties": {
          "course_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "training_calendar_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "title": {
            "type": "string"
          },
          "mode": {
            "$ref": "#/components/schemas/SessionMode"
          },
          "instructor_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "instructor_name": {
            "type": "string"
          },
          "venue": {
            "type": "string",
            "description": "Required when mode IN (CLASSROOM",
            "HYBRID).": null
          },
          "meeting_link": {
            "type": "string",
            "description": "Required when mode IN (VIRTUAL",
            "HYBRID).": null
          },
          "start_at": {
            "$ref": "#/components/schemas/TimestampRef"
          },
          "end_at": {
            "$ref": "#/components/schemas/TimestampRef"
          },
          "capacity": {
            "type": "integer",
            "minimum": 1
          }
        }
      },
      "TrainingSessionUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": "string"
          },
          "mode": {
            "$ref": "#/components/schemas/SessionMode"
          },
          "status": {
            "$ref": "#/components/schemas/SessionStatus"
          },
          "instructor_id": {
            "$ref": "#/components/schemas/UuidRef"
          },
          "instructor_name": {
            "type": "string"
          },
          "venue": {
            "type": "string"
          },
          "meeting_link": {
            "type": "string"
          },
          "start_at": {
            "$ref": "#/components/schemas/TimestampRef"
          },
          "end_at": {
            "$ref": "#/components/schemas/TimestampRef"
          },
          "capacity": {
            "type": "integer",
            "minimum": 1
          }
        }
      },
      "Uuid": {
        "type": "string",
        "format": "uuid",
        "description": "UUIDv7 surrogate primary key (db-docs/00 §3). Never the business identifier."
      },
      "Timestamp": {
        "type": "string",
        "format": "date-time",
        "description": "timestamptz, serialized UTC ISO-8601. Presentation timezone is a client concern."
      },
      "DateOnly": {
        "type": "string",
        "format": "date",
        "description": "Calendar-only value (pay-period date, leave date, due date)."
      },
      "DecimalHours": {
        "type": "string",
        "pattern": "^-?\\d+(\\.\\d{1,2})?$",
        "description": "numeric(9,2) decimal hours/days as a string (OT hours, leave days). Never a float."
      },
      "Rate": {
        "type": "string",
        "pattern": "^-?\\d+(\\.\\d{1,6})?$",
        "description": "numeric(9,6) fraction as a string, e.g. \"0.120000\" for the 12% EPF rate. Never a float; percentages are stored as fractions."
      },
      "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"
        }
      },
      "HijriDisplay": {
        "type": "string",
        "readOnly": true,
        "description": "Formatted Umm al-Qura display string (`*_hijri`, db-docs/00 §6) accompanying a canonical Gregorian value on KSA-facing read-models (GOSI/WPS periods, Iqama expiry, KSA payslips). NEVER the source of truth; never accepted as input.\n"
      },
      "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"
      },
      "FileDownload": {
        "type": "object",
        "description": "Authorized file handle (db-docs/00 §14, xc.files). Bytes never transit the API — the backend mints a time-limited presigned URL after authorization. Clients never see storage keys or hold storage credentials; the presigned URL is never persisted.\n",
        "required": [
          "file_id",
          "file_name",
          "url",
          "expires_at"
        ],
        "properties": {
          "file_id": {
            "$ref": "#/components/schemas/Uuid"
          },
          "file_name": {
            "type": "string"
          },
          "mime_type": {
            "type": "string"
          },
          "size_bytes": {
            "type": "integer"
          },
          "content_hash": {
            "type": [
              "string",
              "null"
            ],
            "description": "SHA-256",
            "present where tamper-evidence matters (payslips": null,
            "letters": null,
            "e-sign artifacts).": null
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Time-limited presigned URL."
          },
          "expires_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "AuditMeta": {
        "type": "object",
        "description": "Standard mutable-entity columns (db-docs/00 §5). Read-only; present on every mutable read-model.",
        "readOnly": true,
        "properties": {
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "created_by": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              },
              {
                "type": "null"
              }
            ],
            "description": "null = system/jobs"
          },
          "updated_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "updated_by": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              },
              {
                "type": "null"
              }
            ]
          },
          "deleted_at": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Timestamp"
              },
              {
                "type": "null"
              }
            ],
            "description": "soft-delete marker; live rows are null. Deleted rows are excluded by default scope."
          },
          "version": {
            "type": "integer",
            "description": "Optimistic-lock counter (where present); surfaces as the ETag."
          }
        }
      },
      "AppendOnlyMeta": {
        "type": "object",
        "description": "Standard append-only/immutable columns (db-docs/00 §5/§8). No update/version/delete; corrections are new compensating rows.",
        "readOnly": true,
        "properties": {
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "created_by": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Uuid"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "CursorPage": {
        "type": "object",
        "description": "Generic cursor-pagination envelope. List operations compose it via allOf to type `data`, e.g. `allOf: [ {$ref CursorPage}, { properties: { data: { items: {$ref Employee} } } } ]`.\n",
        "required": [
          "data",
          "page"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {}
          },
          "page": {
            "type": "object",
            "required": [
              "has_more"
            ],
            "properties": {
              "next_cursor": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "prev_cursor": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "has_more": {
                "type": "boolean"
              },
              "total_est": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Optional, capped, APPROXIMATE row estimate for grid \"X of Z\" display only — never an exact COUNT(*) on large tables (attend.attendance_records, xc.notifications, audit.*).\n"
              }
            }
          }
        }
      },
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem detail (application/problem+json). The platform-wide error envelope (03 §1).",
        "required": [
          "type",
          "title",
          "status"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "default": "about:blank",
            "description": "Problem-type URI."
          },
          "title": {
            "type": "string",
            "description": "Short, human-readable summary (stable per type)."
          },
          "status": {
            "type": "integer",
            "description": "HTTP status code, duplicated for convenience."
          },
          "detail": {
            "type": "string",
            "description": "Human-readable explanation specific to this occurrence."
          },
          "instance": {
            "type": "string",
            "description": "URI reference for this specific occurrence."
          },
          "code": {
            "$ref": "#/components/schemas/ErrorCode"
          },
          "correlation_id": {
            "$ref": "#/components/schemas/Uuid"
          }
        }
      },
      "ValidationProblem": {
        "description": "422 field-level validation failure; extends Problem with a per-field error array. `detail` is ALWAYS present on a 422 (#1251) and is the human summary of `errors[]`: one offending field renders as `\"<field>: <its message>\"` (`withholding_amount: is required for an India entity`), several as `\"N fields were refused: a, b, c.\"`, capped at five names. It is display copy derived from members already in the same body — clients keep branching on `code` and mapping `errors[].pointer` back to a control, never parsing this sentence.\n",
        "allOf": [
          {
            "$ref": "#/components/schemas/Problem"
          },
          {
            "type": "object",
            "required": [
              "detail",
              "errors"
            ],
            "properties": {
              "detail": {
                "type": "string",
                "description": "Human summary of `errors[]`, always populated on a 422 so a client never has to fall back to generic copy for the one status that names a fixable field.\n",
                "example": "withholding_amount: is required for an India entity"
              },
              "errors": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "pointer",
                    "rule"
                  ],
                  "properties": {
                    "pointer": {
                      "type": "string",
                      "description": "JSON Pointer to the offending field, e.g. /claim_amount"
                    },
                    "rule": {
                      "type": "string",
                      "enum": [
                        "required",
                        "format",
                        "length",
                        "range",
                        "cross-field",
                        "async-server",
                        "consent-gated",
                        "uniqueness-business",
                        "not_found"
                      ],
                      "description": "FSD validation taxonomy rule (fsd-docs/00 §8.2). `not_found` is the server-side-lookup arm: a body field that REFERENCES another resource (e.g. `project_id` on a work entry) and did not resolve for this caller. It is reported here, under the field's pointer, and NOT as a 404 — the request addresses its own resource, so the failure belongs on the form field the client can actually fix (#805).\n"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "CurrencyCode": {
        "type": "string",
        "enum": [
          "INR",
          "SAR"
        ],
        "description": "ISO-4217. A legal entity operates in a single currency (db-docs/00 §6)."
      },
      "ErrorCode": {
        "type": "string",
        "description": "Machine-stable error code (paired with the HTTP status; drives client handling, not display copy).",
        "enum": [
          "VALIDATION_FAILED",
          "IDEMPOTENCY_KEY_REUSE",
          "VERSION_CONFLICT",
          "PRECONDITION_REQUIRED",
          "MAKER_EQUALS_CHECKER",
          "STEP_UP_REQUIRED",
          "CONSENT_REQUIRED",
          "TOKEN_DENIED",
          "SCOPE_DENIED",
          "OWNERSHIP_DENIED",
          "STATE_TRANSITION_INVALID",
          "FACE_MISMATCH",
          "FACE_VERIFICATION_REQUIRED",
          "WITHHOLDING_REVIEW_REQUIRED",
          "FEATURE_NOT_IN_PLAN",
          "PLAN_LIMIT_EXCEEDED",
          "TENANT_PAST_DUE",
          "TENANT_SUSPENDED",
          "TENANT_CANCELLED",
          "RATE_LIMITED",
          "NOT_FOUND"
        ]
      }
    },
    "parameters": {
      "PathId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUIDv7 surrogate key of the target resource. Business numbers (`employee_no`, `claim_no`, …) are read-model fields, never path keys.",
        "schema": {
          "$ref": "#/components/schemas/Uuid"
        }
      },
      "PageSize": {
        "name": "page[size]",
        "in": "query",
        "required": false,
        "description": "Max items per page. Cursor pagination only (03 §2); offset pagination is rejected (ADR 0015).",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        }
      },
      "PageAfter": {
        "name": "page[after]",
        "in": "query",
        "required": false,
        "description": "Opaque forward keyset cursor (from a prior page's `page.next_cursor`).",
        "schema": {
          "type": "string"
        }
      },
      "PageBefore": {
        "name": "page[before]",
        "in": "query",
        "required": false,
        "description": "Opaque backward keyset cursor (from a prior page's `page.prev_cursor`).",
        "schema": {
          "type": "string"
        }
      },
      "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"
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "Client-generated unique key. REQUIRED on every mutation (this round tightens ADR 0015's \"platform + retryable mutations\" floor to ALL mutations for uniformity — offline punch/leave sync depends on it). Scoped (tenant, principal, route, key); a replay within the ~24h window returns the stored response with `Idempotency-Replayed: true`; the same key with a different body → 409 IDEMPOTENCY_KEY_REUSE (04 §1).\n",
        "schema": {
          "type": "string",
          "minLength": 8,
          "maxLength": 255
        }
      },
      "IfMatch": {
        "name": "If-Match",
        "in": "header",
        "required": true,
        "description": "Optimistic-concurrency precondition for mutating a VERSIONED mutable entity (db-docs/00 §5 applies `version` where concurrent edits are likely). Value is the entity's current ETag (the row `version`). Absent → 428; stale → 412 (04 §2). N/A for append-only entities and for unversioned low-contention entities (their update ops simply omit this parameter).\n",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing, expired, or invalid session token (no authenticated principal).",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Authenticated but denied — permission token not granted, out of scope (self/team/branch), not the owner, tenant suspended, or an MC-2 operation without a fresh step-up challenge. `code` ∈ TOKEN_DENIED | SCOPE_DENIED | OWNERSHIP_DENIED | MAKER_EQUALS_CHECKER | STEP_UP_REQUIRED | CONSENT_REQUIRED | TENANT_SUSPENDED. A plan feature-flag being off is 402 FEATURE_NOT_IN_PLAN, not 403 (see PaymentRequired).\n",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource does not exist OR is masked by RLS (tenant/self/team/branch scope) — the API does not distinguish, so existence is never confirmed across a scope boundary (02 §4 disclosure posture).\n",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "Conflict": {
        "description": "Idempotency-key reuse with a different body, an invalid state transition, or a uniqueness/business-rule violation (fsd 00 §8.2). For database-backed uniqueness rules, detail names the exact violated rule; unmapped constraints are not collapsed into a generic 409.\n",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "UnprocessableEntity": {
        "description": "Field-level validation failed. The body carries both `errors[]` (per-field, pointer-addressed) and a `detail` summarising them — never an empty `detail` (#1251).\n",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ValidationProblem"
            },
            "examples": {
              "singleField": {
                "summary": "One refused field — `detail` names it",
                "value": {
                  "type": "about:blank",
                  "title": "Unprocessable Entity",
                  "status": 422,
                  "code": "VALIDATION_FAILED",
                  "detail": "withholding_amount: is required for an India entity",
                  "errors": [
                    {
                      "pointer": "/withholding_amount",
                      "rule": "required",
                      "message": "is required for an India entity"
                    }
                  ]
                }
              },
              "severalFields": {
                "summary": "Several refused fields — `detail` counts and names them",
                "value": {
                  "type": "about:blank",
                  "title": "Unprocessable Entity",
                  "status": 422,
                  "code": "VALIDATION_FAILED",
                  "detail": "2 fields were refused: effective_from, cap_amount.amount.",
                  "errors": [
                    {
                      "pointer": "/effective_from",
                      "rule": "cross-field",
                      "message": "Overlaps an existing version."
                    },
                    {
                      "pointer": "/cap_amount/amount",
                      "rule": "range",
                      "message": "Must be a non-negative decimal string."
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "Locked": {
        "description": "Tenant subscription `past_due` (ADR 0009): WRITES are blocked (423), reads still succeed. `code` = TENANT_PAST_DUE. Mutations return this; list/get operations do not.\n",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Per-principal/route rate limit exceeded.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "PreconditionRequired": {
        "description": "If-Match header absent on a mutation of a versioned mutable entity (428).",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "PreconditionFailed": {
        "description": "If-Match / ETag mismatch — the row changed since it was read (412, VERSION_CONFLICT).",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      }
    },
    "headers": {
      "ETag": {
        "description": "Strong validator of the row `version` (e.g. `\"v7\"`). Use as `If-Match` on the next mutation.",
        "schema": {
          "type": "string"
        }
      },
      "Location": {
        "description": "URI of the created/affected resource.",
        "schema": {
          "type": "string",
          "format": "uri-reference"
        }
      },
      "IdempotencyReplayed": {
        "description": "`true` when a stored idempotent response was replayed rather than freshly computed.",
        "schema": {
          "type": "boolean"
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait before retrying (on 429 / 503).",
        "schema": {
          "type": "integer"
        }
      }
    }
  }
}