{
    "openapi": "3.0.0",
    "info": {
        "title": "LFF Assessment API",
        "description": "Schema-driven, bilingual (English/Yoruba) assessment platform for the LFF Sorting Out programme. Admins define assessment structure and per-locale wording as data; clients fetch a fully localized schema and submit answers through one generic surface.\n\nAuthenticate with a Sanctum bearer token (`POST /auth/register` or `/auth/login`), then send `Authorization: Bearer <token>` on every other request.\n\n## Language\n\nEvery localized response resolves its language in this order: `?locale=` query param → `Accept-Language` header → the logged-in user's own `preferredLocale` (set at registration) → `en`. This means a Yoruba-preferring user's whole session — profile, assessment list, every schema — renders in Yoruba automatically, with no `?locale=` needed on each request; `?locale=` is only for overriding it per-call. Untranslated content quietly falls back to English rather than erroring. Answer payloads (the `.../answers` endpoints) are the one exception — they carry option **codes**, never localized text, so language has no effect on them at all; pair a stored code with a schema fetched in either language to display it.\n\nEvery error is RFC 9457 `application/problem+json`; see the ProblemDetails schema.",
        "version": "1.0.0"
    },
    "servers": [
        {
            "url": "/v1",
            "description": "Versioned API surface"
        }
    ],
    "paths": {
        "/admin/assessments": {
            "get": {
                "tags": [
                    "Admin · Assessments"
                ],
                "summary": "List every assessment (structure view)",
                "description": "Section/question counts and which locales each assessment has wording for — includes inactive assessments, unlike the client-facing list.",
                "operationId": "66d1506f701ae93bf18b61d987800eae",
                "responses": {
                    "200": {
                        "description": "All assessments, active or not",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "properties": {
                                                    "code": {
                                                        "type": "string",
                                                        "example": "form-0"
                                                    },
                                                    "version": {
                                                        "type": "integer",
                                                        "example": 1
                                                    },
                                                    "position": {
                                                        "type": "integer",
                                                        "example": 0
                                                    },
                                                    "isActive": {
                                                        "type": "boolean",
                                                        "example": true
                                                    },
                                                    "locales": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "string"
                                                        },
                                                        "example": [
                                                            "en",
                                                            "yo"
                                                        ]
                                                    },
                                                    "sectionCount": {
                                                        "type": "integer",
                                                        "example": 1
                                                    },
                                                    "questionCount": {
                                                        "type": "integer",
                                                        "example": 3
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Not an admin",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            },
            "post": {
                "tags": [
                    "Admin · Assessments"
                ],
                "summary": "Create a new assessment",
                "description": "Structure only — no wording yet. Add sections/questions next, then wording via PUT .../translations/{locale}.",
                "operationId": "8d5ac1571f8debb8862a713c64eff9a6",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "code"
                                ],
                                "properties": {
                                    "code": {
                                        "type": "string",
                                        "example": "form-followup"
                                    },
                                    "position": {
                                        "type": "integer",
                                        "example": 20
                                    },
                                    "is_active": {
                                        "type": "boolean",
                                        "example": true
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "properties": {
                                                "code": {
                                                    "type": "string",
                                                    "example": "form-followup"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Code already taken, or invalid",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/admin/assessments/{assessment}": {
            "delete": {
                "tags": [
                    "Admin · Assessments"
                ],
                "summary": "Deactivate an assessment",
                "description": "Soft delete only — deactivates, never destroys, so submitted answers stay resolvable.",
                "operationId": "62f4d0f1d28c8e6e14043166b7602111",
                "parameters": [
                    {
                        "name": "assessment",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Deactivated",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "properties": {
                                                "code": {
                                                    "type": "string"
                                                },
                                                "isActive": {
                                                    "type": "boolean",
                                                    "example": false
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            },
            "patch": {
                "tags": [
                    "Admin · Assessments"
                ],
                "summary": "Update position/active flag",
                "description": "Bumps `version` so clients can detect schema drift on their cached copy.",
                "operationId": "2d062901027593f461220cd634f1cf0d",
                "parameters": [
                    {
                        "name": "assessment",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "properties": {
                                    "position": {
                                        "type": "integer"
                                    },
                                    "is_active": {
                                        "type": "boolean"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Updated",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "properties": {
                                                "code": {
                                                    "type": "string"
                                                },
                                                "version": {
                                                    "type": "integer"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/admin/instances": {
            "get": {
                "tags": [
                    "Admin · Review"
                ],
                "summary": "Review queue",
                "description": "What an admin sees first — every instance, optionally filtered by status.",
                "operationId": "23d920f14aa6e041ad1ccd2a3dd35619",
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "draft",
                                "submitted",
                                "closed"
                            ]
                        }
                    },
                    {
                        "name": "perPage",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Paginated instances with a minimal respondent summary",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "properties": {
                                                    "id": {
                                                        "type": "string"
                                                    },
                                                    "reference": {
                                                        "type": "string"
                                                    },
                                                    "status": {
                                                        "type": "string"
                                                    },
                                                    "user": {
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "surname": {
                                                                "type": "string"
                                                            },
                                                            "otherNames": {
                                                                "type": "string"
                                                            },
                                                            "email": {
                                                                "type": "string"
                                                            }
                                                        },
                                                        "type": "object"
                                                    },
                                                    "startedAt": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "nullable": true
                                                    },
                                                    "submittedAt": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "nullable": true
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "meta": {
                                            "properties": {
                                                "pagination": {
                                                    "$ref": "#/components/schemas/PaginationMeta"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Not an admin",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/admin/instances/{instance}": {
            "get": {
                "tags": [
                    "Admin · Review"
                ],
                "summary": "Full submission for review",
                "description": "Every assessment with answers, localized — this is what the ministers read. Assessments with no answers are omitted entirely.",
                "operationId": "5d90dffa8c4b6a7eac8e0ef48d2d9c1d",
                "parameters": [
                    {
                        "name": "instance",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "locale",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "en",
                                "yo"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Full localized answer set",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "properties": {
                                                "id": {
                                                    "type": "string"
                                                },
                                                "reference": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "string"
                                                },
                                                "schemaVersions": {
                                                    "description": "Assessment code → version, captured at submit time.",
                                                    "type": "object"
                                                },
                                                "user": {
                                                    "properties": {
                                                        "id": {
                                                            "type": "integer"
                                                        },
                                                        "surname": {
                                                            "type": "string"
                                                        },
                                                        "otherNames": {
                                                            "type": "string"
                                                        },
                                                        "email": {
                                                            "type": "string"
                                                        }
                                                    },
                                                    "type": "object"
                                                },
                                                "startedAt": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "nullable": true
                                                },
                                                "submittedAt": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "nullable": true
                                                },
                                                "assessments": {
                                                    "type": "array",
                                                    "items": {
                                                        "properties": {
                                                            "code": {
                                                                "type": "string"
                                                            },
                                                            "title": {
                                                                "type": "string"
                                                            },
                                                            "answers": {
                                                                "type": "array",
                                                                "items": {
                                                                    "$ref": "#/components/schemas/Answer"
                                                                }
                                                            }
                                                        },
                                                        "type": "object"
                                                    }
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Not an admin",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/admin/option-sets": {
            "get": {
                "tags": [
                    "Admin · Structure"
                ],
                "summary": "Every shared choice list in the system",
                "description": "Codes only, English-agnostic — cross-reference these against the `option`/`options` values sent in answers, and against registration's country/religion/marital-status/sex/previous-attendance fields.",
                "operationId": "7b2ac47c44728526aa00aa0e9cee7f92",
                "responses": {
                    "200": {
                        "description": "All option sets",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "properties": {
                                                    "code": {
                                                        "type": "string",
                                                        "example": "family-members"
                                                    },
                                                    "options": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "string"
                                                        },
                                                        "example": [
                                                            "na",
                                                            "pgf",
                                                            "pgm",
                                                            "f",
                                                            "m"
                                                        ]
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            },
            "post": {
                "tags": [
                    "Admin · Structure"
                ],
                "summary": "Create a new shared choice list",
                "description": "Codes only — labels ship separately via PUT .../translations/{locale}.",
                "operationId": "b2a21363a24c6aaab62277cea1cc4cd8",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "code",
                                    "options"
                                ],
                                "properties": {
                                    "code": {
                                        "type": "string",
                                        "example": "agreement"
                                    },
                                    "options": {
                                        "type": "array",
                                        "items": {
                                            "type": "string"
                                        },
                                        "example": [
                                            "agree",
                                            "disagree"
                                        ]
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "properties": {
                                                "code": {
                                                    "type": "string"
                                                },
                                                "optionCount": {
                                                    "type": "integer",
                                                    "example": 2
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Code already taken",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/admin/sections/{section}/questions": {
            "post": {
                "tags": [
                    "Admin · Structure"
                ],
                "summary": "Add a question to a section",
                "description": "`config.optionSet` is required for select/multi_select/matrix/matrix_period and must reference an existing OptionSet. `config.visibleWhen` (question/equals|includes|answered) must point at a real, different question — authoring-time validated so a broken rule can never be saved.",
                "operationId": "9995f4584cb4e68f8963b71c5a31c949",
                "parameters": [
                    {
                        "name": "section",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "followup-s1"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "code",
                                    "type"
                                ],
                                "properties": {
                                    "code": {
                                        "type": "string",
                                        "example": "followup-why"
                                    },
                                    "type": {
                                        "type": "string",
                                        "example": "textarea",
                                        "enum": [
                                            "text",
                                            "textarea",
                                            "select",
                                            "multi_select",
                                            "yes_no",
                                            "yes_no_period",
                                            "yes_no_unknown",
                                            "matrix",
                                            "matrix_period"
                                        ]
                                    },
                                    "position": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "is_required": {
                                        "type": "boolean",
                                        "example": false
                                    },
                                    "config": {
                                        "properties": {
                                            "optionSet": {
                                                "description": "Required for select/multi_select/matrix/matrix_period.",
                                                "type": "string",
                                                "example": "family-members"
                                            },
                                            "group": {
                                                "type": "string",
                                                "nullable": true
                                            },
                                            "maxRows": {
                                                "type": "integer",
                                                "example": 5,
                                                "nullable": true
                                            },
                                            "periods": {
                                                "type": "array",
                                                "items": {
                                                    "type": "string"
                                                },
                                                "nullable": true
                                            },
                                            "allowsDetail": {
                                                "type": "boolean",
                                                "nullable": true
                                            },
                                            "visibleWhen": {
                                                "properties": {
                                                    "question": {
                                                        "type": "string",
                                                        "example": "followup-helpful"
                                                    },
                                                    "equals": {
                                                        "example": false
                                                    }
                                                },
                                                "type": "object",
                                                "nullable": true
                                            }
                                        },
                                        "type": "object",
                                        "nullable": true
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "properties": {
                                                "code": {
                                                    "type": "string"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Missing option set, unknown/self-referencing visibleWhen target, or invalid rule",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/admin/questions/{question}": {
            "delete": {
                "tags": [
                    "Admin · Structure"
                ],
                "summary": "Deactivate a question",
                "description": "Soft delete — existing answers keep resolving.",
                "operationId": "31c459854f3a1ec6d0d1367bb7548a58",
                "parameters": [
                    {
                        "name": "question",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Deactivated",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "properties": {
                                                "code": {
                                                    "type": "string"
                                                },
                                                "isActive": {
                                                    "type": "boolean",
                                                    "example": false
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            },
            "patch": {
                "tags": [
                    "Admin · Structure"
                ],
                "summary": "Update a question",
                "description": "⚠️ Setting `is_required: true` applies to in-flight instances too — any draft that has not answered it can no longer submit.",
                "operationId": "c209b03e7a14a402b022ee50e3aca21e",
                "parameters": [
                    {
                        "name": "question",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "enum": [
                                            "text",
                                            "textarea",
                                            "select",
                                            "multi_select",
                                            "yes_no",
                                            "yes_no_period",
                                            "yes_no_unknown",
                                            "matrix",
                                            "matrix_period"
                                        ]
                                    },
                                    "position": {
                                        "type": "integer"
                                    },
                                    "is_required": {
                                        "type": "boolean"
                                    },
                                    "is_active": {
                                        "type": "boolean"
                                    },
                                    "config": {
                                        "type": "object",
                                        "nullable": true
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Updated",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "properties": {
                                                "code": {
                                                    "type": "string"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Invalid config",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/admin/assessments/{assessment}/sections": {
            "post": {
                "tags": [
                    "Admin · Structure"
                ],
                "summary": "Add a section to an assessment",
                "operationId": "94bb625addf047132bbb260d703a098f",
                "parameters": [
                    {
                        "name": "assessment",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "form-followup"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "code"
                                ],
                                "properties": {
                                    "code": {
                                        "type": "string",
                                        "example": "followup-s1"
                                    },
                                    "position": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "properties": {
                                                "code": {
                                                    "type": "string"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/admin/sections/{section}": {
            "delete": {
                "tags": [
                    "Admin · Structure"
                ],
                "summary": "Delete a section",
                "description": "Hard delete, unlike assessments/questions — refused (409) while the section still has any questions, active or deactivated. Questions cascade-delete with their section, which would cascade-delete their answers too; there is no \"hard delete a question\" endpoint, so a section that ever had a question attached can never be removed via the API — by design, so a submitted answer is never silently destroyed by deleting its container.",
                "operationId": "19f9f29780cbe498113c12cb993f592d",
                "parameters": [
                    {
                        "name": "section",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Deleted",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "properties": {
                                                "code": {
                                                    "type": "string"
                                                },
                                                "deleted": {
                                                    "type": "boolean",
                                                    "example": true
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Still has questions attached (active or not)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            },
            "patch": {
                "tags": [
                    "Admin · Structure"
                ],
                "summary": "Reorder a section",
                "operationId": "a46b07247ca8a1c66bf8f0bcb30e6fff",
                "parameters": [
                    {
                        "name": "section",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "properties": {
                                    "position": {
                                        "type": "integer"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Updated",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "properties": {
                                                "code": {
                                                    "type": "string"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/admin/assessments/{assessment}/translations/{locale}": {
            "put": {
                "tags": [
                    "Admin · Translations"
                ],
                "summary": "Bulk wording upload — how a language ships",
                "description": "Everything one assessment needs in one locale, in one call. Unknown section/question/option codes 422 rather than silently no-opping. Idempotent — safe to re-run. Shipping a new language is just inserting rows: no migration, no deploy — see `database/seeders/YorubaTranslationSeeder.php` for the same mechanism used to seed all 13 forms' Yoruba wording.",
                "operationId": "632927bf22c7cd2ba2f0d84a9488fda5",
                "parameters": [
                    {
                        "name": "assessment",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "form-followup"
                    },
                    {
                        "name": "locale",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "enum": [
                                "en",
                                "yo"
                            ]
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "properties": {
                                    "title": {
                                        "type": "string"
                                    },
                                    "description": {
                                        "type": "string",
                                        "nullable": true
                                    },
                                    "sections": {
                                        "type": "object",
                                        "additionalProperties": {
                                            "properties": {
                                                "title": {
                                                    "type": "string"
                                                },
                                                "description": {
                                                    "type": "string",
                                                    "nullable": true
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "questions": {
                                        "type": "object",
                                        "additionalProperties": {
                                            "properties": {
                                                "label": {
                                                    "type": "string"
                                                },
                                                "help": {
                                                    "type": "string",
                                                    "nullable": true
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "options": {
                                        "description": "Option-set code → option code → label. Option sets are global, not per-assessment — translating `family-members` once via any assessment covers every question that references it.",
                                        "type": "object",
                                        "additionalProperties": {
                                            "type": "object",
                                            "additionalProperties": {
                                                "type": "string"
                                            }
                                        }
                                    }
                                },
                                "type": "object"
                            },
                            "examples": {
                                "english": {
                                    "summary": "Shipping English wording",
                                    "value": {
                                        "title": "Follow-up",
                                        "sections": {
                                            "followup-s1": {
                                                "title": "After your session"
                                            }
                                        },
                                        "questions": {
                                            "followup-helpful": {
                                                "label": "Did you find the session helpful?"
                                            }
                                        }
                                    }
                                },
                                "yoruba": {
                                    "summary": "Shipping Yoruba wording — same assessment, path locale=yo",
                                    "value": {
                                        "title": "Ìbéèrè àfikún",
                                        "sections": {
                                            "followup-s1": {
                                                "title": "Lẹ́yìn ìpàdé yín"
                                            }
                                        },
                                        "questions": {
                                            "followup-helpful": {
                                                "label": "Ṣé ìpàdé náà ṣe ọ́ láǹfààní?"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Rows written per category",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "properties": {
                                                "assessment": {
                                                    "type": "string",
                                                    "example": "form-followup"
                                                },
                                                "locale": {
                                                    "type": "string",
                                                    "example": "yo"
                                                },
                                                "written": {
                                                    "properties": {
                                                        "assessment": {
                                                            "type": "integer",
                                                            "example": 1
                                                        },
                                                        "sections": {
                                                            "type": "integer",
                                                            "example": 1
                                                        },
                                                        "questions": {
                                                            "type": "integer",
                                                            "example": 1
                                                        },
                                                        "options": {
                                                            "type": "integer",
                                                            "example": 0
                                                        }
                                                    },
                                                    "type": "object"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Unsupported locale, or an unknown section/question/option code",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/auth/register": {
            "post": {
                "tags": [
                    "Auth"
                ],
                "summary": "Register a new respondent",
                "description": "Mirrors lffsortingout.org/register.aspx field-for-field — every field marked * there is required here too (only telephone/mobile are optional). Choice fields take an option code, not a raw label — see GET /admin/option-sets for the valid codes.",
                "operationId": "ed42f392010c301892e640067141676e",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "surname",
                                    "other_names",
                                    "email",
                                    "password",
                                    "password_confirmation",
                                    "date_of_birth",
                                    "home_address",
                                    "nationality",
                                    "country_of_residence",
                                    "home_town",
                                    "religion",
                                    "church_name",
                                    "church_address",
                                    "marital_status",
                                    "sex",
                                    "previous_attendance",
                                    "security_question",
                                    "security_answer",
                                    "waiver_accepted"
                                ],
                                "properties": {
                                    "surname": {
                                        "type": "string",
                                        "example": "Doe"
                                    },
                                    "other_names": {
                                        "type": "string",
                                        "example": "Jane"
                                    },
                                    "email": {
                                        "type": "string",
                                        "format": "email",
                                        "example": "jane@example.com"
                                    },
                                    "password": {
                                        "type": "string",
                                        "format": "password",
                                        "example": "password123"
                                    },
                                    "password_confirmation": {
                                        "type": "string",
                                        "format": "password",
                                        "example": "password123"
                                    },
                                    "preferred_locale": {
                                        "type": "string",
                                        "example": "en"
                                    },
                                    "date_of_birth": {
                                        "type": "string",
                                        "format": "date",
                                        "example": "1990-06-15"
                                    },
                                    "home_address": {
                                        "type": "string",
                                        "example": "12 Test Street, Testville"
                                    },
                                    "nationality": {
                                        "type": "string",
                                        "example": "Nigerian"
                                    },
                                    "country_of_residence": {
                                        "description": "Option code from the `countries` set.",
                                        "type": "string",
                                        "example": "nigeria"
                                    },
                                    "home_town": {
                                        "type": "string",
                                        "example": "Testville"
                                    },
                                    "telephone": {
                                        "type": "string",
                                        "example": "08011112222",
                                        "nullable": true
                                    },
                                    "mobile": {
                                        "type": "string",
                                        "example": "08033334444",
                                        "nullable": true
                                    },
                                    "religion": {
                                        "description": "Option code from the `religions` set.",
                                        "type": "string",
                                        "example": "christianity"
                                    },
                                    "other_religion": {
                                        "description": "Required only when religion is `other`.",
                                        "type": "string",
                                        "example": null,
                                        "nullable": true
                                    },
                                    "church_name": {
                                        "type": "string",
                                        "example": "Grace Chapel"
                                    },
                                    "church_address": {
                                        "type": "string",
                                        "example": "1 Grace Chapel Road"
                                    },
                                    "marital_status": {
                                        "description": "Option code from the `marital-statuses` set.",
                                        "type": "string",
                                        "example": "single"
                                    },
                                    "sex": {
                                        "description": "Option code from the `sexes` set.",
                                        "type": "string",
                                        "example": "female"
                                    },
                                    "previous_attendance": {
                                        "description": "Option code from the `previous-attendances` set.",
                                        "type": "string",
                                        "example": "first-time"
                                    },
                                    "security_question": {
                                        "type": "string",
                                        "example": "What is your favorite color?"
                                    },
                                    "security_answer": {
                                        "description": "Hashed at rest, same as password.",
                                        "type": "string",
                                        "example": "Blue"
                                    },
                                    "waiver_accepted": {
                                        "type": "boolean",
                                        "example": true
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Account created. Set `preferred_locale: \"yo\"` (as in the second example) to get Yoruba wording back immediately — see also `?locale=yo` on login/me.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/AuthResponse"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "english": {
                                        "summary": "preferred_locale: en",
                                        "value": {
                                            "data": {
                                                "user": {
                                                    "id": 3,
                                                    "surname": "Doe",
                                                    "otherNames": "Jane",
                                                    "email": "jane@example.com",
                                                    "role": "user",
                                                    "preferredLocale": "en",
                                                    "dateOfBirth": "1990-06-15",
                                                    "homeAddress": "12 Test Street, Testville",
                                                    "nationality": "Nigerian",
                                                    "countryOfResidence": "Nigeria",
                                                    "homeTown": "Testville",
                                                    "telephone": "08011112222",
                                                    "mobile": "08033334444",
                                                    "religion": "Christianity",
                                                    "otherReligion": null,
                                                    "churchName": "Grace Chapel",
                                                    "churchAddress": "1 Grace Chapel Road",
                                                    "maritalStatus": "Single",
                                                    "sex": "Female",
                                                    "previousAttendance": "I am attending for the first time"
                                                },
                                                "token": "1|EXAMPLEjXjZ8vN2pQrLt6yWc4hFmKdGsB9nRaUeYq7oCiSw"
                                            }
                                        }
                                    },
                                    "yoruba": {
                                        "summary": "preferred_locale: yo",
                                        "value": {
                                            "data": {
                                                "user": {
                                                    "id": 4,
                                                    "surname": "Adebayo",
                                                    "otherNames": "Tunde",
                                                    "email": "tunde@example.com",
                                                    "role": "user",
                                                    "preferredLocale": "yo",
                                                    "dateOfBirth": "1990-06-15",
                                                    "homeAddress": "12 Test St",
                                                    "nationality": "Nigerian",
                                                    "countryOfResidence": "Nàìjíríà",
                                                    "homeTown": "Ibadan",
                                                    "telephone": null,
                                                    "mobile": null,
                                                    "religion": "Ìsìn Kristẹni",
                                                    "otherReligion": null,
                                                    "churchName": "Grace Chapel",
                                                    "churchAddress": "1 Grace Rd",
                                                    "maritalStatus": "Àpọ́n",
                                                    "sex": "Ọkùnrin",
                                                    "previousAttendance": "Èyí Ni Ìgbà Àkọ́kọ́ Tí Mo Ń Wá"
                                                },
                                                "token": "2|EXAMPLEyt3p1B1c3ML31v5PX5uqtrGiuMuifHKe2qS2sYb1"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Validation failed",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/auth/login": {
            "post": {
                "tags": [
                    "Auth"
                ],
                "summary": "Log in",
                "description": "The user's own `preferred_locale` drives their profile wording by default (checked after `?locale=` and `Accept-Language`, before the `en` platform default); add `?locale=yo` to override it for this response only, same as the schema endpoints.",
                "operationId": "8cb7742ae98d0990acb2907c4e00bf24",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "email",
                                    "password"
                                ],
                                "properties": {
                                    "email": {
                                        "type": "string",
                                        "format": "email",
                                        "example": "user@lff.test"
                                    },
                                    "password": {
                                        "type": "string",
                                        "format": "password",
                                        "example": "password"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Authenticated",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/AuthResponse"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "english": {
                                        "summary": "Default / preferred_locale: en",
                                        "value": {
                                            "data": {
                                                "user": {
                                                    "id": 1,
                                                    "surname": "User",
                                                    "otherNames": "Client",
                                                    "email": "user@lff.test",
                                                    "role": "user",
                                                    "preferredLocale": "en",
                                                    "dateOfBirth": null,
                                                    "homeAddress": null,
                                                    "nationality": null,
                                                    "countryOfResidence": null,
                                                    "homeTown": null,
                                                    "telephone": null,
                                                    "mobile": null,
                                                    "religion": null,
                                                    "otherReligion": null,
                                                    "churchName": null,
                                                    "churchAddress": null,
                                                    "maritalStatus": null,
                                                    "sex": null,
                                                    "previousAttendance": null
                                                },
                                                "token": "1|EXAMPLEjXjZ8vN2pQrLt6yWc4hFmKdGsB9nRaUeYq7oCiSw"
                                            }
                                        }
                                    },
                                    "yoruba": {
                                        "summary": "?locale=yo (or preferred_locale: yo on the account)",
                                        "value": {
                                            "data": {
                                                "user": {
                                                    "id": 4,
                                                    "surname": "Adebayo",
                                                    "otherNames": "Tunde",
                                                    "email": "tunde@example.com",
                                                    "role": "user",
                                                    "preferredLocale": "yo",
                                                    "dateOfBirth": "1990-06-15",
                                                    "homeAddress": "12 Test St",
                                                    "nationality": "Nigerian",
                                                    "countryOfResidence": "Nàìjíríà",
                                                    "homeTown": "Ibadan",
                                                    "telephone": null,
                                                    "mobile": null,
                                                    "religion": "Ìsìn Kristẹni",
                                                    "otherReligion": null,
                                                    "churchName": "Grace Chapel",
                                                    "churchAddress": "1 Grace Rd",
                                                    "maritalStatus": "Àpọ́n",
                                                    "sex": "Ọkùnrin",
                                                    "previousAttendance": "Èyí Ni Ìgbà Àkọ́kọ́ Tí Mo Ń Wá"
                                                },
                                                "token": "2|EXAMPLEyt3p1B1c3ML31v5PX5uqtrGiuMuifHKe2qS2sYb1"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Credentials do not match",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/auth/logout": {
            "post": {
                "tags": [
                    "Auth"
                ],
                "summary": "Revoke the current token",
                "operationId": "0d29c740dc06d77602af8095bf4654cc",
                "responses": {
                    "200": {
                        "description": "Revoked"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/auth/me": {
            "get": {
                "tags": [
                    "Auth"
                ],
                "summary": "Current authenticated user",
                "description": "Same locale resolution as everywhere else: `?locale=yo` beats `Accept-Language`, which beats the account's `preferredLocale`, which beats `en`.",
                "operationId": "a9c495788506b114956e3f509e5d90a2",
                "responses": {
                    "200": {
                        "description": "Profile",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/UserProfile"
                                        }
                                    },
                                    "type": "object"
                                },
                                "examples": {
                                    "english": {
                                        "summary": "English",
                                        "value": {
                                            "data": {
                                                "id": 3,
                                                "surname": "Doe",
                                                "otherNames": "Jane",
                                                "email": "jane@example.com",
                                                "role": "user",
                                                "preferredLocale": "en",
                                                "dateOfBirth": "1990-06-15",
                                                "homeAddress": "12 Test Street, Testville",
                                                "nationality": "Nigerian",
                                                "countryOfResidence": "Nigeria",
                                                "homeTown": "Testville",
                                                "telephone": "08011112222",
                                                "mobile": "08033334444",
                                                "religion": "Christianity",
                                                "otherReligion": null,
                                                "churchName": "Grace Chapel",
                                                "churchAddress": "1 Grace Chapel Road",
                                                "maritalStatus": "Single",
                                                "sex": "Female",
                                                "previousAttendance": "I am attending for the first time"
                                            }
                                        }
                                    },
                                    "yoruba": {
                                        "summary": "?locale=yo",
                                        "value": {
                                            "data": {
                                                "id": 4,
                                                "surname": "Adebayo",
                                                "otherNames": "Tunde",
                                                "email": "tunde@example.com",
                                                "role": "user",
                                                "preferredLocale": "yo",
                                                "dateOfBirth": "1990-06-15",
                                                "homeAddress": "12 Test St",
                                                "nationality": "Nigerian",
                                                "countryOfResidence": "Nàìjíríà",
                                                "homeTown": "Ibadan",
                                                "telephone": null,
                                                "mobile": null,
                                                "religion": "Ìsìn Kristẹni",
                                                "otherReligion": null,
                                                "churchName": "Grace Chapel",
                                                "churchAddress": "1 Grace Rd",
                                                "maritalStatus": "Àpọ́n",
                                                "sex": "Ọkùnrin",
                                                "previousAttendance": "Èyí Ni Ìgbà Àkọ́kọ́ Tí Mo Ń Wá"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/instances/{instance}/assessments/{assessment}/answers": {
            "get": {
                "tags": [
                    "Client · Answers"
                ],
                "summary": "Read answers for one assessment within an instance",
                "description": "Returns exactly the shape the PUT accepts, so a client can GET → edit → PUT with no transformation.",
                "operationId": "cdcb289c31f873e47c00a9792d44570e",
                "parameters": [
                    {
                        "name": "instance",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "assessment",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "form-0"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Current answers",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/AnswerEnvelope"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not the current user's instance",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            },
            "put": {
                "tags": [
                    "Client · Answers"
                ],
                "summary": "Idempotent bulk-upsert of answers",
                "description": "Replace semantics — safe to re-run. The API refuses answers to hidden (visibleWhen not met) questions, and automatically prunes any answer stranded by a trigger changing in the same request. Visibility is judged on the state *after* the write, so a trigger and its dependent can be satisfied in one call.",
                "operationId": "ee35af6d9c8019cee3bbaac2498dd700",
                "parameters": [
                    {
                        "name": "instance",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "assessment",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "form-0"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "answers"
                                ],
                                "properties": {
                                    "answers": {
                                        "type": "array",
                                        "items": {
                                            "$ref": "#/components/schemas/Answer"
                                        }
                                    }
                                },
                                "type": "object"
                            },
                            "example": {
                                "answers": [
                                    {
                                        "question": "f0-challenge",
                                        "rows": [
                                            {
                                                "row": 0,
                                                "value": {
                                                    "text": "Persistent financial difficulty affecting my family"
                                                }
                                            }
                                        ]
                                    },
                                    {
                                        "question": "f0-duration",
                                        "rows": [
                                            {
                                                "row": 0,
                                                "option": "2"
                                            }
                                        ]
                                    },
                                    {
                                        "question": "f1-a-1",
                                        "options": [
                                            "f",
                                            "m"
                                        ]
                                    },
                                    {
                                        "question": "f3-a-1",
                                        "value": {
                                            "answer": true,
                                            "periods": [
                                                "past"
                                            ]
                                        }
                                    },
                                    {
                                        "question": "f7-a-1",
                                        "value": {
                                            "answer": false
                                        }
                                    },
                                    {
                                        "question": "f1-s2-b-1",
                                        "value": {
                                            "answer": "yes",
                                            "detail": "Known in the village as a herbalist"
                                        }
                                    },
                                    {
                                        "question": "f10-a-1",
                                        "cells": [
                                            {
                                                "option": "self",
                                                "periods": [
                                                    "past"
                                                ]
                                            }
                                        ]
                                    },
                                    {
                                        "question": "f12-a-4-areas",
                                        "options": [
                                            "head",
                                            "hands"
                                        ]
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Written and read back",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/AnswerEnvelope"
                                        },
                                        "meta": {
                                            "properties": {
                                                "questionsWritten": {
                                                    "type": "integer",
                                                    "example": 2
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not the current user's instance, or unknown/inactive assessment",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Instance already submitted — immutable",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Invalid payload, or an answer targets a currently-hidden question",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/assessments": {
            "get": {
                "tags": [
                    "Client · Assessments"
                ],
                "summary": "List active assessments",
                "description": "Localized titles only — fetch /assessments/{code}/schema for the full render tree.",
                "operationId": "48071bcf0b1ba25413427d786e44bc26",
                "parameters": [
                    {
                        "name": "locale",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "en",
                                "yo"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Active assessments, ordered by position",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/AssessmentSummary"
                                            }
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/assessments/{assessment}/schema": {
            "get": {
                "tags": [
                    "Client · Assessments"
                ],
                "summary": "Full localized render tree for one assessment",
                "description": "Everything a client needs to render the form. Structure and wording are separate — the same assessment renders in any supported language; untranslated strings fall back to English rather than breaking.",
                "operationId": "db328882f5e8c047095f67b5b9317a81",
                "parameters": [
                    {
                        "name": "assessment",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "form-0"
                    },
                    {
                        "name": "locale",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "en",
                                "yo"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Schema tree",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/AssessmentSchema"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Unknown or inactive assessment code",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/locales": {
            "get": {
                "tags": [
                    "Client · Assessments"
                ],
                "summary": "Supported locales",
                "operationId": "64e1583faae0efa41f68550157f0abf2",
                "responses": {
                    "200": {
                        "description": "Locale codes this platform can render wording in",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "properties": {
                                                "supported": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "example": [
                                                        "en",
                                                        "yo"
                                                    ]
                                                },
                                                "default": {
                                                    "type": "string",
                                                    "example": "en"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/instances": {
            "get": {
                "tags": [
                    "Client · Instances"
                ],
                "summary": "List the current user's instances",
                "operationId": "0ac5f252a654ff602eac64d3e8106115",
                "parameters": [
                    {
                        "name": "perPage",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "example": 25,
                            "maximum": 100
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Most recent first",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/InstanceSummary"
                                            }
                                        },
                                        "meta": {
                                            "properties": {
                                                "pagination": {
                                                    "$ref": "#/components/schemas/PaginationMeta"
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            },
            "post": {
                "tags": [
                    "Client · Instances"
                ],
                "summary": "Start a new instance",
                "description": "One instance = one attempt at the whole battery. A person can hold several over time.",
                "operationId": "80b5e8bfc3bcabfb0fdb202ef8b842bc",
                "responses": {
                    "201": {
                        "description": "Created as draft",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/InstanceSummary"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/instances/{instance}": {
            "get": {
                "tags": [
                    "Client · Instances"
                ],
                "summary": "Instance detail with per-assessment progress",
                "operationId": "a295c638e755f49be43a3cb813916a6f",
                "parameters": [
                    {
                        "name": "instance",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Everything a form navigator needs",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "allOf": [
                                                {
                                                    "$ref": "#/components/schemas/InstanceSummary"
                                                },
                                                {
                                                    "properties": {
                                                        "progress": {
                                                            "type": "array",
                                                            "items": {
                                                                "$ref": "#/components/schemas/InstanceProgress"
                                                            }
                                                        }
                                                    },
                                                    "type": "object"
                                                }
                                            ]
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not the current user's instance",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/instances/{instance}/submit": {
            "post": {
                "tags": [
                    "Client · Instances"
                ],
                "summary": "Submit — locks the instance",
                "description": "Succeeds only once every required question (that is currently visible) has an answer. Queues a confirmation to the respondent and a review alert to every admin. Further writes to this instance return 409.",
                "operationId": "f4f9ebe5c88ed9648a5fc659ded703a4",
                "parameters": [
                    {
                        "name": "instance",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Now submitted",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/InstanceSummary"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Already submitted",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "A required, currently-visible question is unanswered",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/option-sets/{optionSet}": {
            "get": {
                "tags": [
                    "Client · Assessments"
                ],
                "summary": "Localized options for one choice list",
                "description": "Unauthenticated — needed to render registration's choice fields (country_of_residence, religion, marital_status, sex, previous_attendance) before an account exists. Send the returned `code` back as the field value on POST /auth/register.",
                "operationId": "9312a8a6dff472032990ef1ac44b3ce2",
                "parameters": [
                    {
                        "name": "optionSet",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "religions"
                    },
                    {
                        "name": "locale",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "en",
                                "yo"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Options in position order",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "data": {
                                            "properties": {
                                                "code": {
                                                    "type": "string",
                                                    "example": "religions"
                                                },
                                                "options": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/OptionRef"
                                                    }
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Unknown option-set code",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ProblemDetails"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "ProblemDetails": {
                "description": "RFC 9457 problem+json error envelope used by every error response.",
                "properties": {
                    "type": {
                        "description": "Carries the document-level OpenAPI attributes (info, servers, security\nscheme, shared error schemas) that don't belong to any single controller.\nNever instantiated — swagger-php only reads the attributes off the class.",
                        "type": "string",
                        "example": "about:blank"
                    },
                    "title": {
                        "type": "string",
                        "example": "Validation failed"
                    },
                    "status": {
                        "type": "integer",
                        "example": 422
                    },
                    "detail": {
                        "type": "string",
                        "example": "One or more fields are invalid."
                    },
                    "errors": {
                        "description": "Present on 422s — field name to array of messages.",
                        "type": "object",
                        "nullable": true,
                        "additionalProperties": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    }
                },
                "type": "object"
            },
            "PaginationMeta": {
                "properties": {
                    "page": {
                        "type": "integer",
                        "example": 1
                    },
                    "perPage": {
                        "type": "integer",
                        "example": 25
                    },
                    "total": {
                        "type": "integer",
                        "example": 3
                    },
                    "lastPage": {
                        "type": "integer",
                        "example": 1
                    }
                },
                "type": "object"
            },
            "UserProfile": {
                "description": "Full registrant profile, returned by register/login/me. Choice fields (countryOfResidence, religion, maritalStatus, sex, previousAttendance) are resolved to a localized label, not the raw option code.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "example": 3
                    },
                    "surname": {
                        "type": "string",
                        "example": "Doe"
                    },
                    "otherNames": {
                        "type": "string",
                        "example": "Jane"
                    },
                    "email": {
                        "type": "string",
                        "format": "email",
                        "example": "jane@example.com"
                    },
                    "role": {
                        "type": "string",
                        "example": "user",
                        "enum": [
                            "user",
                            "admin"
                        ]
                    },
                    "preferredLocale": {
                        "type": "string",
                        "example": "en"
                    },
                    "dateOfBirth": {
                        "type": "string",
                        "format": "date",
                        "example": "1990-06-15"
                    },
                    "homeAddress": {
                        "type": "string",
                        "example": "12 Test Street, Testville"
                    },
                    "nationality": {
                        "type": "string",
                        "example": "Nigerian"
                    },
                    "countryOfResidence": {
                        "type": "string",
                        "example": "Nigeria"
                    },
                    "homeTown": {
                        "type": "string",
                        "example": "Testville"
                    },
                    "telephone": {
                        "type": "string",
                        "example": "08011112222",
                        "nullable": true
                    },
                    "mobile": {
                        "type": "string",
                        "example": "08033334444",
                        "nullable": true
                    },
                    "religion": {
                        "type": "string",
                        "example": "Christianity"
                    },
                    "otherReligion": {
                        "type": "string",
                        "example": null,
                        "nullable": true
                    },
                    "churchName": {
                        "type": "string",
                        "example": "Grace Chapel"
                    },
                    "churchAddress": {
                        "type": "string",
                        "example": "1 Grace Chapel Road"
                    },
                    "maritalStatus": {
                        "type": "string",
                        "example": "Single"
                    },
                    "sex": {
                        "type": "string",
                        "example": "Female"
                    },
                    "previousAttendance": {
                        "type": "string",
                        "example": "I am attending for the first time"
                    }
                },
                "type": "object"
            },
            "AuthResponse": {
                "properties": {
                    "user": {
                        "$ref": "#/components/schemas/UserProfile"
                    },
                    "token": {
                        "type": "string",
                        "example": "1|EXAMPLEjXjZ8vN2pQrLt6yWc4hFmKdGsB9nRaUeYq7oCiSw"
                    }
                },
                "type": "object"
            },
            "AssessmentSummary": {
                "properties": {
                    "code": {
                        "type": "string",
                        "example": "form-0"
                    },
                    "version": {
                        "type": "integer",
                        "example": 1
                    },
                    "title": {
                        "type": "string",
                        "example": "General Information"
                    }
                },
                "type": "object"
            },
            "OptionRef": {
                "properties": {
                    "code": {
                        "type": "string",
                        "example": "na"
                    },
                    "label": {
                        "type": "string",
                        "example": "N/A"
                    }
                },
                "type": "object"
            },
            "Question": {
                "description": "Shape varies by `type` — see README \"API surface\" for the exact answer payload each type expects. `options` appears only when the question references an option set; `group`/`maxRows` only on repeatable questions; `visibleWhen` only on conditional questions.",
                "properties": {
                    "code": {
                        "type": "string",
                        "example": "f0-challenge"
                    },
                    "type": {
                        "type": "string",
                        "example": "textarea",
                        "enum": [
                            "text",
                            "textarea",
                            "select",
                            "multi_select",
                            "yes_no",
                            "yes_no_unknown",
                            "yes_no_period",
                            "matrix",
                            "matrix_period"
                        ]
                    },
                    "required": {
                        "type": "boolean",
                        "example": true
                    },
                    "label": {
                        "type": "string",
                        "example": "Please summarise your challenges or problems"
                    },
                    "help": {
                        "type": "string",
                        "example": null,
                        "nullable": true
                    },
                    "group": {
                        "type": "string",
                        "example": "challenges",
                        "nullable": true
                    },
                    "maxRows": {
                        "type": "integer",
                        "example": 5,
                        "nullable": true
                    },
                    "options": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/OptionRef"
                        },
                        "nullable": true
                    },
                    "visibleWhen": {
                        "description": "Present only on conditional questions.",
                        "properties": {
                            "question": {
                                "type": "string",
                                "example": "f9-prior-marriage"
                            },
                            "equals": {
                                "example": true
                            }
                        },
                        "type": "object",
                        "nullable": true
                    }
                },
                "type": "object"
            },
            "AssessmentSection": {
                "properties": {
                    "code": {
                        "type": "string",
                        "example": "f0-s1"
                    },
                    "title": {
                        "type": "string",
                        "example": "Section 1 of 1 (General Information)"
                    },
                    "description": {
                        "type": "string",
                        "example": null,
                        "nullable": true
                    },
                    "questions": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Question"
                        }
                    }
                },
                "type": "object"
            },
            "InstanceSummary": {
                "description": "One attempt at the whole battery.",
                "properties": {
                    "id": {
                        "type": "string",
                        "example": "01kyxkwy4j5m1xmb1pnnxky51x"
                    },
                    "reference": {
                        "type": "string",
                        "example": "SO-2026-000123"
                    },
                    "status": {
                        "type": "string",
                        "example": "draft",
                        "enum": [
                            "draft",
                            "submitted"
                        ]
                    },
                    "startedAt": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "submittedAt": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    }
                },
                "type": "object"
            },
            "InstanceProgress": {
                "properties": {
                    "assessment": {
                        "type": "string",
                        "example": "form-0"
                    },
                    "questionsAnswered": {
                        "type": "integer",
                        "example": 2
                    },
                    "questionsTotal": {
                        "type": "integer",
                        "example": 3
                    }
                },
                "type": "object"
            },
            "Answer": {
                "description": "Shape depends on the question's type — `value` for single answers (text/yes-no, optionally with `periods`/`detail`), `rows` for repeatable questions, `options`/`cells` for matrix questions. See README \"API surface\" for the full type-by-type breakdown; the example here shows one of each.",
                "properties": {
                    "question": {
                        "type": "string",
                        "example": "f0-challenge"
                    },
                    "value": {
                        "type": "object",
                        "nullable": true
                    },
                    "rows": {
                        "type": "array",
                        "items": {
                            "type": "object"
                        },
                        "nullable": true
                    },
                    "options": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "nullable": true
                    },
                    "cells": {
                        "type": "array",
                        "items": {
                            "type": "object"
                        },
                        "nullable": true
                    }
                },
                "type": "object"
            },
            "AnswerEnvelope": {
                "properties": {
                    "assessment": {
                        "type": "string",
                        "example": "form-0"
                    },
                    "answers": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Answer"
                        }
                    }
                },
                "type": "object"
            },
            "AssessmentSchema": {
                "properties": {
                    "code": {
                        "type": "string",
                        "example": "form-0"
                    },
                    "version": {
                        "type": "integer",
                        "example": 1
                    },
                    "title": {
                        "type": "string",
                        "example": "General Information"
                    },
                    "description": {
                        "type": "string",
                        "example": "Summarise your challenges, how long you have had them, and the efforts made so far.",
                        "nullable": true
                    },
                    "updatedAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "sections": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/AssessmentSection"
                        }
                    }
                },
                "type": "object"
            }
        },
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "description": "Sanctum personal access token returned by register/login, e.g. `1|abc123...`",
                "scheme": "bearer"
            }
        }
    },
    "tags": [
        {
            "name": "Admin · Assessments",
            "description": "Admin · Assessments"
        },
        {
            "name": "Admin · Review",
            "description": "Admin · Review"
        },
        {
            "name": "Admin · Structure",
            "description": "Admin · Structure"
        },
        {
            "name": "Admin · Translations",
            "description": "Admin · Translations"
        },
        {
            "name": "Auth",
            "description": "Auth"
        },
        {
            "name": "Client · Answers",
            "description": "Client · Answers"
        },
        {
            "name": "Client · Assessments",
            "description": "Client · Assessments"
        },
        {
            "name": "Client · Instances",
            "description": "Client · Instances"
        }
    ]
}