{
  "openapi": "3.1.0",
  "info": {
    "title": "ONE API",
    "version": "0.25.0",
    "description": "HTTP API for approved ONE agent and integration access."
  },
  "servers": [
    {
      "url": "https://one.geotech.one/api",
      "description": "ONE production API"
    },
    {
      "url": "https://geotech-crm.web.app/api",
      "description": "Permanent Firebase Hosting fallback"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    },
    {
      "geoCrmKey": []
    }
  ],
  "paths": {
    "/finance/projects/{boardId}/summary": {
      "get": {
        "operationId": "getProjectFinanceSummary",
        "tags": [
          "Finance"
        ],
        "summary": "Read compact project cost and income totals",
        "description": "Returns summaries keyed by authorized project ID and revision. Each cost/income currency bucket contains weightedMinor {n,d} as exact rational integer strings, fixedEurMinor as an integer string and count. Apply the same reporting FX policy as detailed entries. Requires live Finance and board/project grants.",
        "parameters": [
          {
            "name": "boardId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result; revision identifies the derived index version."
          },
          "401": {
            "description": "Authentication required."
          },
          "403": {
            "description": "Finance and board/project access are required."
          },
          "409": {
            "description": "Source revision changed. Restart the read or review a fresh rebuild dry run."
          },
          "503": {
            "description": "Derived summaries are not verified and complete; no full-ledger fallback."
          }
        }
      }
    },
    "/finance/projects/{boardId}/{projectId}/entries": {
      "get": {
        "operationId": "listProjectFinanceEntries",
        "tags": [
          "Finance"
        ],
        "summary": "Read a page of project allocation details",
        "description": "Returns records {transactionId: {transaction, decision}}, categories, revision and nextCursor. Up to 100 records per page. Restart if a subsequent page has a different revision. Canonical minor-unit amounts remain strings.",
        "parameters": [
          {
            "name": "boardId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "projectId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result; revision identifies the derived index version."
          },
          "401": {
            "description": "Authentication required."
          },
          "403": {
            "description": "Finance and board/project access are required."
          },
          "409": {
            "description": "Source revision changed. Restart the read or review a fresh rebuild dry run."
          },
          "503": {
            "description": "Derived summaries are not verified and complete; no full-ledger fallback."
          }
        }
      }
    },
    "/finance/project-summaries/rebuild": {
      "post": {
        "operationId": "rebuildProjectFinanceSummaries",
        "tags": [
          "Finance"
        ],
        "summary": "Preview or apply an owner-approved derived-summary rebuild",
        "description": "Owner Firebase session only. Defaults to dry run returning sourceDigest, transactions, allocatedTransactions, summaryBytes and applied=false. An apply holds the Finance mutation lock, requires the current sourceDigest and exact confirmation, and replaces only the derived index. Canonical Finance records are preserved. Equivalent MCP tool: finance_rebuild_project_summaries, available to an owner OAuth actor with write scope.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "apply": {
                    "type": "boolean",
                    "default": false
                  },
                  "confirm": {
                    "type": "string",
                    "const": "REBUILD PROJECT FINANCE SUMMARIES"
                  },
                  "sourceDigest": {
                    "type": "string",
                    "pattern": "^[a-f0-9]{64}$"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Authorized result; revision identifies the derived index version."
          },
          "401": {
            "description": "Authentication required."
          },
          "403": {
            "description": "Finance and board/project access are required."
          },
          "409": {
            "description": "Source revision changed. Restart the read or review a fresh rebuild dry run."
          },
          "503": {
            "description": "Derived summaries are not verified and complete; no full-ledger fallback."
          }
        }
      }
    },
    "/health": {
      "get": {
        "summary": "Health check",
        "security": [],
        "responses": {
          "200": {
            "description": "API is reachable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          }
        }
      }
    },
    "/info": {
      "get": {
        "summary": "Get app info",
        "description": "Return canonical ONE app URLs, API/docs links, and short answer hints for agents.",
        "security": [],
        "responses": {
          "200": {
            "description": "Canonical ONE app metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppInfoResponse"
                }
              }
            }
          }
        }
      }
    },
    "/procurement/categories": {
      "post": {
        "summary": "Create a Procurement category",
        "description": "Add a shared Procurement category. Requires a signed-in ONE owner or admin with current Procurement edit access. API keys are not accepted.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "type": "object", "required": ["name"], "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 80 } } } } }
        },
        "responses": { "201": { "description": "Category created." } }
      }
    },
    "/procurement/requests": {
      "get": {
        "summary": "List visible Procurement requests",
        "description": "List requests visible to the signed-in requester, approver, watcher, owner, or admin together with the permitted People/office selection metadata. Requires current Procurement view access. API keys are not accepted.",
        "security": [{ "firebaseAuth": [] }],
        "responses": { "200": { "description": "Visible Procurement workspace.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProcurementListResponse" } } } } }
      },
      "post": {
        "summary": "Create a Procurement request",
        "description": "Create a request and ordered approval chain as the signed-in person. Requires current Procurement edit access. API keys are not accepted.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProcurementRequestCreateInput" } } } },
        "responses": { "201": { "description": "Request created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProcurementRequestResponse" } } } } }
      }
    },
    "/procurement/requests/{requestId}": {
      "parameters": [{ "name": "requestId", "in": "path", "required": true, "schema": { "type": "string", "minLength": 1, "maxLength": 200 } }],
      "patch": {
        "summary": "Update a Procurement request",
        "description": "Update a pending request and reset its approval chain when the signed-in person is allowed to edit it.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProcurementRequestUpdateInput" } } } },
        "responses": { "200": { "description": "Request updated.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProcurementRequestResponse" } } } } }
      },
      "delete": {
        "summary": "Delete a Procurement request",
        "description": "Permanently remove an eligible request and its discussion/attachment links. A linked Hardware inventory record is preserved.",
        "security": [{ "firebaseAuth": [] }],
        "responses": { "200": { "description": "Request deleted." } }
      }
    },
    "/procurement/requests/{requestId}/approvers": {
      "post": {
        "summary": "Append Procurement approvers",
        "description": "Append people to an eligible ordered approval chain. Requires current request-level permission.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "name": "requestId", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["approvers"], "properties": { "approvers": { "type": "array", "minItems": 1, "maxItems": 12, "items": { "$ref": "#/components/schemas/ProcurementApproverInput" } } } } } } },
        "responses": { "201": { "description": "Approvers appended.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProcurementRequestResponse" } } } } }
      }
    },
    "/procurement/requests/{requestId}/comments": {
      "post": {
        "summary": "Add a Procurement comment",
        "description": "Add an internal request comment and optional People mentions as the signed-in person.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "name": "requestId", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProcurementCommentInput" } } } },
        "responses": { "201": { "description": "Comment added.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProcurementRequestResponse" } } } } }
      }
    },
    "/procurement/requests/{requestId}/comments/{commentId}": {
      "parameters": [
        { "name": "requestId", "in": "path", "required": true, "schema": { "type": "string" } },
        { "name": "commentId", "in": "path", "required": true, "schema": { "type": "string" } }
      ],
      "patch": {
        "summary": "Edit a Procurement comment",
        "description": "Edit an eligible internal comment and its People mentions.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProcurementCommentInput" } } } },
        "responses": { "200": { "description": "Comment updated.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProcurementRequestResponse" } } } } }
      },
      "delete": {
        "summary": "Delete a Procurement comment",
        "description": "Delete an eligible internal comment.",
        "security": [{ "firebaseAuth": [] }],
        "responses": { "200": { "description": "Comment deleted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProcurementRequestResponse" } } } } }
      }
    },
    "/procurement/requests/{requestId}/decision": {
      "post": {
        "summary": "Decide a Procurement request",
        "description": "Approve, reject, or request changes when the signed-in person is the active approver.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "name": "requestId", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["decision"], "properties": { "decision": { "type": "string", "enum": ["approve", "reject", "request_changes"] }, "note": { "type": "string", "maxLength": 4000 } } } } } },
        "responses": { "200": { "description": "Decision recorded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProcurementRequestResponse" } } } } }
      }
    },
    "/procurement/requests/{requestId}/lifecycle": {
      "patch": {
        "summary": "Update Procurement Hardware lifecycle",
        "description": "Update an eligible Hardware request status/destination and synchronize its Hardware record. Restricted to the named Hardware managers enforced by ONE.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "name": "requestId", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "status": { "type": "string", "enum": ["approved", "ordered", "delivered", "complete", "cancelled"] }, "destination": { "$ref": "#/components/schemas/ProcurementDestinationInput" } } } } } },
        "responses": { "200": { "description": "Lifecycle updated.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProcurementRequestResponse" } } } } }
      }
    },
    "/procurement/requests/{requestId}/attachments": {
      "post": {
        "summary": "Upload a Procurement attachment",
        "description": "Upload a base64-encoded attachment smaller than 8 MB to a visible request. The object remains private to the Procurement workflow.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "name": "requestId", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["fileName", "dataBase64"], "properties": { "fileName": { "type": "string", "minLength": 1, "maxLength": 180 }, "contentType": { "type": "string", "maxLength": 180 }, "dataBase64": { "type": "string", "format": "byte" } } } } } },
        "responses": { "201": { "description": "Attachment uploaded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProcurementRequestResponse" } } } }, "413": { "description": "Attachment exceeds 8 MB." } }
      }
    },
    "/hardware/boards/{boardId}/assets": {
      "get": {
        "summary": "List Hardware assets",
        "description": "List canonical Hardware inventory, custody, audit revision, costs, procurement links, and document counts. Requires Firebase OAuth plus Hardware view access.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "name": "query", "in": "query", "schema": { "type": "string", "maxLength": 240 } },
          { "name": "status", "in": "query", "schema": { "type": "string", "enum": ["assigned", "available", "returned", "transferred", "bought_out", "removed", "archived"] } },
          { "name": "custodian_type", "in": "query", "schema": { "type": "string", "enum": ["person", "office", "unassigned"] } },
          { "name": "include_archived", "in": "query", "schema": { "type": "boolean", "default": false } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 } }
        ],
        "responses": { "200": { "description": "Visible Hardware inventory.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HardwareAssetListResponse" } } } } }
      },
      "post": {
        "summary": "Create Hardware asset",
        "description": "Create a canonical Hardware asset with audited initial custody. Requires Firebase OAuth plus Hardware edit access.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HardwareAssetCreateInput" } } } },
        "responses": { "201": { "description": "Hardware asset created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HardwareAssetResponse" } } } } }
      }
    },
    "/hardware/boards/{boardId}/assets/{assetId}": {
      "get": {
        "summary": "Get Hardware asset",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/HardwareAssetId" }],
        "responses": { "200": { "description": "Hardware asset, custody and history.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HardwareAssetResponse" } } } } }
      },
      "patch": {
        "summary": "Update Hardware asset",
        "description": "Update non-custody fields using the current 64-character asset revision.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/HardwareAssetId" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HardwareAssetUpdateInput" } } } },
        "responses": { "200": { "description": "Hardware asset updated.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HardwareAssetResponse" } } } } }
      },
      "delete": {
        "summary": "Archive Hardware asset",
        "description": "Archive the asset, release custody, and append an audit movement. Requires current revision and exact asset-ID confirmation.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/HardwareAssetId" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HardwareAssetArchiveInput" } } } },
        "responses": { "200": { "description": "Hardware asset archived.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HardwareAssetResponse" } } } } }
      }
    },
    "/hardware/boards/{boardId}/assets/{assetId}/move": {
      "post": {
        "summary": "Move Hardware asset",
        "description": "Change custody and append an immutable movement. Requires current revision and an idempotency key.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/HardwareAssetId" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HardwareAssetMoveInput" } } } },
        "responses": { "200": { "description": "Hardware custody updated or idempotent replay returned.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HardwareAssetResponse" } } } } }
      }
    },
    "/hardware/boards/{boardId}/assets/{assetId}/documents": {
      "get": {
        "summary": "List Hardware documents",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/HardwareAssetId" }],
        "responses": { "200": { "description": "Safe private-document metadata.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HardwareDocumentListResponse" } } } } }
      },
      "post": {
        "summary": "Upload Hardware document",
        "description": "Upload raw PDF, JPEG, PNG, or WebP bytes up to 20 MB. Send the file name in X-File-Name.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "$ref": "#/components/parameters/HardwareAssetId" },
          { "name": "X-File-Name", "in": "header", "required": true, "schema": { "type": "string", "maxLength": 180 } }
        ],
        "requestBody": { "required": true, "content": { "application/pdf": { "schema": { "type": "string", "format": "binary" } }, "image/jpeg": { "schema": { "type": "string", "format": "binary" } }, "image/png": { "schema": { "type": "string", "format": "binary" } }, "image/webp": { "schema": { "type": "string", "format": "binary" } } } },
        "responses": { "201": { "description": "Document stored privately.", "content": { "application/json": { "schema": { "type": "object", "properties": { "document": { "$ref": "#/components/schemas/HardwareDocumentRecord" } } } } } } }
      }
    },
    "/hardware/boards/{boardId}/assets/{assetId}/documents/{documentId}": {
      "get": {
        "summary": "Download Hardware document",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/HardwareAssetId" }, { "$ref": "#/components/parameters/DocumentId" }],
        "responses": { "200": { "description": "Checksum-verified private document.", "content": { "application/octet-stream": { "schema": { "type": "string", "format": "binary" } } } } }
      },
      "delete": {
        "summary": "Delete Hardware document",
        "description": "Requires X-Document-Revision and URL-encoded X-Confirm-Document-Name headers.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/HardwareAssetId" }, { "$ref": "#/components/parameters/DocumentId" },
          { "name": "X-Document-Revision", "in": "header", "required": true, "schema": { "type": "string", "pattern": "^[a-f0-9]{64}$" } },
          { "name": "X-Confirm-Document-Name", "in": "header", "required": true, "schema": { "type": "string", "maxLength": 540 } }
        ],
        "responses": { "200": { "description": "Document metadata and private bytes deleted." } }
      }
    },
    "/people/boards/{boardId}/items/{itemId}/documents": {
      "get": {
        "summary": "List person documents",
        "description": "Requires Firebase OAuth plus the explicit People Documents view grant.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/ItemId" }, { "$ref": "#/components/parameters/PeopleDocumentColumnId" }, { "name": "folder_id", "in": "query", "schema": { "type": "string", "maxLength": 200 } }],
        "responses": { "200": { "description": "Safe person-document metadata.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PeopleDocumentListResponse" } } } } }
      },
      "post": {
        "summary": "Upload person document",
        "description": "Atomically stores private bytes and appends the file to the selected person document folder.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/ItemId" }, { "$ref": "#/components/parameters/PeopleDocumentColumnId" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PeopleDocumentUploadInput" } } } },
        "responses": { "201": { "description": "Person document stored and linked.", "content": { "application/json": { "schema": { "type": "object", "properties": { "document": { "$ref": "#/components/schemas/PeopleDocumentRecord" } } } } } } }
      }
    },
    "/people/boards/{boardId}/items/{itemId}/documents/{documentId}": {
      "get": {
        "summary": "Download person document",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/ItemId" }, { "$ref": "#/components/parameters/PeopleDocumentColumnId" }, { "$ref": "#/components/parameters/DocumentId" }],
        "responses": { "200": { "description": "Private person document.", "content": { "application/octet-stream": { "schema": { "type": "string", "format": "binary" } } } } }
      },
      "delete": {
        "summary": "Delete person document",
        "description": "Atomically removes the person-record link and private bytes using revision and exact-name confirmation.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/ItemId" }, { "$ref": "#/components/parameters/PeopleDocumentColumnId" }, { "$ref": "#/components/parameters/DocumentId" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PeopleDocumentDeleteInput" } } } },
        "responses": { "200": { "description": "Person document deleted." } }
      }
    },
    "/people/boards/{boardId}/documents": {
      "get": {
        "summary": "List company-link documents",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }, { "name": "folder_id", "in": "query", "schema": { "type": "string", "maxLength": 200 } }],
        "responses": { "200": { "description": "Safe company-link document metadata.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PeopleDocumentListResponse" } } } } }
      },
      "post": {
        "summary": "Upload company-link document",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PeopleDocumentUploadInput" } } } },
        "responses": { "201": { "description": "Company-link document stored and linked.", "content": { "application/json": { "schema": { "type": "object", "properties": { "document": { "$ref": "#/components/schemas/PeopleDocumentRecord" } } } } } } }
      }
    },
    "/people/boards/{boardId}/documents/{documentId}": {
      "get": {
        "summary": "Download company-link document",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/DocumentId" }],
        "responses": { "200": { "description": "Private company-link document.", "content": { "application/octet-stream": { "schema": { "type": "string", "format": "binary" } } } } }
      },
      "delete": {
        "summary": "Delete company-link document",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/DocumentId" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PeopleDocumentDeleteInput" } } } },
        "responses": { "200": { "description": "Company-link document deleted." } }
      }
    },
    "/boards/{boardId}/remote-machines": {
      "get": {
        "summary": "List Remote Machines",
        "description": "List the OneClient-managed Remote Machines scheduler inventory with live availability, active sessions, specifications, optional CPU/GPU temperatures, network addresses, and optional booking-window conflicts. The credential must have read access to the selected Remote Machines board. Suitable for Slack and other agent integrations.",
        "security": [
          { "bearerAuth": [] },
          { "geoCrmKey": [] },
          { "firebaseAuth": [] }
        ],
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "name": "query", "in": "query", "schema": { "type": "string", "maxLength": 240 } },
          { "name": "status", "in": "query", "schema": { "type": "string", "enum": ["online", "offline", "available", "in_use", "booked", "not_bookable"] } },
          { "name": "from", "in": "query", "description": "ISO-8601 booking-window start. Provide with to.", "schema": { "type": "string", "format": "date-time" } },
          { "name": "to", "in": "query", "description": "ISO-8601 booking-window end, no more than 31 days after from.", "schema": { "type": "string", "format": "date-time" } },
          { "name": "include_bookings", "in": "query", "schema": { "type": "boolean", "default": false } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 } }
        ],
        "responses": {
          "200": { "description": "Visible Remote Machines and computed availability.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RemoteMachineListResponse" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/boards/{boardId}/remote-machines/{machineId}": {
      "get": {
        "summary": "Get a Remote Machine",
        "description": "Get one Remote Machine with live telemetry, active sessions, up to 60 recent CPU samples, protected network addresses, and bookings.",
        "security": [
          { "bearerAuth": [] },
          { "geoCrmKey": [] },
          { "firebaseAuth": [] }
        ],
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "name": "machineId", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "from", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "to", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "include_metrics", "in": "query", "schema": { "type": "boolean", "default": true } }
        ],
        "responses": {
          "200": { "description": "Remote Machine detail.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RemoteMachineResponse" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/boards/{boardId}/remote-machine-bookings": {
      "get": {
        "summary": "List Remote Machine bookings",
        "description": "List scheduler bookings visible through the selected Remote Machines board.",
        "security": [
          { "bearerAuth": [] },
          { "geoCrmKey": [] },
          { "firebaseAuth": [] }
        ],
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "name": "machine_id", "in": "query", "schema": { "type": "string" } },
          { "name": "status", "in": "query", "schema": { "type": "string", "enum": ["booked", "cancelled", "completed"] } },
          { "name": "from", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "to", "in": "query", "schema": { "type": "string", "format": "date-time" } },
          { "name": "mine", "in": "query", "schema": { "type": "boolean", "default": false } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 } }
        ],
        "responses": {
          "200": { "description": "Remote Machines bookings.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RemoteMachineBookingListResponse" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      },
      "post": {
        "summary": "Create a Remote Machine booking",
        "description": "Book an available Remote Machine. Conflicting windows return 409. Supply an idempotency key for retry-safe Slack and agent workflows.",
        "security": [
          { "bearerAuth": [] },
          { "geoCrmKey": [] },
          { "firebaseAuth": [] }
        ],
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" }
        ],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RemoteMachineBookingCreate" } } }
        },
        "responses": {
          "201": { "description": "Booking created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RemoteMachineBookingMutationResponse" } } } },
          "200": { "description": "Idempotent replay of an existing identical booking.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RemoteMachineBookingMutationResponse" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "description": "The machine is already booked, or an idempotency key was reused with different input." }
        }
      }
    },
    "/boards/{boardId}/remote-machine-bookings/{bookingId}": {
      "patch": {
        "summary": "Update a Remote Machine booking",
        "description": "Edit or reschedule a booking owned by the current person or integration. Administrators may update any booking.",
        "security": [
          { "bearerAuth": [] },
          { "geoCrmKey": [] },
          { "firebaseAuth": [] }
        ],
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "name": "bookingId", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RemoteMachineBookingUpdate" } } } },
        "responses": {
          "200": { "description": "Booking updated.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RemoteMachineBookingMutationResponse" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "description": "Booking revision is stale or the destination machine is already booked." }
        }
      },
      "delete": {
        "summary": "Cancel a Remote Machine booking",
        "description": "Set a booking to cancelled while preserving its audit record. The booking owner or a ONE administrator may cancel it.",
        "security": [
          { "bearerAuth": [] },
          { "geoCrmKey": [] },
          { "firebaseAuth": [] }
        ],
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "name": "bookingId", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": { "required": false, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RemoteMachineBookingCancel" } } } },
        "responses": {
          "200": { "description": "Booking cancelled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RemoteMachineBookingMutationResponse" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "description": "Booking revision is stale." }
        }
      }
    },
    "/cloud-costs/summary": {
      "get": {
        "summary": "Get protected cloud cost aggregates",
        "description": "Return cached or freshly aggregated Google Cloud Billing export and OpenRouter usage for one month. Cloud Costs viewer access is required. Set refresh=1 to force provider reads; that action requires Cloud Costs editor access.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "month",
            "in": "query",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-(0[1-9]|1[0-2])$"
            }
          },
          {
            "name": "refresh",
            "in": "query",
            "description": "Set to 1 to bypass the aggregate cache. Requires Cloud Costs editor access.",
            "schema": {
              "type": "string",
              "enum": ["1"]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Provider aggregates, freshness, health, drivers, and optimization recommendations.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["month", "generatedAt", "providerHealth", "recommendations"],
                  "properties": {
                    "month": { "type": "string" },
                    "generatedAt": { "type": "string", "format": "date-time" },
                    "mode": { "type": "string", "enum": ["live", "cached", "emulator_fixture"] },
                    "google": { "type": ["object", "null"] },
                    "openRouter": { "type": ["object", "null"] },
                    "providerHealth": { "type": "object" },
                    "recommendations": { "type": "array", "items": { "type": "object" } }
                  }
                }
              }
            }
          },
          "400": { "description": "Invalid month." },
          "401": { "description": "Firebase authentication is required." },
          "403": { "description": "Cloud Costs module access is missing, or editor access is required for refresh." },
          "503": { "description": "Provider aggregates are temporarily unavailable." }
        }
      }
    },
    "/machines/client/latest": {
      "get": {
        "summary": "Get latest OneClient release",
        "description": "Return the signed release manifest for the requested OneClient channel and platform.",
        "security": [],
        "parameters": [
          {
            "name": "platform",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["windows", "darwin", "linux"],
              "default": "windows"
            }
          },
          {
            "name": "arch",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "amd64"
            }
          },
          {
            "name": "channel",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "stable"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Signed OneClient release manifest.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "channel": {
                      "type": "string"
                    },
                    "platform": {
                      "type": "string"
                    },
                    "arch": {
                      "type": "string"
                    },
                    "release": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string"
                        },
                        "channel": {
                          "type": "string"
                        },
                        "platform": {
                          "type": "string"
                        },
                        "arch": {
                          "type": "string"
                        },
                        "releasedAt": {
                          "type": "string"
                        },
                        "bootstrap": {
                          "type": "object"
                        },
                        "agent": {
                          "type": "object"
                        },
                        "updater": {
                          "type": "object"
                        },
                        "signature": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/machines/client/releases/{version}/{platform}/{arch}/{fileName}": {
      "get": {
        "summary": "Download OneClient release artifact",
        "description": "Stream a signed-release artifact from Firebase Storage through the ONE API.",
        "security": [],
        "parameters": [
          {
            "name": "version",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "platform",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "arch",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fileName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "one-client-agent.exe",
                "one-client-updater.exe",
                "one-client-tray.exe",
                "bootstrap-windows-service.ps1",
                "one-client-agent",
                "one-client-updater",
                "bootstrap-macos-service.sh",
                "bootstrap-linux-service.sh"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Windows, macOS, or Linux executable/bootstrap artifact.",
            "content": {
              "application/vnd.microsoft.portable-executable": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/machines/{machineId}/color": {
      "patch": {
        "summary": "Set a shared remote machine color",
        "description": "Save the machine and calendar color as a global Remote Machines setting. Requires Firebase admin or owner access.",
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "parameters": [
          {
            "name": "machineId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "color"
                ],
                "properties": {
                  "color": {
                    "type": "string",
                    "pattern": "^#[0-9a-fA-F]{6}$",
                    "example": "#18b67c"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Shared machine color was updated."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/machines/{machineId}/role": {
      "patch": {
        "summary": "Set a remote machine role",
        "description": "Classify a Remote Machine and its server-resolved aliases as a bookable graphics machine or a non-bookable automation runner. Enabling role policy classifies existing legacy machines as graphics; future unclassified machines remain non-bookable. Requires Firebase admin or owner access.",
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "parameters": [
          {
            "name": "machineId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "role"
                ],
                "properties": {
                  "role": {
                    "type": "string",
                    "enum": ["graphics", "runner"]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Machine role was updated."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/machines/{machineId}": {
      "delete": {
        "summary": "Remove a remote machine",
        "description": "Archive a machine and its server-resolved aliases from the Remote Machines scheduler and clear live status, sessions, CPU metrics, events, and bookings. The installed client is not uninstalled. Requires the exact current machine name as confirmation and Firebase admin or owner access.",
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "parameters": [
          {
            "name": "machineId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "confirmMachineName"
                ],
                "properties": {
                  "confirmMachineName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 240,
                    "description": "Exact current machine name returned by the Remote Machines read API."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Machine was archived from the scheduler."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/administration/audit": {
      "get": {
        "summary": "Get the ONE administration audit",
        "description": "Return a read-only audit of access users, permission groups, materialized board and project grants, invitations, bootstrap administrators, API-key metadata, and configuration findings. API-key hashes, reusable secrets, bridge settings, connector tokens, and credentials are omitted. Requires a signed-in Firebase owner or administrator; ONE API keys are rejected.",
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Current redacted administration audit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdministrationAudit"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/me": {
      "get": {
        "summary": "Show API key metadata",
        "responses": {
          "200": {
            "description": "Authenticated API key metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "apiKey": {
                      "$ref": "#/components/schemas/ApiKey"
                    }
                  },
                  "required": [
                    "apiKey"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/team/requests": {
      "get": {
        "summary": "Get Personal Workspace",
        "description": "Return the signed-in person's People profile, company links and calendar, ONE-calculated time-off balances and audited ledger, assigned hardware, personal requests, and pending approvals for direct reports. Calendar absences accept canonical and imported request fields and include approved, accepted, completed, scheduled, recorded, or taken time off while excluding pending, rejected, and accrual rows. Owners and admins also receive time-off administration state. The response is identity-bound and API keys are rejected.",
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "The current person's Personal Workspace view.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonalWorkspace"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "description": "The People request service is unavailable."
          }
        }
      }
    },
    "/team/requests/profile": {
      "patch": {
        "summary": "Update Personal Workspace profile",
        "description": "Patch editable People profile fields for the signed-in person. Omitted fields are preserved, the target identity comes from Firebase authentication, and API keys are rejected.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "profile": { "$ref": "#/components/schemas/PersonalProfileUpdate" } }, "required": ["profile"], "additionalProperties": false } } } },
        "responses": {
          "200": { "description": "Updated Personal Workspace view.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PersonalWorkspace" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/team/requests/time-off": {
      "post": {
        "summary": "Create a personal time-off request",
        "description": "Submit paid, sick, or unpaid time off for the signed-in person to their team lead. The range must contain at least one working day.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PersonalTimeOffRequestInput" } } } },
        "responses": {
          "201": { "description": "Updated Personal Workspace view.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PersonalWorkspace" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/team/requests/time-off/{requestId}": {
      "patch": {
        "summary": "Update a personal time-off request",
        "description": "Update one pending time-off request owned by the signed-in person. Approved or denied history cannot be changed.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "name": "requestId", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PersonalTimeOffRequestInput" } } } },
        "responses": {
          "200": { "description": "Updated Personal Workspace view.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PersonalWorkspace" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" }
        }
      },
      "delete": {
        "summary": "Cancel a personal time-off request",
        "description": "Cancel one pending time-off request owned by the signed-in person. Approved or denied history is preserved.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "name": "requestId", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": { "description": "Updated Personal Workspace view.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PersonalWorkspace" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" }
        }
      }
    },
    "/team/requests/hardware": {
      "post": {
        "summary": "Create a personal hardware request",
        "description": "Submit a hardware procurement request for the signed-in person through ONE's configured approval chain. The assigned approvers are notified.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PersonalHardwareRequestInput" } } } },
        "responses": {
          "201": { "description": "Updated Personal Workspace view.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PersonalWorkspace" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "409": { "$ref": "#/components/responses/Conflict" }
        }
      }
    },
    "/team/requests/approvals/time-off/{personId}/{requestId}": {
      "post": {
        "summary": "Decide a direct-report time-off request",
        "description": "Approve or deny one pending request as the direct report's current team lead. Approval also appends audited balance usage.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [
          { "name": "personId", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "requestId", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DirectReportTimeOffDecision" } } } },
        "responses": {
          "200": { "description": "Updated Personal Workspace view.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PersonalWorkspace" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" }
        }
      }
    },
    "/team/time-off/admin": {
      "get": {
        "summary": "Get time-off administration",
        "description": "List ONE-managed PTO and sick-time settings, employee policy assignments, balances, and the last automatic accrual run. Requires a Firebase user who is a ONE owner or admin.",
        "security": [{ "firebaseAuth": [] }],
        "responses": {
          "200": { "description": "Current time-off administration state.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TimeOffAdministration" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/team/time-off/people/{personId}/history": {
      "get": {
        "summary": "Get a person's complete time-off history",
        "description": "Return the complete chronological ONE time-off ledger for one employee, including accruals, requests, carryover losses, adjustments, balances, and policy events. Requires a Firebase user who is a ONE owner or admin.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "name": "personId", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": { "description": "The employee's complete time-off history.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TimeOffPersonHistory" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/team/time-off/policies/{policyId}": {
      "patch": {
        "summary": "Update a time-off policy",
        "description": "Update future PTO or sick-time rules while preserving existing ledger history. Requires a ONE owner or admin.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "name": "policyId", "in": "path", "required": true, "schema": { "type": "string", "enum": ["paid", "sick"] } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TimeOffPolicyUpdate" } } } },
        "responses": {
          "200": { "description": "Updated time-off administration state.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TimeOffAdministration" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/team/time-off/people/{personId}/policies/{policyId}": {
      "put": {
        "summary": "Set a person's time-off policy",
        "description": "Assign, change the accrual start date, or remove PTO or sick-time eligibility and append a reasoned audit event. Existing history remains intact.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [
          { "name": "personId", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "policyId", "in": "path", "required": true, "schema": { "type": "string", "enum": ["paid", "sick"] } }
        ],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TimeOffPolicyAssignment" } } } },
        "responses": {
          "200": { "description": "Updated time-off administration state.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TimeOffAdministration" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/team/time-off/people/{personId}/balance-adjustments": {
      "post": {
        "summary": "Adjust a person's time-off balance",
        "description": "Set a PTO or sick-time balance on an effective date and append the amount, administrator, and required reason to the audit ledger.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "name": "personId", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TimeOffBalanceAdjustment" } } } },
        "responses": {
          "201": { "description": "Updated time-off administration state.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TimeOffAdministration" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/team/time-off/accruals/run": {
      "post": {
        "summary": "Run time-off accruals",
        "description": "Run the idempotent PTO and sick-time processor through a date. Imported BambooHR Vacation/Holiday and Sick Leave balances continue under their matching ONE policy, while unpaid leave never accrues. A scheduled Firebase function normally runs it daily; this endpoint supports owner/admin review and recovery.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "throughDate": { "type": "string", "format": "date" } }, "additionalProperties": false } } } },
        "responses": {
          "200": { "description": "Accrual run summary.", "content": { "application/json": { "schema": { "type": "object", "properties": { "ok": { "type": "boolean" }, "throughDate": { "type": "string", "format": "date" }, "peopleChanged": { "type": "integer" }, "eventsCreated": { "type": "integer" }, "ranAt": { "type": "string", "format": "date-time" } }, "required": ["ok", "throughDate", "peopleChanged", "eventsCreated", "ranAt"], "additionalProperties": false } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/logs": {
      "get": {
        "summary": "List recent diagnostic logs",
        "description": "Read the last seven days of ONE logs, filtered by time range, level, category, connector, source, or text query.",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Optional ISO timestamp or epoch milliseconds. Values older than seven days are clamped."
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Optional ISO timestamp or epoch milliseconds. Defaults to now."
          },
          {
            "name": "level",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated levels: debug, info, warn, error."
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated categories: app, llm, connector, system."
          },
          {
            "name": "connector",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated connector filters, such as slack, gmail, openrouter, codex, api, or web."
          },
          {
            "name": "source",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated source filters, such as web, bridge, mcp, or geoCrmApi."
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Case-insensitive text search across messages and details."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Recent diagnostic logs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LogListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "summary": "Write a diagnostic log",
        "description": "Write a short-lived app, LLM, connector, or system diagnostic log entry. Requires write scope.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WriteLogRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Stored diagnostic log.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteLogResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/branding": {
      "get": {
        "summary": "Get GeoTech brand standards",
        "description": "Return the authoritative approved logos, exact colour values, typography, patterns, hosted assets, the Cover, Getting Started, Foundations, and Tokens pages, and all 89 design variables for decks, reports, websites, product design, and other visual work.",
        "security": [],
        "responses": {
          "200": {
            "description": "Current GeoTech brand standards.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BrandStandardsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/decks": {
      "get": {
        "summary": "List ONE client decks",
        "description": "List draft and published decks with kind, access mode, revision, and URL. Imported owner-only reports are visible only to their owner. Firebase ID tokens, OAuth, and API keys are accepted. Requires decks:read (or general read) on a service key, or a signed-in ONE identity with Decks view access. Owners and administrators retain access; member grants can be direct or from permission groups.",
        "responses": { "200": { "description": "Deck publication directory." }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" } }
      }
    },
    "/decks/migrate-reports": {
      "post": {
        "summary": "Migrate the owner's legacy reports to Decks",
        "description": "Requires a signed-in owner via Firebase, OAuth, or a personal API key. Idempotently preserves HTML, revision history, and owner-only access; retains original boards for recovery.",
        "responses": { "200": { "description": "Imported deck summaries." }, "403": { "$ref": "#/components/responses/Forbidden" }, "409": { "$ref": "#/components/responses/Conflict" } }
      }
    },
    "/decks/{slug}/preview": {
      "get": {
        "summary": "Read a private first-page preview",
        "description": "Requires Decks view access and the same per-deck owner boundary as get_deck. Returns the first published image/PDF page, or the preserved HTML report. Responses are private and never cached.",
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Image, one-page PDF, or sanitized report HTML." }, "401": { "$ref": "#/components/responses/Unauthorized" }, "404": { "$ref": "#/components/responses/NotFound" } }
      }
    },
    "/decks/{slug}": {
      "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string", "pattern": "^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$" } }],
      "get": {
        "summary": "Get a ONE deck draft",
        "description": "Requires decks:read (or general read) on a service key, or a signed-in ONE identity with Decks view access. Owners and administrators retain access; member grants can be direct or from permission groups.",
        "responses": { "200": { "description": "Current mutable draft and immutable publication metadata." }, "404": { "$ref": "#/components/responses/NotFound" } }
      },
      "delete": {
        "summary": "Delete a ONE deck with title confirmation",
        "description": "Removes the deck from the library and disables public content, assets, PDF, and access setup. Content and revision history remain private for recovery; deleted slugs stay reserved and reports are not reimported. Requires Decks edit access for a signed-in identity, or both decks:write and decks:publish (or general write) for a service key, plus the existing per-deck owner boundary. Safe to retry a confirmed deletion.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": {
          "type": "object",
          "required": ["confirmName", "expectedRevision", "expectedUpdatedAt"],
          "properties": {
            "confirmName": { "type": "string", "description": "Exact current deck title confirmed by the user." },
            "expectedRevision": { "type": "integer", "minimum": 1, "description": "Current draftRevision from GET /decks/{slug}." },
            "expectedUpdatedAt": { "type": "string", "description": "Current updatedAt from GET /decks/{slug}." }
          }
        } } } },
        "responses": { "200": { "description": "Deck deleted, or previously deleted by a confirmed request." }, "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "description": "Deck management permission required." }, "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" } }
      },
      "put": {
        "summary": "Create or update a ONE deck draft",
        "description": "Save a structured deck without rebuilding Firebase Hosting. Pass expectedRevision on updates for optimistic concurrency. Requires Decks edit access for a signed-in identity, or decks:write (or general write) for a service key.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeckDraftInput" } } } },
        "responses": { "200": { "description": "Draft saved." }, "400": { "$ref": "#/components/responses/BadRequest" }, "409": { "$ref": "#/components/responses/Conflict" } }
      }
    },
    "/decks/{slug}/access": {
      "put": {
        "summary": "Set or remove a deck passcode",
        "description": "Requires Decks edit access for a signed-in identity, or decks:access-admin (or general write) for a service key. Plaintext passcodes and hashes are never returned.",
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["passcode"], "properties": { "passcode": { "oneOf": [{ "type": "string", "minLength": 6, "maxLength": 128 }, { "type": "null" }] } }, "additionalProperties": false } } } },
        "responses": { "200": { "description": "Access policy updated without returning the passcode or hash." } }
      }
    },
    "/decks/{slug}/access-setup": {
      "post": {
        "summary": "Create a private deck passcode setup link",
        "description": "Requires Decks edit access for a signed-in identity, or decks:access-admin (or general write) for a service key. Returns a one-time 15-minute browser URL so the passcode never enters an MCP or AI conversation.",
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "One-time passcode setup URL and expiry." }, "404": { "$ref": "#/components/responses/NotFound" } }
      }
    },
    "/decks/{slug}/assets": {
      "post": {
        "summary": "Upload a private deck asset",
        "description": "Requires Decks edit access for a signed-in identity, or decks:write (or general write) for a service key. Storage object names and Firebase download tokens are never returned.",
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeckAssetInput" } } } },
        "responses": { "201": { "description": "Asset stored privately and bound to the deck." }, "413": { "description": "Asset exceeds the 10 MiB API limit." } }
      }
    },
    "/decks/{slug}/publish": {
      "post": {
        "summary": "Publish an immutable deck revision and PDF",
        "description": "Requires Decks edit access for a signed-in identity, or decks:publish (or general write) for a service key. Snapshots the current ONE brand contract, stores the exact spec, generates the synchronized branded PDF, and atomically points the public route at the immutable revision.",
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["expectedRevision"], "properties": { "expectedRevision": { "type": "integer", "minimum": 1 } }, "additionalProperties": false } } } },
        "responses": { "200": { "description": "Immutable revision published." }, "409": { "$ref": "#/components/responses/Conflict" } }
      }
    },
    "/decks/{slug}/unpublish": {
      "post": {
        "summary": "Unpublish a deck",
        "description": "Requires Decks edit access for a signed-in identity, or decks:publish (or general write) for a service key. Removes public access while retaining the draft, private assets, and immutable revision history.",
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["expectedRevisionId"], "properties": { "expectedRevisionId": { "type": "string", "minLength": 1, "maxLength": 100 } }, "additionalProperties": false } } } },
        "responses": { "200": { "description": "Deck unpublished." }, "409": { "$ref": "#/components/responses/Conflict" } }
      }
    },
    "/decks/public/{slug}": {
      "get": {
        "summary": "Read a published web deck",
        "security": [],
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Published immutable deck spec." }, "401": { "description": "The deck requires a passcode session." }, "404": { "$ref": "#/components/responses/NotFound" } }
      }
    },
    "/decks/public/{slug}/access": {
      "post": {
        "summary": "Unlock a passcode-protected deck",
        "security": [],
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["passcode"], "properties": { "passcode": { "type": "string", "minLength": 6, "maxLength": 128 } }, "additionalProperties": false } } } },
        "responses": { "200": { "description": "Sets the Firebase Hosting-compatible __session cookie for eight hours with Secure, HttpOnly, and SameSite=Lax." }, "401": { "description": "Passcode is incorrect." } }
      }
    },
    "/decks/public/{slug}/access/setup": {
      "post": {
        "summary": "Complete one-time deck passcode setup",
        "description": "Consumes the short-lived setup fragment and saves the passcode verifier without returning the passcode or hash.",
        "security": [],
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["token", "passcode"], "properties": { "token": { "type": "string", "minLength": 32, "maxLength": 256 }, "passcode": { "type": "string", "minLength": 6, "maxLength": 128 } }, "additionalProperties": false } } } },
        "responses": { "200": { "description": "Passcode protection enabled." }, "401": { "description": "Setup link is invalid, expired, or already consumed." } }
      }
    },
    "/decks/public/{slug}/pdf": {
      "get": {
        "summary": "Download the synchronized deck PDF",
        "security": [],
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Branded 16:9 PDF generated from the published web deck source.", "content": { "application/pdf": {} } }, "401": { "description": "The deck requires a passcode session." } }
      }
    },
    "/decks/public/{slug}/assets/{assetId}": {
      "get": {
        "summary": "Read one published deck asset",
        "security": [],
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "assetId", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Private asset bytes after the deck access check." }, "401": { "description": "The deck requires a passcode session." }, "404": { "$ref": "#/components/responses/NotFound" } }
      }
    },
    "/boards": {
      "get": {
        "summary": "List boards",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Optional board-name filter."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Board summaries.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "boards": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/BoardSummary"
                      }
                    },
                    "structure": {
                      "$ref": "#/components/schemas/BoardStructureContext",
                      "description": "Present only for a ONE owner or administrator who may manage board structure."
                    }
                  },
                  "required": [
                    "boards"
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a standard ONE board",
        "description": "Requires a ONE owner or administrator using OAuth or a personal API key. Creates a public board with the standard columns, one Main table group, and no generated Dashboard view. The current board-directory revision is required.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateBoardRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Board created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateBoardResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/boards/reorder": {
      "post": {
        "summary": "Preview or apply the complete board order",
        "description": "Requires a ONE owner or administrator using OAuth or a personal API key. Submit every reorderable board ID exactly once. Requests preview by default; set dryRun to false only after reviewing the returned changes.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReorderBoardsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Board-order preview or applied result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReorderBoardsResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/boards/{boardId}": {
      "get": {
        "summary": "Get board metadata",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          }
        ],
        "responses": {
          "200": {
            "description": "One board summary.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "board": {
                      "$ref": "#/components/schemas/BoardSummary"
                    }
                  },
                  "required": [
                    "board"
                  ]
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "summary": "Rename a non-protected ONE board",
        "description": "Requires a ONE owner or administrator using OAuth or a personal API key and the exact board revision returned by GET /boards/{boardId}. Core or specialized workspaces cannot be renamed through this route.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenameBoardRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Board renamed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RenameBoardResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      },
      "delete": {
        "summary": "Remove a board from the active workspace",
        "description": "Requires a ONE owner or administrator using OAuth or a personal API key. The exact current board name and revision must be supplied as confirmation. Protected core boards cannot be removed. Removed boards are archived under an internal deleted-boards path for recovery.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteBoardRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Board removed from active workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteBoardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/boards/{boardId}/columns": {
      "post": {
        "summary": "Create or return a board column",
        "description": "Requires a ONE owner or administrator using OAuth or a personal API key and the exact current board revision. If a matching column title or ID already exists, the existing column is returned.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnsureColumnRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Existing column returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnsureColumnResponse"
                }
              }
            }
          },
          "201": {
            "description": "Column created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnsureColumnResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/boards/{boardId}/columns/{columnId}": {
      "patch": {
        "summary": "Rename a board column",
        "description": "Requires a ONE owner or administrator using OAuth or a personal API key and the exact current board revision. Protected columns cannot be renamed. Embedded item-cell column labels are synchronized.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ColumnId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenameColumnRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Column renamed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RenameColumnResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      },
      "delete": {
        "summary": "Archive a board column",
        "description": "Requires a ONE owner or administrator using OAuth or a personal API key, the exact current board revision, and the exact current column title. Archives a non-name, non-subitems column so it no longer appears in the active board table. Existing item cell data is preserved for recovery.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ColumnId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ArchiveColumnRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Column archived.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ArchiveColumnResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/boards/{boardId}/items": {
      "get": {
        "summary": "List board items",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Optional text search across item names and visible fields."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Board metadata and matching item summaries.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "board": {
                      "$ref": "#/components/schemas/BoardSummary"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ItemSummary"
                      }
                    }
                  },
                  "required": [
                    "board",
                    "items"
                  ]
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a board item",
        "description": "Requires an API key with the write scope. Creates a new item on one board using existing column IDs or titles for field values.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateItemRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created item detail.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "item": {
                      "$ref": "#/components/schemas/ItemDetail"
                    }
                  },
                  "required": [
                    "item"
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/boards/{boardId}/items/move": {
      "post": {
        "summary": "Move filtered board items",
        "description": "Requires an API key with the write scope. Moves matching items on one board to another group, such as moving Production rows with Status=Done to Archived. Use dryRun to preview matched items without writing.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MoveItemsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Move result or dry-run preview.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MoveItemsResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/boards/{boardId}/items/duplicates": {
      "get": {
        "summary": "Find duplicate board records",
        "description": "Find duplicate candidate groups on one board by exact or similar normalized item names.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "name_threshold",
            "in": "query",
            "schema": {
              "type": "number",
              "minimum": 0.5,
              "maximum": 1,
              "default": 0.86
            },
            "description": "Similarity threshold for fuzzy name matches."
          }
        ],
        "responses": {
          "200": {
            "description": "Duplicate board record candidate groups.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DuplicateCandidateResponse"
                }
              }
            }
          }
        }
      }
    },
    "/boards/{boardId}/items/duplicates/merge": {
      "post": {
        "summary": "Merge duplicate board records",
        "description": "Requires an API key with the write scope. Merges duplicate items on one board into a primary item, preserving candidate field values.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BoardItemDuplicateMergeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Merge result or dry-run preview.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BoardItemDuplicateMergeResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/boards/{boardId}/items/{itemId}": {
      "get": {
        "summary": "Get one item",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ItemId"
          }
        ],
        "responses": {
          "200": {
            "description": "One item with updates, assets, and subitems.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "item": {
                      "$ref": "#/components/schemas/ItemDetail"
                    }
                  },
                  "required": [
                    "item"
                  ]
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "summary": "Update item name or fields",
        "description": "Requires an API key with the write scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ItemId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateItemRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated item summary.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "item": {
                      "$ref": "#/components/schemas/ItemSummary"
                    }
                  },
                  "required": [
                    "item"
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "delete": {
        "summary": "Soft-delete an item",
        "description": "Requires an API key with the write scope. Marks the item state as deleted and writes an audit update.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ItemId"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteItemRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Soft-delete result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean"
                    },
                    "item": {
                      "$ref": "#/components/schemas/ItemDetail"
                    },
                    "update": {
                      "$ref": "#/components/schemas/Update"
                    }
                  },
                  "required": [
                    "deleted",
                    "item",
                    "update"
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/boards/{boardId}/items/{itemId}/duplicate": {
      "post": {
        "summary": "Duplicate one board item",
        "description": "Requires current board edit access and the exact source-item revision. The duplicate gets a new identity and audit metadata, clears updates and protected owner assignment, and omits ONE-managed private files so it never reuses the source item's protected object references.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ItemId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DuplicateItemRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Item duplicated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DuplicateItemResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/boards/{boardId}/items/{itemId}/files": {
      "get": {
        "summary": "List private files stored for an item",
        "description": "Requires current read access to the board. Storage object paths and public tokens are never returned.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ItemId"
          },
          {
            "name": "columnId",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Optional file column ID filter."
          }
        ],
        "responses": {
          "200": {
            "description": "Safe private item-file metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "files": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ItemFileRecord"
                      }
                    }
                  },
                  "required": [
                    "ok",
                    "files"
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "summary": "Upload a private item file",
        "description": "Send a validated PDF, JPEG, PNG, WebP, Office, CSV, JSON, text, or ZIP file up to 20 MB as the raw body. X-File-Name and X-Column-Id select the file and destination. Legacy non-Drive link requests remain supported for compatibility, but Google Drive URLs are rejected.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ItemId"
          },
          {
            "name": "X-File-Name",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Required for a raw file upload."
          },
          {
            "name": "X-Column-Id",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Existing file column ID, or a stable ID when X-Column-Title creates one."
          },
          {
            "name": "X-Column-Title",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Optional title used when the file column does not exist."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetFileFieldRequest"
              }
            },
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "application/pdf": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/jpeg": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/png": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Private item file appended, or legacy external-link field updated.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean"
                        },
                        "file": {
                          "$ref": "#/components/schemas/ItemFileRecord"
                        },
                        "column": {
                          "$ref": "#/components/schemas/Column"
                        }
                      },
                      "required": [
                        "ok",
                        "file",
                        "column"
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/SetFileFieldResponse"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/boards/{boardId}/items/{itemId}/files/import-drive": {
      "post": {
        "summary": "Copy a Google Drive file into private ONE storage",
        "description": "Requires a Firebase-authenticated ONE user with board editor access and a connected Google account whose email matches the ONE session. Native Docs, Sheets, Slides, and Drawings are exported to stable business formats before storage. API keys are rejected.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ItemId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "driveUrl": {
                    "type": "string",
                    "description": "Google Drive/Docs URL or Drive file ID."
                  },
                  "resourceKey": {
                    "type": "string"
                  },
                  "columnId": {
                    "type": "string"
                  },
                  "columnTitle": {
                    "type": "string"
                  }
                },
                "required": [
                  "driveUrl",
                  "columnId"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Drive file copied and appended to the item column.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "file": {
                      "$ref": "#/components/schemas/ItemFileRecord"
                    }
                  },
                  "required": [
                    "ok",
                    "file"
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/boards/{boardId}/items/{itemId}/files/{fileId}": {
      "get": {
        "summary": "Stream a private item file",
        "description": "Rechecks current board read access and the stored SHA-256 checksum before returning private bytes.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ItemId"
          },
          {
            "name": "fileId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Checksum-verified private file bytes.",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "File not found."
          }
        }
      },
      "delete": {
        "summary": "Delete a private item file",
        "description": "Requires current board write access. Removes the managed file entry, private metadata, and Firebase / Google Cloud object.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ItemId"
          },
          {
            "name": "fileId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Private item file permanently deleted."
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "File not found."
          }
        }
      }
    },
    "/item-files/drive/accounts": {
      "get": {
        "summary": "Get Google Drive readiness for item-file import",
        "description": "Returns the session-bound Google account capability and public Google Identity Services client configuration. The Google email must match the signed-in ONE Firebase session; API keys are rejected.",
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Drive connection and authorization capability summary."
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/item-files/drive/authorization": {
      "post": {
        "summary": "Authorize Google Drive for item-file import",
        "description": "Exchanges a one-time Google Identity Services popup code, verifies the Google profile email equals the Firebase session email, and stores a private per-user refresh token. Tokens are never returned. Requires X-Requested-With: XmlHttpRequest and a matching HTTPS or local-development origin; API keys are rejected.",
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Requested-With",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "const": "XmlHttpRequest"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "One-time code returned by Google Identity Services."
                  },
                  "redirectUri": {
                    "type": "string",
                    "format": "uri",
                    "description": "Current ONE browser origin used by the popup code flow."
                  }
                },
                "required": [
                  "code",
                  "redirectUri"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Session-bound Drive authorization and capability summary."
          },
          "400": {
            "description": "Invalid code, in-app header, or origin."
          },
          "403": {
            "description": "The Google email differs from the ONE session or the caller is not a Firebase user."
          },
          "409": {
            "description": "Required Drive scopes or offline refresh access were not granted."
          }
        }
      }
    },
    "/boards/{boardId}/items/{itemId}/updates": {
      "post": {
        "summary": "Add an item update note",
        "description": "Requires an API key with the write scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ItemId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created update note.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "update": {
                      "$ref": "#/components/schemas/Update"
                    }
                  },
                  "required": [
                    "update"
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/boards/{boardId}/items/{itemId}/updates/{updateId}": {
      "patch": {
        "summary": "Edit a general item update",
        "description": "Requires current board edit access, the exact update revision, and either update authorship or ONE owner/administrator access.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ItemId"
          },
          {
            "$ref": "#/components/parameters/UpdateId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EditItemUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Update edited.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EditItemUpdateResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      },
      "delete": {
        "summary": "Delete a general item update",
        "description": "Requires current board edit access, the exact update revision and current text, and either update authorship or ONE owner/administrator access.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ItemId"
          },
          {
            "$ref": "#/components/parameters/UpdateId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteItemUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Update deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteItemUpdateResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/contacts": {
      "post": {
        "summary": "Create or update a contact and link a company",
        "description": "Requires an API key with the write scope. Finds an existing Contacts record by email/name or creates one, then links it to an existing or newly created Companies record when company details are provided.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpsertContactRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Existing contact returned after verification or update.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpsertContactResponse"
                }
              }
            }
          },
          "201": {
            "description": "Contact created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpsertContactResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/contacts/duplicates": {
      "get": {
        "summary": "Find duplicate contact candidates",
        "description": "Find duplicate candidate groups on the Contacts board by shared email, shared phone, exact name, or similar name.",
        "parameters": [
          {
            "name": "board_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Optional Contacts board ID. Defaults to the board named Contacts."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "name_threshold",
            "in": "query",
            "schema": {
              "type": "number",
              "minimum": 0.5,
              "maximum": 1,
              "default": 0.86
            },
            "description": "Similarity threshold for fuzzy name matches."
          }
        ],
        "responses": {
          "200": {
            "description": "Duplicate contact candidate groups.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "board": {
                      "$ref": "#/components/schemas/BoardSummary"
                    },
                    "candidateGroups": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ContactDuplicateGroup"
                      }
                    },
                    "totalCandidateGroups": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "board",
                    "candidateGroups",
                    "totalCandidateGroups"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/contacts/duplicates/merge": {
      "post": {
        "summary": "Merge duplicate contacts",
        "description": "Requires an API key with the write scope. Merges duplicate Contacts items into a primary item, preserving secondary emails and candidate field values.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactDuplicateMergeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Merge result or dry-run preview.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactDuplicateMergeResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/task-automation/assign": {
      "post": {
        "summary": "Assign or unassign local Codex",
        "description": "Firebase-authenticated browser endpoint. Assigning Codex or explicitly mentioning @Codex assigns the task to the Codex agent for manual MCP pickup; unassigning removes the Codex assignee without removing human assignees. No worker job is created.",
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskAutomationAssignmentRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The task was already assigned to Codex (idempotent repeat)."
          },
          "201": {
            "description": "Codex assignment was applied or cancelled."
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/task-projects/boards": {
      "get": {
        "summary": "List project-task boards",
        "description": "Requires tasks:read, read, or write scope. Returns only least-privilege board summaries allowed for project-task automation; task-only keys cannot use generic board-read routes.",
        "parameters": [
          { "name": "query", "in": "query", "schema": { "type": "string" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100 } }
        ],
        "responses": {
          "200": { "description": "Allowed project-task board summaries." },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/task-projects/boards/{boardId}/projects": {
      "get": {
        "summary": "List task project summaries",
        "description": "Requires tasks:read, read, or write scope. Returns only safe project identity and lifecycle fields; updates, assets, fields, and nested tasks are omitted.",
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "name": "query", "in": "query", "schema": { "type": "string" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100 } }
        ],
        "responses": {
          "200": { "description": "Safe project summaries." },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/task-projects/boards/{boardId}/projects/{projectId}": {
      "get": {
        "summary": "Get a task project summary",
        "description": "Requires tasks:read, read, or write scope. Returns one safe project summary without generic item updates, assets, fields, or nested tasks.",
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "$ref": "#/components/parameters/ProjectId" }
        ],
        "responses": {
          "200": { "description": "Safe project summary." },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/boards/{boardId}/projects/{projectId}/tasks": {
      "get": {
        "summary": "List project tasks or get revision-bound tracking context",
        "description": "Ordinary tasks:read, read, and write requests retain the legacy task-list response. Set tracking_context=true with tasks:read (or a legacy compatible read/write scope) to explicitly request stable-ID task pages plus project lifecycle, configured statuses, sprints, milestones, up to 12 exact active People matches, safe import fingerprints/tombstones, and project_revision. The safe import ledger is deterministically capped at 500 returned records; tracker callers must inspect import_records_total and import_records_truncated before reconciling. The opaque cursor is bound to board, project, filters, and revision; a concurrent project change returns 409 so the caller restarts at page one.",
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "$ref": "#/components/parameters/ProjectId" },
          { "name": "tracking_context", "in": "query", "description": "Explicitly opt into the revision-bound project tracker response. Requires tasks:read or a legacy compatible read/write scope.", "schema": { "type": "boolean", "default": false } },
          { "name": "query", "in": "query", "schema": { "type": "string" } },
          { "name": "slackUrl", "in": "query", "description": "Exact Slack thread lookup resolved through canonical Slack entries in task work_links. Equivalent root and reply permalinks match.", "schema": { "type": "string", "format": "uri" } },
          {
            "name": "people",
            "in": "query",
            "description": "Repeat for up to 12 exact active People names or IDs. Partial matches are never returned.",
            "schema": { "type": "array", "maxItems": 12, "items": { "type": "string", "maxLength": 160 } },
            "explode": true
          },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 } },
          { "name": "cursor", "in": "query", "description": "Opaque next_cursor from the preceding page.", "schema": { "type": "string", "maxLength": 2000 } }
        ],
        "responses": {
          "200": {
            "description": "Revision-bound tracking context only when tracking_context=true with tasks:read or a legacy compatible read/write scope; otherwise the legacy task list. Task and subtask records expose canonical workLinks and no slackSources response alias.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/ProjectTrackingContext" },
                    { "$ref": "#/components/schemas/LegacyProjectTaskListResponse" }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" }
        }
      },
      "post": {
        "summary": "Create project tasks or import typed tracker tasks",
        "description": "The local tasks-profile contract uses a project-scoped service key with exact tasks:create and a configured, non-empty allowedProjects list matching the target, and creates 1-12 typed, revision-bound records with deterministic import keys, canonical People references, explicit blank scheduling fields, initial status rationale, and structured work links. A new entry requires the latest project_revision; an exact replay returns action existing even with a stale revision. Non-Backlog status additionally requires tasks:import_status. Tracker imports never enqueue enrichment. Legacy personal/full-profile creation remains Backlog-only and uses tasks:write, tasks:create, or write according to the credential type. Human reviewers alone may complete normal developer tasks; the import-status exception is limited to the service import contract.",
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "$ref": "#/components/parameters/ProjectId" }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  { "$ref": "#/components/schemas/TrackerTaskCreateRequest" },
                  { "$ref": "#/components/schemas/LegacyProjectTaskCreateRequest" }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created or replayed tasks. Tracker responses include per-entry created/existing dispositions and the resulting project_revision; conflicts are whole-request 409 responses.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/TrackerTaskCreateResponse" },
                    { "$ref": "#/components/schemas/LegacyProjectTaskCreateResponse" }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" }
        }
      },
      "patch": {
        "summary": "Update project tracker tasks transactionally",
        "description": "Exact-project tracker service capability. Requires tasks:create and a configured, non-empty allowedProjects list matching the target. Replaces the complete tracker-managed field set for 1-12 existing tasks while preserving comments, attachments, hidden work-link metadata, and unrelated server-managed fields. Supply subtask_id when renaming an existing subtask; ambiguous remove-and-add replacements return a whole-request 409 without reassigning identity. Each task requires a new immutable update_import_key and the latest project_revision. An exact replay returns action existing even with a stale revision; a changed replay or stale new write returns a whole-request 409. This narrow transition does not require tasks:import_status and does not grant generic task writes.",
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "$ref": "#/components/parameters/ProjectId" }
        ],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TrackerTaskUpdateRequest" } } }
        },
        "responses": {
          "200": {
            "description": "Updated or exactly replayed tasks and the resulting project_revision.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TrackerTaskUpdateResponse" } } }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" }
        }
      }
    },
    "/boards/{boardId}/projects/{projectId}/milestones:upsert": {
      "post": {
        "summary": "Upsert project tracker milestones transactionally",
        "description": "Local tasks-profile capability only. Requires a service API key with tasks:milestones:write and at least one exact allowedProjects entry matching this project. Adds 1-100 actual ISO calendar dates with deterministic retry-safe import keys, preserves unrelated milestones, and atomically mirrors projectBoard.milestones and task_global_milestones with private audit metadata. Exact replays return 200 even with a stale revision; a new or semantically ambiguous write returns whole-request 409 without mutation. This route is not exposed as a remote OAuth MCP tool.",
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "$ref": "#/components/parameters/ProjectId" }
        ],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TrackerMilestoneUpsertRequest" } } }
        },
        "responses": {
          "200": {
            "description": "Every entry resolved to an existing milestone.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TrackerMilestoneUpsertResponse" } } }
          },
          "201": {
            "description": "At least one milestone was created.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TrackerMilestoneUpsertResponse" } } }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" }
        }
      }
    },
    "/boards/{boardId}/projects/{projectId}/calendar": {
      "get": {
        "summary": "List project calendar items",
        "description": "Returns milestones and durable calendar events whose inclusive ranges overlap date_from/date_to. Exact-project service keys require tasks:read; signed-in users require current project read access.",
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/CalendarProjectId" },
          { "name": "item_type", "in": "query", "schema": { "type": "string", "enum": ["milestone", "calendar_event"] } },
          { "name": "date_from", "in": "query", "schema": { "type": "string", "format": "date" } },
          { "name": "date_to", "in": "query", "schema": { "type": "string", "format": "date" } }
        ],
        "responses": { "200": { "description": "Authoritative calendar items and project revision.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProjectCalendarListResponse" } } } }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" } }
      },
      "post": {
        "summary": "Create a project calendar item",
        "description": "Creates a milestone or calendar event through the canonical revision-bound project transition. Service keys require tasks:calendar:write and an exact nonempty allowedProjects list. source_key is resolved against the current privacy-safe projection and copied as an independent snapshot.",
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/CalendarProjectId" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProjectCalendarCreate" } } } },
        "responses": { "201": { "description": "Created item, generated ID, changed counts, authoritative project and revision.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProjectCalendarMutationResponse" } } } }, "400": { "$ref": "#/components/responses/BadRequest" }, "403": { "$ref": "#/components/responses/Forbidden" }, "409": { "$ref": "#/components/responses/Conflict" } }
      }
    },
    "/boards/{boardId}/projects/{projectId}/calendar/sources": {
      "get": {
        "summary": "List privacy-safe project calendar sources",
        "description": "Returns roster-scoped approved People time-off and company-event sources for read-only calendar display. Requires project read access or tasks:read plus an exact project allowlist.",
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/CalendarProjectId" }, { "name": "date_from", "in": "query", "schema": { "type": "string", "format": "date" } }, { "name": "date_to", "in": "query", "schema": { "type": "string", "format": "date" } }],
        "responses": { "200": { "description": "Safe source projection and current project revision.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProjectCalendarSourcesResponse" } } } }, "403": { "$ref": "#/components/responses/Forbidden" } }
      }
    },
    "/boards/{boardId}/projects/{projectId}/calendar/{itemId}": {
      "patch": {
        "summary": "Update a project calendar item",
        "description": "Revision-bound rename, move, or inclusive edge-resize by stable item ID and item_type. Milestone renames atomically update matching task and subtask Milestone fields.",
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/CalendarProjectId" }, { "name": "itemId", "in": "path", "required": true, "schema": { "type": "string", "minLength": 1, "maxLength": 160 } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProjectCalendarUpdate" } } } },
        "responses": { "200": { "description": "Updated item, changed counts, authoritative project and revision.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProjectCalendarMutationResponse" } } } }, "403": { "$ref": "#/components/responses/Forbidden" }, "409": { "$ref": "#/components/responses/Conflict" } }
      },
      "delete": {
        "summary": "Delete a project calendar item",
        "description": "Destructive revision-bound deletion by stable ID and item_type. Requires exact current_title confirmation; service keys additionally require tasks:calendar:delete. Milestone deletion atomically clears matching task and subtask Milestone fields.",
        "parameters": [{ "$ref": "#/components/parameters/BoardId" }, { "$ref": "#/components/parameters/CalendarProjectId" }, { "name": "itemId", "in": "path", "required": true, "schema": { "type": "string", "minLength": 1, "maxLength": 160 } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProjectCalendarDelete" } } } },
        "responses": { "200": { "description": "Deleted item, changed counts, authoritative project and revision.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProjectCalendarMutationResponse" } } } }, "403": { "$ref": "#/components/responses/Forbidden" }, "409": { "$ref": "#/components/responses/Conflict" } }
      }
    },
    "/boards/{boardId}/projects/{projectId}/tasks/{taskId}": {
      "get": {
        "summary": "Get developer task context",
        "description": "Requires tasks:read, read, or write scope. Returns nested task fields, the complete comment timeline, attachment metadata with authenticated attachmentPath values, image-only metadata for visual inspection, and a revision for concurrency-safe writes.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ProjectId"
          },
          {
            "$ref": "#/components/parameters/TaskId"
          }
        ],
        "responses": {
          "200": {
            "description": "Complete developer task context.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskContext"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "summary": "Update project task",
        "description": "ONE API-key and OAuth callers require tasks:write or write scope and use bot-managed field provenance; details and comments are append-only, and status changes must use the review-state endpoint. A signed-in ONE web user with project edit access may use this same route for a Global quick edit when expectedRevision or expected_revision is present and fields contains only status and/or severity.",
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "$ref": "#/components/parameters/ProjectId" },
          { "$ref": "#/components/parameters/TaskId" }
        ],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object" } } } },
        "responses": {
          "200": { "description": "Task updated with any preserved-field conflicts." },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "409": { "description": "Task revision conflict." }
        }
      }
    },
    "/boards/{boardId}/projects/{projectId}/tasks/{taskId}/subtasks/{subtaskId}": {
      "parameters": [
        { "$ref": "#/components/parameters/BoardId" },
        { "$ref": "#/components/parameters/ProjectId" },
        { "$ref": "#/components/parameters/TaskId" },
        { "$ref": "#/components/parameters/SubtaskId" }
      ],
      "get": {
        "summary": "Get project subtask context",
        "description": "Requires tasks:read, read, or write scope. Returns full one-level subtask fields, comments, attachment metadata with authenticated retrieval paths, images, Slack sources, and revision.",
        "responses": { "200": { "description": "Subtask context." }, "404": { "$ref": "#/components/responses/NotFound" } }
      },
      "patch": {
        "summary": "Update project subtask",
        "description": "Requires tasks:write or write scope. Applies the same field, comment, source, and revision semantics as a top-level task. Status changes and nested subtasks are rejected.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object" } } } },
        "responses": { "200": { "description": "Subtask updated." }, "409": { "description": "Subtask revision conflict." } }
      }
    },
    "/boards/{boardId}/projects/{projectId}/tasks/{taskId}/subtasks/{subtaskId}/comments": {
      "parameters": [
        { "$ref": "#/components/parameters/BoardId" },
        { "$ref": "#/components/parameters/ProjectId" },
        { "$ref": "#/components/parameters/TaskId" },
        { "$ref": "#/components/parameters/SubtaskId" }
      ],
      "post": {
        "summary": "Comment on a project subtask",
        "description": "Requires tasks:comment or broader write scope. Returns only the appended comment, duplicate flag, and new revision; it does not expose subtask fields or prior comments.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["text"] } } } },
        "responses": { "200": { "description": "Idempotent duplicate comment." }, "201": { "description": "Comment appended." }, "409": { "description": "Subtask revision conflict." } }
      }
    },
    "/boards/{boardId}/projects/{projectId}/tasks/{taskId}/subtasks/{subtaskId}/images/{assetId}": {
      "get": {
        "summary": "Fetch developer subtask image",
        "description": "Requires tasks:read, read, or write scope. Proxies a Firebase subtask-description or comment image without exposing its stored download URL.",
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "$ref": "#/components/parameters/ProjectId" },
          { "$ref": "#/components/parameters/TaskId" },
          { "$ref": "#/components/parameters/SubtaskId" },
          { "$ref": "#/components/parameters/AssetId" }
        ],
        "responses": {
          "200": {
            "description": "Image bytes.",
            "content": {
              "image/*": {
                "schema": { "type": "string", "format": "binary" }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/boards/{boardId}/projects/{projectId}/tasks/{taskId}/subtasks/{subtaskId}/attachments/{assetId}": {
      "get": {
        "summary": "Fetch developer subtask attachment",
        "description": "Requires tasks:read, read, or write scope. Returns authenticated subtask attachment bytes without exposing Firebase Storage paths or download URLs.",
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "$ref": "#/components/parameters/ProjectId" },
          { "$ref": "#/components/parameters/TaskId" },
          { "$ref": "#/components/parameters/SubtaskId" },
          { "$ref": "#/components/parameters/AssetId" }
        ],
        "responses": {
          "200": {
            "description": "Attachment bytes using the validated stored content type.",
            "content": { "application/octet-stream": { "schema": { "type": "string", "format": "binary" } } }
          },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/slack/task-automation/channels/{teamId}/{channelId}": {
      "parameters": [
        { "$ref": "#/components/parameters/TeamId" },
        { "$ref": "#/components/parameters/ChannelId" }
      ],
      "get": {
        "summary": "Get Slack channel project mapping",
        "description": "Requires tasks:read, read, or write scope.",
        "responses": { "200": { "description": "Mapping or null." } }
      },
      "post": {
        "summary": "Save Slack channel project mapping",
        "description": "Requires tasks:write or write scope. Validates that the board is a project task board and that the project exists before saving the lookup.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["boardId", "projectId"] } } } },
        "responses": { "200": { "description": "Mapping saved." } }
      }
    },
    "/slack/task-automation/proposals": {
      "get": {
        "summary": "List Slack task proposals",
        "description": "Requires tasks:read, read, or write scope. Returns only proposals created by the active ONE credential and filters by teamId, channelId, threadTs, proposalMessageTs, or status.",
        "responses": { "200": { "description": "Versioned proposal list." } }
      },
      "post": {
        "summary": "Create Slack task proposal",
        "description": "Requires tasks:write or write scope, read access to the ONE People board for identity resolution, and a project task board target. Binds the proposal controls to the creating ONE credential. Stores only the summary, task operations, participant IDs, hashes, and Slack source metadata; raw transcripts and attachment bytes are not accepted or persisted.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object" } } } },
        "responses": { "201": { "description": "Pending 24-hour proposal created." } }
      }
    },
    "/slack/task-automation/proposals/{proposalId}": {
      "parameters": [
        { "$ref": "#/components/parameters/ProposalId" }
      ],
      "get": {
        "summary": "Get Slack task proposal",
        "description": "Requires tasks:read, read, or write scope and the same ONE credential that created the proposal.",
        "responses": { "200": { "description": "Proposal." }, "404": { "$ref": "#/components/responses/NotFound" } }
      },
      "patch": {
        "summary": "Refresh Slack task proposal",
        "description": "Requires tasks:write or write scope, the same ONE credential that created the proposal, and, for content refreshes, read access to the ONE People board for identity resolution. Replaces a pending preview with a new version and 24-hour expiry using an exact positive-integer expectedVersion. The project target cannot change. The Slack bot binds a posted message without incrementing the proposal version before advertising approval controls; approval remains gated until that exact visible version is acknowledged. A modal revision first sets beginRevision with the trusted Slack binding and actor, which transactionally makes the old version inactive and returns a revisionLock token required by the replacement refresh. revisionMessageTs retains bounded, trusted Slack revision-note references so later thread refreshes preserve prior modal corrections. Set supersede to true when a deleted target makes the pending preview permanently obsolete.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["expectedVersion"], "properties": { "expectedVersion": { "type": "integer", "minimum": 1 }, "bindProposalMessage": { "type": "boolean" }, "acknowledgeVisibleVersion": { "type": "boolean" }, "visibleVersion": { "type": "integer", "minimum": 1 }, "proposalMessageTs": { "type": "string" }, "beginRevision": { "type": "boolean" }, "actorSlackUserId": { "type": "string" }, "teamId": { "type": "string" }, "channelId": { "type": "string" }, "threadTs": { "type": "string" }, "revisionLockToken": { "type": "string" }, "revisionMessageTs": { "type": "array", "maxItems": 20, "items": { "type": "string", "maxLength": 80 } }, "supersede": { "type": "boolean" }, "supersededReason": { "type": "string", "maxLength": 500 } }, "allOf": [ { "if": { "required": ["bindProposalMessage"], "properties": { "bindProposalMessage": { "const": true } } }, "then": { "required": ["proposalMessageTs"] } }, { "if": { "required": ["acknowledgeVisibleVersion"], "properties": { "acknowledgeVisibleVersion": { "const": true } } }, "then": { "required": ["visibleVersion", "proposalMessageTs"] } }, { "if": { "required": ["beginRevision"], "properties": { "beginRevision": { "const": true } } }, "then": { "required": ["actorSlackUserId", "teamId", "channelId", "threadTs", "proposalMessageTs"] } } ] } } } },
        "responses": { "200": { "description": "Refreshed proposal." }, "400": { "$ref": "#/components/responses/BadRequest" }, "403": { "$ref": "#/components/responses/Forbidden" }, "409": { "description": "Proposal version, binding, state, or revision-lock conflict." }, "410": { "description": "Proposal expired before revision." } }
      }
    },
    "/slack/task-automation/proposals/{proposalId}/approve": {
      "parameters": [
        { "$ref": "#/components/parameters/ProposalId" }
      ],
      "post": {
        "summary": "Approve Slack task proposal",
        "description": "Requires tasks:write or write scope and the same ONE credential that created the proposal. Validates the exact version, trusted Slack team/channel/thread/message binding, live thread snapshot hash, 24-hour expiry, and participant approver before idempotently applying task operations.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["approverSlackUserId", "expectedVersion", "sourceSnapshotHash", "teamId", "channelId", "threadTs", "proposalMessageTs", "approvalSource"], "properties": { "approverSlackUserId": { "type": "string" }, "expectedVersion": { "type": "integer", "minimum": 1 }, "sourceSnapshotHash": { "type": "string" }, "teamId": { "type": "string" }, "channelId": { "type": "string" }, "threadTs": { "type": "string" }, "proposalMessageTs": { "type": "string" }, "approvalSource": { "type": "string", "enum": ["button", "command", "reaction"] } } } } } },
        "responses": { "200": { "description": "Proposal applied or prior idempotent result returned." }, "400": { "$ref": "#/components/responses/BadRequest" }, "403": { "$ref": "#/components/responses/Forbidden" }, "409": { "description": "Stale proposal or changed thread." }, "410": { "description": "Proposal expired." } }
      }
    },
    "/slack/task-automation/proposals/{proposalId}/cancel": {
      "parameters": [
        { "$ref": "#/components/parameters/ProposalId" }
      ],
      "post": {
        "summary": "Cancel Slack task proposal",
        "description": "Requires tasks:write or write scope and the same ONE credential that created the proposal. Transactionally validates the current visible version and trusted Slack message binding, then permits only the original requester or a proposed task owner to cancel without changing project tasks.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["actorSlackUserId", "expectedVersion", "teamId", "channelId", "threadTs", "proposalMessageTs"], "properties": { "actorSlackUserId": { "type": "string" }, "expectedVersion": { "type": "integer", "minimum": 1 }, "teamId": { "type": "string" }, "channelId": { "type": "string" }, "threadTs": { "type": "string" }, "proposalMessageTs": { "type": "string" }, "reason": { "type": "string", "maxLength": 500 } } } } } },
        "responses": { "200": { "description": "Proposal cancelled or prior idempotent cancellation returned." }, "400": { "$ref": "#/components/responses/BadRequest" }, "403": { "$ref": "#/components/responses/Forbidden" }, "409": { "description": "Stale or mismatched proposal control." }, "410": { "description": "Proposal expired." } }
      }
    },
    "/boards/{boardId}/projects/{projectId}/tasks/{taskId}/images/{assetId}": {
      "get": {
        "summary": "Fetch developer task image",
        "description": "Requires tasks:read, read, or write scope. Proxies a Firebase task-description or comment image without exposing its stored download URL.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ProjectId"
          },
          {
            "$ref": "#/components/parameters/TaskId"
          },
          {
            "$ref": "#/components/parameters/AssetId"
          }
        ],
        "responses": {
          "200": {
            "description": "Image bytes.",
            "content": {
              "image/*": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/boards/{boardId}/projects/{projectId}/tasks/{taskId}/attachments": {
      "post": {
        "summary": "Attach a document to a developer task",
        "description": "Requires tasks:write, broader write scope, or an assigned personal task. Uploads one PDF or UTF-8 TXT, Markdown, CSV, JSON, XML, YAML, or LOG file under 10 MB through private ONE storage. Use X-Idempotency-Key for safe retries and optional X-Expected-Revision for concurrency safety.",
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "$ref": "#/components/parameters/ProjectId" },
          { "$ref": "#/components/parameters/TaskId" },
          { "name": "X-File-Name", "in": "header", "required": true, "schema": { "type": "string", "maxLength": 180 } },
          { "name": "X-Idempotency-Key", "in": "header", "required": true, "schema": { "type": "string", "maxLength": 160 } },
          { "name": "X-Expected-Revision", "in": "header", "required": false, "schema": { "type": "string", "maxLength": 128 } }
        ],
        "requestBody": {
          "required": true,
          "content": { "application/octet-stream": { "schema": { "type": "string", "format": "binary" } } }
        },
        "responses": {
          "200": { "description": "Idempotent duplicate upload." },
          "201": { "description": "Document attached." },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "409": { "description": "Task revision or attachment-limit conflict." }
        }
      }
    },
    "/boards/{boardId}/projects/{projectId}/tasks/{taskId}/attachments/{assetId}": {
      "get": {
        "summary": "Fetch developer task attachment",
        "description": "Requires tasks:read, read, or write scope. Returns authenticated task attachment bytes without exposing Firebase Storage paths or download URLs. PDF and UTF-8 text documents are suitable for get_task_attachment, videos for get_task_video, and images remain available through the image route for visual MCP content.",
        "parameters": [
          { "$ref": "#/components/parameters/BoardId" },
          { "$ref": "#/components/parameters/ProjectId" },
          { "$ref": "#/components/parameters/TaskId" },
          { "$ref": "#/components/parameters/AssetId" }
        ],
        "responses": {
          "200": {
            "description": "Attachment bytes using the validated stored content type.",
            "content": { "application/octet-stream": { "schema": { "type": "string", "format": "binary" } } }
          },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/boards/{boardId}/projects/{projectId}/tasks/{taskId}/comments": {
      "post": {
        "summary": "Add developer task comment",
        "description": "Requires tasks:comment or write scope. Adds an idempotent Codex-attributed nested task comment and rejects stale revisions.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ProjectId"
          },
          {
            "$ref": "#/components/parameters/TaskId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskCommentRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Task comment created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskWriteResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "Task revision conflict."
          }
        }
      }
    },
    "/boards/{boardId}/projects/{projectId}/tasks/{taskId}/review-state": {
      "patch": {
        "summary": "Set developer task review state",
        "description": "Requires tasks:review or write scope. Codex may set only In Progress or Review; a human must mark Done.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ProjectId"
          },
          {
            "$ref": "#/components/parameters/TaskId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskReviewStateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Task review state updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskWriteResponse"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "Task revision conflict."
          }
        }
      }
    },
    "/search": {
      "get": {
        "summary": "Search items across boards",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Text to search across item names, board names, groups, and visible fields. Search ignores common instruction words and supports token/prefix matches such as chris for Christopher."
          },
          {
            "name": "board_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Optional board ID or board name to limit search. Omit it to use the bounded compact cross-board index."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Opaque nextCursor from a prior cross-board search page. Cursors are revision-bound and are not used for board-scoped search."
          }
        ],
        "responses": {
          "200": {
            "description": "Matching item summaries.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ItemSummary"
                      }
                    },
                    "indexRevision": {
                      "type": "string",
                      "description": "Revision of the compact search index used for a cross-board result."
                    },
                    "nextCursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next bounded cross-board page, when more matches exist."
                    }
                  },
                  "required": [
                    "items"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/backups": {
      "get": {
        "summary": "List protected ONE backup metadata",
        "description": "Returns newest-first backup summaries without workspace or protected data-root payloads. Requires backups:read or Firebase owner authentication. Use nextCursor for the next page.",
        "security": [
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Opaque backup ID returned as nextCursor by the previous page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Backup metadata page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BackupListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid or expired cursor."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "summary": "Queue a protected ONE backup",
        "description": "Returns immediately with a background job. Requires backups:write or Firebase owner authentication; API keys may create manual backups only.",
        "security": [
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "source": {
                    "type": "string",
                    "enum": [
                      "manual",
                      "automatic"
                    ],
                    "default": "manual"
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "compact",
                      "full"
                    ],
                    "default": "compact"
                  },
                  "label": {
                    "type": "string",
                    "maxLength": 240
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Backup job queued."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/backups/{backupId}": {
      "get": {
        "summary": "Get protected ONE backup metadata",
        "description": "Returns one backup's safe identity, coverage statistics, content policy, and protected root names without workspace or data-root payloads. Requires backups:read or Firebase owner authentication.",
        "security": [
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "parameters": [
          {
            "name": "backupId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Backup metadata without protected payloads.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BackupMetadataResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "Backup snapshot not found."
          }
        }
      }
    },
    "/backups/{backupId}/export": {
      "get": {
        "summary": "Export a protected ONE backup",
        "description": "Downloads an import-compatible ONE JSON backup envelope. This sensitive read requires a signed-in Firebase owner; API keys are never accepted. Import, restore, deletion, and backup-settings mutation remain private UI operations. HTTPS export is limited to 30 MiB; larger snapshots remain downloadable from the signed-in ONE Backups panel.",
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "parameters": [
          {
            "name": "backupId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Import-compatible JSON export. X-Content-SHA256 contains the lowercase SHA-256 digest of the response bytes.",
            "headers": {
              "X-Content-SHA256": {
                "schema": {
                  "type": "string",
                  "pattern": "^[0-9a-f]{64}$"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BackupExport"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "Backup snapshot not found."
          },
          "409": {
            "description": "Backup write is incomplete."
          },
          "413": {
            "description": "Backup exceeds the HTTPS export limit."
          }
        }
      }
    },
    "/backups/jobs/{jobId}": {
      "get": {
        "summary": "Get a backup job",
        "description": "Returns queued, running, completed, or failed status and the saved backup summary when complete. Backup API keys may read only jobs they created.",
        "security": [
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current backup job state."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "Backup job not found."
          }
        }
      }
    },
    "/documents/sign-requests": {
      "get": {
        "summary": "List e-signature agreements",
        "description": "Requires documents:read or a Firebase user with Documents access.",
        "responses": {
          "200": {
            "description": "Private agreement records without signing tokens.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignatureRequestListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "summary": "Create an agreement draft",
        "description": "Upload a raw PDF, PNG, JPEG, or WebP body (20 MB maximum). Headers X-File-Name, X-Document-Name, and X-Signers are required; X-Subject, X-Message, and JSON X-Settings are optional. Requires documents:write.",
        "parameters": [
          {
            "in": "header",
            "name": "X-File-Name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Document-Name",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Signers",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Subject",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Message",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Settings",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/pdf": {
              "schema": {
                "type": "string",
                "contentEncoding": "binary"
              }
            },
            "image/*": {
              "schema": {
                "type": "string",
                "contentEncoding": "binary"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Draft created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignatureRequestResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/documents/sign-requests/from-template": {
      "post": {
        "summary": "Create a draft from a template",
        "description": "Fill the template recipient roles in order. Requires documents:write.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "templateId": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "signers": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/SignatureRecipient"
                    }
                  },
                  "subject": {
                    "type": "string"
                  },
                  "message": {
                    "type": "string"
                  },
                  "settings": {
                    "$ref": "#/components/schemas/SignatureSettings"
                  }
                },
                "required": [
                  "templateId",
                  "name",
                  "signers"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Draft created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignatureRequestResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/documents/sign-templates": {
      "get": {
        "summary": "List reusable agreement templates",
        "description": "Requires documents:read.",
        "responses": {
          "200": {
            "description": "Templates with documents, roles, fields, messages, and options."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/documents/sign-templates/{templateId}": {
      "delete": {
        "summary": "Delete a signature template",
        "description": "Permanently removes the selected reusable template and its private document copies. Requires documents:write.",
        "parameters": [
          {
            "in": "path",
            "name": "templateId",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Template deleted."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/documents/sign-requests/{requestId}": {
      "parameters": [
        {
          "in": "path",
          "name": "requestId",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "summary": "Get an agreement",
        "description": "Requires documents:read.",
        "responses": {
          "200": {
            "description": "Agreement details.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignatureRequestResponse"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "put": {
        "summary": "Update a draft",
        "description": "Update name, recipients/actions, routing, subject/message, reminders, and expiration. Requires documents:write.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "signers": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/SignatureRecipient"
                    }
                  },
                  "subject": {
                    "type": "string"
                  },
                  "message": {
                    "type": "string"
                  },
                  "settings": {
                    "$ref": "#/components/schemas/SignatureSettings"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated draft.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignatureRequestResponse"
                }
              }
            }
          },
          "409": {
            "description": "Request is not a draft."
          }
        }
      },
      "delete": {
        "summary": "Delete an agreement",
        "description": "Delete a draft or terminal agreement and its private files. Requires documents:write.",
        "responses": {
          "200": {
            "description": "Agreement deleted."
          },
          "409": {
            "description": "Live agreements must be voided first."
          }
        }
      }
    },
    "/documents/sign-requests/{requestId}/documents": {
      "post": {
        "summary": "Add a document to a draft",
        "description": "Upload a raw supported document body; 10 documents maximum. Requires documents:write.",
        "parameters": [
          {
            "in": "path",
            "name": "requestId",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-File-Name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/pdf": {
              "schema": {
                "type": "string",
                "contentEncoding": "binary"
              }
            },
            "image/*": {
              "schema": {
                "type": "string",
                "contentEncoding": "binary"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Document added.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignatureRequestResponse"
                }
              }
            }
          },
          "409": {
            "description": "Request is not a draft."
          }
        }
      }
    },
    "/documents/sign-requests/{requestId}/documents/{documentId}": {
      "delete": {
        "summary": "Remove a document from a draft",
        "parameters": [
          {
            "in": "path",
            "name": "requestId",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "documentId",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Document and its fields removed."
          },
          "409": {
            "description": "The only document cannot be removed."
          }
        }
      }
    },
    "/documents/sign-requests/{requestId}/file": {
      "get": {
        "summary": "Download an agreement file",
        "description": "Return one verified private source document, a PDF combining all source documents, or the completed signed PDF. Source defaults to the first document unless document_id is supplied. Requires documents:read.",
        "parameters": [
          {
            "in": "path",
            "name": "requestId",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "kind",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "source",
                "combined",
                "signed"
              ]
            }
          },
          {
            "in": "query",
            "name": "document_id",
            "description": "Source document ID. Used only when kind=source.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Verified private agreement file.",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "contentEncoding": "binary"
                }
              },
              "image/*": {
                "schema": {
                  "type": "string",
                  "contentEncoding": "binary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/documents/sign-requests/{requestId}/prepare": {
      "put": {
        "summary": "Place recipient fields",
        "description": "Supports signature, initials, text, name, email, title, date_signed, and checkbox fields. Requires documents:write.",
        "parameters": [
          {
            "in": "path",
            "name": "requestId",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "fields": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/SignatureField"
                    }
                  }
                },
                "required": [
                  "fields"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Fields saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignatureRequestResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    },
    "/documents/sign-requests/{requestId}/send": {
      "post": {
        "summary": "Send a prepared agreement",
        "description": "Creates private links for the active parallel/sequential routing group. Requires documents:send.",
        "parameters": [
          {
            "in": "path",
            "name": "requestId",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Agreement sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignatureRequestResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "409": {
            "description": "Request is not a draft."
          }
        }
      }
    },
    "/documents/sign-requests/{requestId}/resend": {
      "post": {
        "summary": "Resend a recipient signing link",
        "description": "Rotate and resend one active recipient's private signing link. The previous link is invalidated. Requires documents:send.",
        "parameters": [
          {
            "in": "path",
            "name": "requestId",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "signerId": {
                    "type": "string"
                  }
                },
                "required": [
                  "signerId"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recipient link rotated and delivery retried.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignatureRequestResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The request or recipient is not eligible for resend."
          }
        }
      }
    },
    "/documents/sign-requests/{requestId}/refresh": {
      "post": {
        "summary": "Refresh agreement status",
        "description": "Return the current native delivery, routing, and completion state. Requires documents:read.",
        "parameters": [
          {
            "in": "path",
            "name": "requestId",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current agreement status.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "rateLimited": {
                      "type": "boolean"
                    },
                    "request": {
                      "$ref": "#/components/schemas/SignatureRequest"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/documents/sign-requests/{requestId}/void": {
      "post": {
        "summary": "Void a live agreement",
        "description": "Stop a sent or delivered agreement and invalidate its private signing links. Requires documents:send.",
        "parameters": [
          {
            "in": "path",
            "name": "requestId",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "maxLength": 500
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Agreement voided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignatureRequestResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Only a sent or delivered agreement can be voided."
          }
        }
      }
    },
    "/documents/sign-requests/{requestId}/template": {
      "post": {
        "summary": "Save a prepared draft as a template",
        "description": "Requires documents:write.",
        "parameters": [
          {
            "in": "path",
            "name": "requestId",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Template saved."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    },
    "/signing/{token}": {
      "get": {
        "summary": "Open a private signing session",
        "security": [],
        "parameters": [
          {
            "in": "path",
            "name": "token",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Token-scoped recipient session."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "410": {
            "description": "Link is no longer active."
          }
        }
      }
    },
    "/signing/{token}/documents/{documentId}": {
      "get": {
        "summary": "Preview or download a token-scoped source document",
        "description": "Returns one private source document for the recipient signing page. The page exposes an explicit download action only when the sender enabled recipient downloads.",
        "security": [],
        "parameters": [
          { "in": "path", "name": "token", "required": true, "schema": { "type": "string" } },
          { "in": "path", "name": "documentId", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Private source document bytes." },
          "404": { "$ref": "#/components/responses/NotFound" },
          "410": { "description": "Link is no longer active." }
        }
      }
    },
    "/signing/{token}/final": {
      "get": {
        "summary": "Download the completed signed PDF",
        "description": "Returns the final PDF only after every required signer has completed and recipient downloads are allowed.",
        "security": [],
        "parameters": [
          { "in": "path", "name": "token", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Completed signed PDF attachment." },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/signing/{token}/assistant": {
      "post": {
        "summary": "Ask the token-scoped contract assistant",
        "description": "Opt-in recipient helper for summaries, document questions, simple explanations, and translations. This external-recipient action deliberately has no MCP tool because agents must not impersonate signers.",
        "security": [],
        "parameters": [
          { "in": "path", "name": "token", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "action": { "type": "string", "enum": ["summary", "ask", "explain", "translate"] },
                  "documentText": { "type": "string", "maxLength": 80000 },
                  "selection": { "type": "string", "maxLength": 4000 },
                  "question": { "type": "string", "maxLength": 500 },
                  "targetLanguage": { "type": "string", "maxLength": 80 }
                },
                "required": ["action", "documentText"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Grounded assistant response and AI disclaimer." },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "429": { "description": "Per-link assistant rate limit reached." }
        }
      }
    },
    "/signing/{token}/complete": {
      "post": {
        "summary": "Complete a signing session",
        "security": [],
        "parameters": [
          {
            "in": "path",
            "name": "token",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Recipient response recorded."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "410": {
            "description": "Link is no longer active."
          }
        }
      }
    },
    "/signing/{token}/decline": {
      "post": {
        "summary": "Decline an agreement",
        "security": [],
        "parameters": [
          {
            "in": "path",
            "name": "token",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Decline recorded and agreement stopped."
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "410": {
            "description": "Link is no longer active."
          }
        }
      }
    },
    "/finance/import": {
      "post": {
        "summary": "Import Finance statement files",
        "description": "Parse, normalize, checksum, and idempotently merge up to 20 supported statement files, including Dutch- and English-language ING payment CSVs and Dutch ING Portefeuilleoverzicht investment PDFs. Investment PDFs use the embedded date and reconcile holdings to the stated EUR totals. Repeated, renamed, regenerated and equivalent CSV/PDF portfolios are skipped by account, date and holdings; corrections update the existing dated valuation with history. Available cash is preserved separately. Overlapping legacy providerless rows and newer stable ING references are reconciled one occurrence at a time so genuine repeated charges remain distinct. Raw source bytes are not retained. Requires a signed-in Firebase user with Finance write access.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["files"], "properties": { "files": { "type": "array", "minItems": 1, "maxItems": 20, "items": { "type": "object", "required": ["name", "byteSize", "contentBase64"], "properties": { "name": { "type": "string", "maxLength": 180 }, "byteSize": { "type": "integer", "minimum": 1, "maximum": 2097152 }, "contentBase64": { "type": "string" }, "accountId": { "type": "string", "maxLength": 120 } } } } } } } } },
        "responses": { "201": { "description": "Statements normalized and merged; duplicate rows and files are reported." }, "400": { "$ref": "#/components/responses/BadRequest" }, "403": { "$ref": "#/components/responses/Forbidden" } }
      }
    },
    "/finance/imports/{batchId}/download": {
      "get": {
        "summary": "Download a normalized Finance statement import",
        "description": "Reconstruct a normalized CSV from canonical Finance records for one import batch. This is not the original uploaded source file.",
        "parameters": [{ "in": "path", "name": "batchId", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Normalized statement CSV.", "content": { "text/csv": { "schema": { "type": "string" } } } }, "404": { "description": "Import batch not found." } }
      }
    },
    "/finance/imports/clear": {
      "post": {
        "summary": "Clear imported Finance data",
        "description": "Owner-only destructive cleanup of all statement imports, imported transactions, statement valuations, and related decisions. Configured accounts and manual valuations are preserved. Exact counts, updated time, acknowledgement, and confirmation phrase are required.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["acknowledged", "expectedImportCount", "expectedTransactionCount", "expectedUpdatedAt", "confirmation"], "properties": { "acknowledged": { "type": "boolean", "const": true }, "expectedImportCount": { "type": "integer", "minimum": 0 }, "expectedTransactionCount": { "type": "integer", "minimum": 0 }, "expectedUpdatedAt": { "type": "string" }, "confirmation": { "type": "string" } } } } } },
        "responses": { "200": { "description": "Imported Finance data cleared." }, "403": { "$ref": "#/components/responses/Forbidden" }, "409": { "description": "Finance state changed after confirmation was prepared." } }
      }
    },
    "/finance/transactions/{transactionId}/decision": {
      "post": {
        "summary": "Set a manual Finance transaction decision",
        "description": "Apply a manual classification, category, project/payroll/admin allocations, remainder treatment, and note to one transaction, then reconcile dependent Finance state.",
        "parameters": [{ "in": "path", "name": "transactionId", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "classification": { "type": "string", "enum": ["external", "external_income", "external_expense", "internal_transfer", "contribution", "withdrawal", "auto"] }, "categoryId": { "type": ["string", "null"] }, "subcategoryId": { "type": ["string", "null"] }, "projectAllocations": { "type": "array", "maxItems": 50, "items": { "type": "object" } }, "payrollAllocations": { "type": "array", "maxItems": 50, "items": { "type": "object" } }, "adminAllocations": { "type": "array", "maxItems": 1, "items": { "type": "object" } }, "allocationRemainder": { "type": ["string", "null"], "enum": ["overhead", "unassigned", null] }, "note": { "type": ["string", "null"] } } } } } },
        "responses": { "200": { "description": "Transaction decision and dependent summaries updated." }, "409": { "description": "Conflicting categorization correction or concurrent Finance mutation." } }
      }
    },
    "/finance/transactions/bulk-decision": {
      "post": {
        "summary": "Set one decision on multiple Finance transactions",
        "description": "Apply one validated manual decision to up to 200 distinct transactions under the Finance mutation lock.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["transactionIds", "decision"], "properties": { "transactionIds": { "type": "array", "minItems": 1, "maxItems": 200, "uniqueItems": true, "items": { "type": "string" } }, "decision": { "type": "object" } } } } } },
        "responses": { "200": { "description": "Per-transaction decisions and reconciled state returned." }, "400": { "$ref": "#/components/responses/BadRequest" } }
      }
    },
    "/finance/transactions/{transactionId}/comments": {
      "get": {
        "summary": "List private Finance transaction comments",
        "description": "Signed-in-user-only Finance discussion. API keys never receive comment text or presence.",
        "parameters": [{ "in": "path", "name": "transactionId", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Comments and mentionable People directory." }, "403": { "$ref": "#/components/responses/Forbidden" } }
      },
      "post": {
        "summary": "Add a private Finance transaction comment",
        "parameters": [{ "in": "path", "name": "transactionId", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["text"], "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "mentions": { "type": "array", "maxItems": 20, "items": { "type": "string" } } } } } } },
        "responses": { "201": { "description": "Comment stored and valid mentions notified." } }
      }
    },
    "/finance/transactions/{transactionId}/comments/{commentId}": {
      "patch": {
        "summary": "Edit a private Finance transaction comment",
        "description": "Author-or-owner edit with optimistic concurrency using the current updatedAt, or createdAt for a never-edited comment.",
        "parameters": [{ "in": "path", "name": "transactionId", "required": true, "schema": { "type": "string" } }, { "in": "path", "name": "commentId", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["text", "expectedUpdatedAt"], "properties": { "text": { "type": "string", "maxLength": 4000 }, "mentions": { "type": "array", "maxItems": 20, "items": { "type": "string" } }, "expectedUpdatedAt": { "type": "string" } } } } } },
        "responses": { "200": { "description": "Comment updated." }, "409": { "description": "Comment changed since it was read." } }
      },
      "delete": {
        "summary": "Delete a private Finance transaction comment",
        "description": "Author-or-owner destructive delete requiring the current updatedAt and exact comment ID confirmation.",
        "parameters": [{ "in": "path", "name": "transactionId", "required": true, "schema": { "type": "string" } }, { "in": "path", "name": "commentId", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["expectedUpdatedAt", "confirmCommentId"], "properties": { "expectedUpdatedAt": { "type": "string" }, "confirmCommentId": { "type": "string" } } } } } },
        "responses": { "200": { "description": "Comment permanently deleted; transaction and other comments preserved." }, "409": { "description": "Comment changed since it was read." } }
      }
    },
    "/finance/bills": {
      "get": {
        "summary": "List Accounts Payable bills",
        "description": "Search, filter, sort, and page the bounded AP register with status counts. Date ranges can target issue, due, paid, or updated dates. Requires finance:read, read, write, or Firebase Finance access.",
        "parameters": [{ "in": "query", "name": "q", "schema": { "type": "string", "maxLength": 160 } }, { "in": "query", "name": "status", "schema": { "type": "string", "enum": ["needs_review", "approved", "paid", "rejected", "cancelled"] } }, { "in": "query", "name": "currency", "schema": { "type": "string", "pattern": "^[A-Z]{3}$" } }, { "in": "query", "name": "matched", "schema": { "type": "string", "enum": ["matched", "unmatched"] } }, { "in": "query", "name": "dateField", "schema": { "type": "string", "enum": ["issueDate", "dueDate", "paidDate", "updatedAt"], "default": "dueDate" } }, { "in": "query", "name": "dateFrom", "schema": { "type": "string", "format": "date" } }, { "in": "query", "name": "dateTo", "schema": { "type": "string", "format": "date" } }, { "in": "query", "name": "sortBy", "schema": { "type": "string", "enum": ["vendor", "invoiceNumber", "issueDate", "dueDate", "paidDate", "status", "amount", "updatedAt"], "default": "dueDate" } }, { "in": "query", "name": "sortDirection", "schema": { "type": "string", "enum": ["asc", "desc"], "default": "asc" } }, { "in": "query", "name": "offset", "schema": { "type": "integer", "minimum": 0, "maximum": 10000 } }, { "in": "query", "name": "limit", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 100 } }, { "in": "query", "name": "cursor", "description": "Stable record id returned as nextCursor by the preceding page.", "schema": { "type": "string", "maxLength": 300 } }],
        "responses": { "200": { "description": "Accounts Payable register." }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" } }
      },
      "post": {
        "summary": "Create an Accounts Payable bill",
        "description": "Create a needs-review supplier bill using minor-unit string amounts. The bill total must be positive, while line-item unitPriceMinor, totalMinor, and rateMinor may be signed to retain printed credits, repayments, discounts, or corrections. Optional lineItems retain printed people, project names, hours, and rates; projectAllocations, payrollAllocations, adminAllocations, and allocationRemainder use the same multi-target work-allocation contract as Finance transactions. Requires finance:write, write, or Firebase Finance write access.",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["vendor", "issueDate", "dueDate", "amountMinor", "currency"], "properties": { "vendor": { "type": "object" }, "invoiceNumber": { "type": "string" }, "issueDate": { "type": "string", "format": "date" }, "dueDate": { "type": "string", "format": "date" }, "amountMinor": { "type": "string", "pattern": "^[0-9]+$" }, "currency": { "type": "string", "pattern": "^[A-Z]{3}$" }, "lineItems": { "type": "array", "maxItems": 200, "items": { "type": "object", "required": ["description", "totalMinor"], "properties": { "description": { "type": "string" }, "quantity": { "type": "string" }, "unitPriceMinor": { "type": "string", "pattern": "^-?[0-9]+$" }, "totalMinor": { "type": "string", "pattern": "^-?[0-9]+$" }, "personName": { "type": "string" }, "projectName": { "type": "string" }, "hours": { "type": "string" }, "rateMinor": { "type": "string", "pattern": "^-?[0-9]+$" } } } } } } } } },
        "responses": { "201": { "description": "Bill created for review." }, "400": { "$ref": "#/components/responses/BadRequest" }, "409": { "description": "Duplicate invoice or idempotency conflict." } }
      }
    },
    "/finance/bills/import": {
      "post": {
        "summary": "Scan an invoice into Accounts Payable",
        "description": "Accept a raw PDF or supported invoice image through ONE's shared receipt scanner (Gemini 2.5 Flash with the configured escalation model), extract supplier, invoice number, dates, totals, itemised people, hours, rates, and printed projects, then create a needs-review Accounts Payable bill. A printed project is auto-allocated only when it uniquely matches an active Production project; otherwise the review UI, API, and MCP expose manual multi-project allocation. Duplicate source files reuse their existing payable.",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }, { "in": "header", "name": "X-File-Name", "required": true, "schema": { "type": "string" } }, { "in": "header", "name": "X-Evidence-Type", "required": false, "schema": { "type": "string", "default": "invoice" } }, { "in": "header", "name": "X-Scan-Channel", "required": false, "schema": { "type": "string", "enum": ["desktop", "mobile"], "default": "desktop" } }],
        "requestBody": { "required": true, "content": { "application/pdf": { "schema": { "type": "string", "contentEncoding": "binary" } }, "image/jpeg": { "schema": { "type": "string", "contentEncoding": "binary" } }, "image/png": { "schema": { "type": "string", "contentEncoding": "binary" } }, "image/heic": { "schema": { "type": "string", "contentEncoding": "binary" } }, "image/tiff": { "schema": { "type": "string", "contentEncoding": "binary" } } } },
        "responses": { "201": { "description": "Invoice scanned and needs-review payable returned." }, "409": { "description": "Idempotency key conflicts with another file." }, "422": { "description": "The document was not recognized as an unpaid invoice or could not create a payable." } }
      }
    },
    "/finance/bills/aging": {
      "get": {
        "summary": "Get Accounts Payable aging",
        "description": "Return approved open bills in current, 1-30, 31-60, and 60+ day buckets by vendor and currency, plus bills awaiting approval.",
        "responses": { "200": { "description": "AP aging report." } }
      }
    },
    "/finance/bills/{billId}/approve": {
      "post": {
        "summary": "Approve an Accounts Payable bill",
        "description": "Approve a reviewed bill so it enters committed cash forecasting and outgoing-bank matching. Related endpoints use the same request contract: unapprove, reject, cancel, match, and unmatch.",
        "parameters": [{ "in": "path", "name": "billId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["expectedRevision"], "properties": { "expectedRevision": { "type": "integer" }, "reason": { "type": "string" }, "transactionId": { "type": "string" } } } } } },
        "responses": { "200": { "description": "Bill transitioned." }, "409": { "description": "Stale revision or invalid lifecycle transition." } }
      }
    },
    "/finance/bills/{billId}": {
      "get": {
        "summary": "Read an Accounts Payable bill",
        "parameters": [{ "in": "path", "name": "billId", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Bill details, audit history, and match candidates." }, "404": { "description": "Bill not found." } }
      },
      "patch": {
        "summary": "Edit an Accounts Payable bill",
        "description": "Review and edit supplier identity, invoice dates, amount/currency, description, signed extracted line items (including person, project, hours, and rate), and multiple Admin, Payroll-role, or active Production-project allocations with optimistic concurrency. For a paid bill created from an uploaded invoice, workMetadataOnly must be true and only supplier name, issue/due dates, line people, printed projects, hours, and work allocations may change; invoice number, descriptions, financial values, payment links, lifecycle state, and source evidence remain immutable.",
        "parameters": [{ "in": "path", "name": "billId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["expectedRevision"], "properties": { "expectedRevision": { "type": "integer", "minimum": 1 }, "workMetadataOnly": { "type": "boolean", "description": "Required for paid uploaded invoices; restricts the update to supplier name, issue/due dates, and existing work metadata while financial, payment, lifecycle, and source fields remain immutable." }, "vendor": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 240 }, "companyItemId": { "type": "string", "maxLength": 180 }, "contactItemId": { "type": "string", "maxLength": 180 } } }, "invoiceNumber": { "type": "string", "maxLength": 120 }, "issueDate": { "type": "string", "format": "date" }, "dueDate": { "type": "string", "format": "date" }, "amountMinor": { "type": "string", "pattern": "^[0-9]+$" }, "currency": { "type": "string", "pattern": "^[A-Z]{3}$" }, "description": { "type": "string", "maxLength": 2000 }, "notes": { "type": "string", "maxLength": 4000 }, "lineItems": { "type": "array", "maxItems": 200, "items": { "type": "object", "properties": { "description": { "type": "string" }, "quantity": { "type": "string" }, "unitPriceMinor": { "type": "string", "pattern": "^-?[0-9]+$" }, "totalMinor": { "type": "string", "pattern": "^-?[0-9]+$" }, "personName": { "type": "string" }, "projectName": { "type": "string" }, "hours": { "type": "string" }, "rateMinor": { "type": "string", "pattern": "^-?[0-9]+$" } } } }, "projectAllocations": { "type": "array", "maxItems": 50 }, "payrollAllocations": { "type": "array", "maxItems": 50 }, "adminAllocations": { "type": "array", "maxItems": 1 }, "allocationRemainder": { "type": "string", "enum": ["overhead", "unassigned"] } } } } } },
        "responses": { "200": { "description": "Bill updated." }, "409": { "description": "Stale revision or immutable state." } }
      },
      "delete": {
        "summary": "Delete an uncommitted Accounts Payable bill",
        "description": "Delete an unmatched bill in needs-review, rejected, or cancelled state. Approved bills must first be unapproved; paid bills are retained. A linked source receipt or scan is preserved for reprocessing.",
        "parameters": [{ "in": "path", "name": "billId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "responses": { "200": { "description": "Uncommitted bill deleted; source evidence retained." }, "409": { "description": "Approved, paid, or matched bill cannot be deleted." } }
      }
    },
    "/finance/bills/{billId}/source-file": {
      "get": {
        "summary": "Stream an Accounts Payable source invoice",
        "description": "Stream the private uploaded PDF or image that created the payable. The route follows the file from the receipt inbox into matched transaction evidence without exposing a Storage path or signed URL.",
        "parameters": [{ "in": "path", "name": "billId", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Private source invoice bytes.", "content": { "application/pdf": {}, "image/jpeg": {}, "image/png": {}, "image/webp": {} } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "description": "The payable has no retained source invoice." } }
      }
    },
    "/finance/bills/bulk-approve": {
      "post": {
        "summary": "Approve a bounded batch of Accounts Payable bills",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "responses": { "200": { "description": "Per-bill approval and failure results." } }
      }
    },
    "/finance/bills/{billId}/unapprove": {
      "post": {
        "summary": "Return an approved bill to review",
        "parameters": [{ "in": "path", "name": "billId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "responses": { "200": { "description": "Bill returned to needs-review." } }
      }
    },
    "/finance/bills/{billId}/reject": {
      "post": {
        "summary": "Reject an Accounts Payable bill",
        "parameters": [{ "in": "path", "name": "billId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "responses": { "200": { "description": "Bill rejected with an audit reason." } }
      }
    },
    "/finance/bills/{billId}/cancel": {
      "post": {
        "summary": "Cancel an open Accounts Payable bill",
        "parameters": [{ "in": "path", "name": "billId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "responses": { "200": { "description": "Bill cancelled with an audit reason." } }
      }
    },
    "/finance/bills/{billId}/match": {
      "post": {
        "summary": "Match a bill to an outgoing bank transaction",
        "parameters": [{ "in": "path", "name": "billId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "responses": { "200": { "description": "Approved bill marked paid and linked to the transaction." }, "409": { "description": "Direction, amount, currency, state, or revision mismatch." } }
      }
    },
    "/finance/bills/{billId}/unmatch": {
      "post": {
        "summary": "Remove a bill payment match",
        "parameters": [{ "in": "path", "name": "billId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "responses": { "200": { "description": "Bill returned to approved and transaction backlink removed." } }
      }
    },
    "/finance/bills/rematch": {
      "post": {
        "summary": "Match approved payables to bank transactions",
        "description": "Conservatively match up to 100 approved unmatched bills to exact outgoing external bank transactions.",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "responses": { "200": { "description": "Matched bills and review candidates." } }
      }
    },
    "/finance/accounts": {
      "get": {
        "summary": "List Finance accounts with invoice payment details",
        "description": "Return configured Finance accounts and their invoice-ready bank, BIC/SWIFT, IBAN, or account-number fields.",
        "responses": { "200": { "description": "Finance accounts and payment details." } }
      }
    },
    "/finance/accounts/{accountId}/payment-details": {
      "patch": {
        "summary": "Update an operating account's invoice payment details",
        "description": "Owner-only update of country, bank, BIC/SWIFT, and either IBAN or account number for an operating account.",
        "parameters": [{ "in": "path", "name": "accountId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["country", "bank", "bic"], "properties": { "country": { "type": "string" }, "bank": { "type": "string" }, "bic": { "type": "string" }, "iban": { "type": "string" }, "accountNumber": { "type": "string" } } } } } },
        "responses": { "200": { "description": "Payment details updated." }, "403": { "$ref": "#/components/responses/Forbidden" } }
      }
    },
    "/finance/invoice-customers": {
      "get": {
        "summary": "List Companies as invoice customers",
        "description": "Return Companies-board records available for Accounts Receivable customer selection.",
        "responses": { "200": { "description": "Invoice customer options." } }
      }
    },
    "/finance/invoices": {
      "get": {
        "summary": "List Accounts Receivable invoices",
        "description": "Search, filter, sort, and page the bounded AR invoice register with draft, issued, paid, and void counts. Date ranges can target issue, due, paid, or updated dates.",
        "parameters": [{ "in": "query", "name": "q", "schema": { "type": "string", "maxLength": 160 } }, { "in": "query", "name": "status", "schema": { "type": "string", "enum": ["draft", "issued", "paid", "void"] } }, { "in": "query", "name": "currency", "schema": { "type": "string", "pattern": "^[A-Z]{3}$" } }, { "in": "query", "name": "matched", "schema": { "type": "string", "enum": ["matched", "unmatched"] } }, { "in": "query", "name": "dateField", "schema": { "type": "string", "enum": ["issueDate", "dueDate", "paidDate", "updatedAt"], "default": "updatedAt" } }, { "in": "query", "name": "dateFrom", "schema": { "type": "string", "format": "date" } }, { "in": "query", "name": "dateTo", "schema": { "type": "string", "format": "date" } }, { "in": "query", "name": "sortBy", "schema": { "type": "string", "enum": ["customer", "invoiceNumber", "issueDate", "dueDate", "paidDate", "status", "amount", "balance", "updatedAt"], "default": "updatedAt" } }, { "in": "query", "name": "sortDirection", "schema": { "type": "string", "enum": ["asc", "desc"], "default": "desc" } }, { "in": "query", "name": "offset", "schema": { "type": "integer", "minimum": 0, "maximum": 10000 } }, { "in": "query", "name": "limit", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 100 } }, { "in": "query", "name": "cursor", "description": "Stable record id returned as nextCursor by the preceding page.", "schema": { "type": "string", "maxLength": 300 } }],
        "responses": { "200": { "description": "Accounts Receivable register." } }
      },
      "post": {
        "summary": "Create an Accounts Receivable invoice draft",
        "description": "Create an editable customer invoice draft. All calculated amounts are server-derived minor-unit strings. requestedNumber is optional and is reserved only when issuing; sowReference and purchaseOrderReference are optional PDF references.",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["client", "lineItems", "currency"], "properties": { "client": { "type": "object" }, "requestedNumber": { "type": "string", "maxLength": 120, "description": "Optional custom number reserved atomically at issue; duplicates are rejected." }, "sowReference": { "type": "string", "maxLength": 160 }, "purchaseOrderReference": { "type": "string", "maxLength": 160 }, "issueDate": { "type": "string", "format": "date" }, "dueDate": { "type": "string", "format": "date" }, "servicePeriod": { "type": "object" }, "taxTreatment": { "type": "string", "enum": ["domestic", "reverse_charge", "intra_community", "exempt", "out_of_scope"] }, "currency": { "type": "string" }, "lineItems": { "type": "array", "minItems": 1, "maxItems": 200, "items": { "type": "object" } } } } } } },
        "responses": { "201": { "description": "Invoice draft created." }, "400": { "$ref": "#/components/responses/BadRequest" } }
      }
    },
    "/finance/invoices/import": {
      "post": {
        "summary": "Extract and import a customer invoice with Gemini",
        "description": "Accept a raw PDF or supported invoice image, validate it, extract customer, dates, currency, lines, tax, and payment account data with Gemini, and create an editable review-required Accounts Receivable draft. Duplicate source hashes reuse the existing draft.",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }, { "in": "header", "name": "X-File-Name", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/pdf": { "schema": { "type": "string", "contentEncoding": "binary" } }, "image/jpeg": { "schema": { "type": "string", "contentEncoding": "binary" } }, "image/png": { "schema": { "type": "string", "contentEncoding": "binary" } } } },
        "responses": { "201": { "description": "Invoice extracted and draft created." }, "200": { "description": "Existing draft returned for a duplicate source file." }, "422": { "description": "Required invoice fields could not be extracted." } }
      }
    },
    "/finance/invoices/aging": {
      "get": {
        "summary": "Get Accounts Receivable aging",
        "description": "Return issued unpaid invoices in current, 1-30, 31-60, and 60+ day buckets by customer and currency.",
        "responses": { "200": { "description": "AR aging report." } }
      }
    },
    "/finance/invoices/{invoiceId}": {
      "get": {
        "summary": "Read an Accounts Receivable invoice",
        "parameters": [{ "in": "path", "name": "invoiceId", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Invoice details, retained revisions, delivery history, and match candidates." }, "404": { "description": "Invoice not found." } }
      },
      "patch": {
        "summary": "Edit an Accounts Receivable draft",
        "parameters": [{ "in": "path", "name": "invoiceId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["expectedRevision"], "properties": { "expectedRevision": { "type": "integer" }, "requestedNumber": { "type": "string", "maxLength": 120 }, "sowReference": { "type": "string", "maxLength": 160 }, "purchaseOrderReference": { "type": "string", "maxLength": 160 }, "client": { "type": "object" }, "issueDate": { "type": "string", "format": "date" }, "dueDate": { "type": "string", "format": "date" }, "servicePeriod": { "type": "object" }, "currency": { "type": "string" }, "lineItems": { "type": "array", "minItems": 1, "maxItems": 200, "items": { "type": "object" } } } } } } },
        "responses": { "200": { "description": "Draft invoice recalculated and updated." }, "409": { "description": "Stale revision or invoice is no longer a draft." } }
      },
      "delete": {
        "summary": "Delete an Accounts Receivable draft",
        "description": "Delete an unissued draft without consuming an invoice number. Issued, paid, and void invoices are retained.",
        "parameters": [{ "in": "path", "name": "invoiceId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "responses": { "200": { "description": "Draft invoice deleted." }, "409": { "description": "Issued invoices are retained." } }
      }
    },
    "/finance/invoices/rematch": {
      "post": {
        "summary": "Match issued receivables to bank transactions",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "responses": { "200": { "description": "Matched invoices and ambiguous review candidates." } }
      }
    },
    "/finance/invoices/{invoiceId}/duplicate": {
      "post": {
        "summary": "Duplicate an Accounts Receivable invoice into a draft",
        "description": "Copy any draft, issued, paid, or void invoice into a new editable draft with a newly reserved sequential invoice number while leaving the source unchanged. Editable commercial fields are copied, but the source number, delivery state, payment state, matches, and stored PDF revisions are not.",
        "parameters": [{ "in": "path", "name": "invoiceId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["expectedRevision"], "properties": { "expectedRevision": { "type": "integer" } } } } } },
        "responses": { "201": { "description": "New numbered, editable invoice draft created." }, "404": { "description": "Source invoice not found." }, "409": { "description": "Source invoice revision is stale or number reservation collided." } }
      }
    },
    "/finance/invoices/{invoiceId}/issue": {
      "post": {
        "summary": "Issue an immutable customer invoice",
        "description": "Atomically reserve the draft's optional requested custom number or the next year-scoped sequence, snapshot legal data and optional SOW/PO references, render a private PDF, and add the invoice to AR aging. Related lifecycle endpoints are revise, void, paid, match, and unmatch.",
        "parameters": [{ "in": "path", "name": "invoiceId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["expectedRevision"], "properties": { "expectedRevision": { "type": "integer" } } } } } },
        "responses": { "200": { "description": "Numbered invoice issued." }, "409": { "description": "Stale revision or invalid invoice state." } }
      }
    },
    "/finance/invoices/{invoiceId}/revise": {
      "post": {
        "summary": "Create a retained revision of an unsent invoice",
        "parameters": [{ "in": "path", "name": "invoiceId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "responses": { "200": { "description": "New immutable PDF revision stored." }, "409": { "description": "Sent, paid, void, or stale invoice cannot be revised." } }
      }
    },
    "/finance/invoices/{invoiceId}/void": {
      "post": {
        "summary": "Void an unsent issued invoice",
        "parameters": [{ "in": "path", "name": "invoiceId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "responses": { "200": { "description": "Invoice voided with an audit reason." }, "409": { "description": "Delivered or paid invoice cannot be voided." } }
      }
    },
    "/finance/invoices/{invoiceId}/match": {
      "post": {
        "summary": "Match an invoice to an incoming bank transaction",
        "parameters": [{ "in": "path", "name": "invoiceId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "responses": { "200": { "description": "Issued invoice marked paid and linked to the transaction." }, "409": { "description": "Direction, amount, currency, state, or revision mismatch." } }
      }
    },
    "/finance/invoices/{invoiceId}/paid": {
      "post": {
        "summary": "Mark an issued invoice paid without a bank match",
        "description": "Clear the outstanding balance, remove the invoice from AR aging and Finance Flow, and append an audit event without linking a bank transaction.",
        "parameters": [{ "in": "path", "name": "invoiceId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["expectedRevision"], "properties": { "expectedRevision": { "type": "integer" }, "paidDate": { "type": "string", "format": "date" } } } } } },
        "responses": { "200": { "description": "Issued invoice marked paid manually and removed from outstanding receivables." }, "409": { "description": "Invoice state or revision mismatch." } }
      }
    },
    "/finance/invoices/{invoiceId}/unmatch": {
      "post": {
        "summary": "Remove an invoice payment match",
        "parameters": [{ "in": "path", "name": "invoiceId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "responses": { "200": { "description": "Invoice returned to issued and transaction backlink removed." } }
      }
    },
    "/finance/invoices/{invoiceId}/send": {
      "post": {
        "summary": "Send an issued invoice",
        "description": "Send the current immutable PDF through the connected owner Gmail account and append delivery history. Requires finance:invoices:send, write, or Firebase Finance write access.",
        "parameters": [{ "in": "path", "name": "invoiceId", "required": true, "schema": { "type": "string" } }, { "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["expectedRevision"], "properties": { "expectedRevision": { "type": "integer" }, "to": { "oneOf": [{ "type": "string", "format": "email" }, { "type": "array", "items": { "type": "string", "format": "email" } }] }, "cc": { "type": "array", "items": { "type": "string", "format": "email" } }, "subject": { "type": "string" }, "message": { "type": "string" } } } } } },
        "responses": { "200": { "description": "Invoice sent and delivery recorded." }, "409": { "description": "Invoice or Gmail connection is not ready." } }
      }
    },
    "/finance/invoices/{invoiceId}/pdf": {
      "get": {
        "summary": "Download a private invoice PDF",
        "description": "Stream the hash-verified current or retained invoice revision with private no-store headers.",
        "parameters": [{ "in": "path", "name": "invoiceId", "required": true, "schema": { "type": "string" } }, { "in": "query", "name": "revision", "schema": { "oneOf": [{ "type": "integer" }, { "type": "string", "const": "current" }] } }],
        "responses": { "200": { "description": "Invoice PDF.", "content": { "application/pdf": { "schema": { "type": "string", "contentEncoding": "binary" } } } }, "404": { "description": "Invoice revision not found." } }
      }
    },
    "/finance/invoices/{invoiceId}/preview": {
      "get": {
        "summary": "Preview an invoice PDF",
        "description": "Render a clearly marked, non-numbered draft preview without storing it or consuming a sequence number. For issued invoices, stream the current hash-verified immutable PDF with inline no-store headers.",
        "parameters": [{ "in": "path", "name": "invoiceId", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Inline invoice PDF preview.", "content": { "application/pdf": { "schema": { "type": "string", "contentEncoding": "binary" } } } }, "404": { "description": "Invoice not found." } }
      }
    },
    "/finance/invoice-settings": {
      "get": { "summary": "Read invoice issuer settings", "responses": { "200": { "description": "Issuer, bank, and numbering settings." } } },
      "patch": {
        "summary": "Update invoice issuer settings",
        "description": "Owner-only legal issuer, payment-destination, and numbering configuration. Issuer VAT is optional; treatment-specific customer VAT requirements still apply.",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "responses": { "200": { "description": "Invoice settings updated." }, "403": { "$ref": "#/components/responses/Forbidden" } }
      }
    },
    "/finance/exports/journal.csv": {
      "post": {
        "summary": "Export the canonical accounting journal",
        "description": "Return a bounded, deterministic UTF-8 CSV with formula-injection protection and transaction/decision provenance.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["dateFrom", "dateTo"], "properties": { "dateFrom": { "type": "string", "format": "date" }, "dateTo": { "type": "string", "format": "date" }, "accountIds": { "type": "array", "items": { "type": "string" } }, "includeTransfers": { "type": "boolean" }, "decisionStatus": { "type": "string", "enum": ["all", "coded", "human_verified"] } } } } } },
        "responses": { "200": { "description": "Accounting journal CSV.", "content": { "text/csv": { "schema": { "type": "string" } } } }, "413": { "description": "Requested export is too large." } }
      }
    },
    "/finance/exports/drive/accounts": {
      "get": {
        "summary": "Get the session Google account for Finance Drive export",
        "description": "Returns Drive readiness and the public Google Identity Services client configuration for the signed-in ONE session. The session email is authoritative and the account is not selectable. Existing matching legacy grants are accepted as a rollout fallback. Firebase user authentication is required; API keys cannot authorize, browse Drive, or invoke external writes.",
        "security": [{ "firebaseAuth": [] }],
        "responses": { "200": { "description": "Connected account capability summary." }, "403": { "$ref": "#/components/responses/Forbidden" } }
      }
    },
    "/finance/drive/authorization": {
      "post": {
        "summary": "Authorize Finance Drive access for the signed-in ONE user",
        "description": "Exchanges a Google Identity Services popup authorization code on the server, verifies the Google Drive profile email exactly matches the Firebase session email, and stores a dedicated per-user refresh token. Tokens are never returned to the browser. Requires X-Requested-With: XmlHttpRequest and an HTTPS or local-development redirect origin matching the request Origin. API keys are rejected.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["code", "redirectUri"], "properties": { "code": { "type": "string", "description": "One-time code returned by Google Identity Services." }, "redirectUri": { "type": "string", "format": "uri", "description": "Current ONE browser origin used by the popup code flow." } } } } } },
        "responses": { "200": { "description": "Session-bound Drive authorization and capability summary." }, "400": { "description": "Invalid code, in-app header, or origin." }, "403": { "description": "The Google account email differs from the signed-in ONE session or the caller is not a Firebase user." }, "409": { "description": "Google did not grant the required Drive scopes or offline refresh access." } }
      }
    },
    "/finance/drive/browser": {
      "post": {
        "summary": "Browse Google Drive export folders",
        "description": "Lists My Drive and Shared Drives, or child folders beneath one selected folder, using only the Google authorization that matches the signed-in ONE email. Access tokens remain server-side. The endpoint is read-only, supports Shared Drives, returns sanitized folder capabilities, and rejects API keys.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "googleAccountId": { "type": "string", "description": "Optional compatibility value; when supplied it must identify the Google authorization matching the signed-in ONE email." }, "folderId": { "type": "string" }, "resourceKey": { "type": "string" } } } } } },
        "responses": { "200": { "description": "Current folder, child folders, Shared Drive context, and add/list-child capabilities." }, "403": { "$ref": "#/components/responses/Forbidden" }, "409": { "description": "The connected account must be reauthorized with Drive read-only access or the folder is unavailable." } }
      }
    },
    "/finance/drive/destination/verify": {
      "post": {
        "summary": "Verify a Google Drive export destination",
        "description": "Re-reads the ONE-browser-selected folder with the session-matched Google account and requires folder MIME type plus capabilities.canAddChildren=true. Supports Shared Drives and does not change the folder.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["destinationFolderId"], "properties": { "googleAccountId": { "type": "string", "description": "Optional compatibility value; the session-matched Google account is authoritative." }, "destinationFolderId": { "type": "string" }, "destinationResourceKey": { "type": "string" } } } } } },
        "responses": { "200": { "description": "Writable folder identity and capability." }, "403": { "description": "The folder is not writable by the session account." }, "409": { "description": "The session account must be reauthorized or the folder is unavailable." } }
      }
    },
    "/finance/drive/destination/create": {
      "post": {
        "summary": "Create a Google Drive export destination folder",
        "description": "Creates exactly one new app-owned folder inside the ONE browser's selected My Drive or Shared Drive parent. Revalidates capabilities.canAddChildren before creation, verifies the new folder and parent afterward, and uses a pre-generated Drive ID plus a stable idempotency key so retries do not create duplicates. Existing Drive content is never changed.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["parentFolderId", "name", "creationId"], "properties": { "googleAccountId": { "type": "string", "description": "Optional compatibility value; the session-matched Google account is authoritative." }, "parentFolderId": { "type": "string" }, "parentResourceKey": { "type": "string" }, "name": { "type": "string", "minLength": 1, "maxLength": 120 }, "creationId": { "type": "string", "pattern": "^fdc_[A-Za-z0-9_-]{8,84}$" }, "retry": { "type": "boolean" } } } } } },
        "responses": { "201": { "description": "New or idempotently reused writable folder metadata." }, "403": { "description": "The selected parent does not permit adding children." }, "409": { "description": "Google reauthorization, parent reselection, or idempotency correction is required." } }
      }
    },
    "/finance/exports/drive": {
      "get": {
        "summary": "List Finance Drive exports",
        "description": "Returns up to 50 durable export records protected by Finance access. Optionally filter by YYYY-MM month.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "query", "name": "month", "schema": { "type": "string", "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])$" } }],
        "responses": { "200": { "description": "Finance Drive export history." } }
      },
      "post": {
        "summary": "Queue an immutable monthly Finance Drive export",
        "description": "Queues a durable background export and returns immediately with an export record to poll at GET /finance/exports/drive/{exportId}. The worker creates a new ONE-owned run beneath a ONE-browser-selected Drive or Shared Drive folder, copies verified evidence/invoice bytes, creates native ING/Wise Google Sheets with links, and never moves, deletes, overwrites, or changes pre-existing Drive content. Requires a signed-in Finance editor/owner and a stable X-Idempotency-Key.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["exportId", "month", "accountIds", "destinationFolderId"], "properties": { "exportId": { "type": "string", "pattern": "^fex_[A-Za-z0-9_-]{8,84}$" }, "month": { "type": "string", "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])$" }, "accountIds": { "type": "array", "items": { "type": "string" }, "maxItems": 100 }, "decisionStatus": { "type": "string", "enum": ["all", "coded", "human_verified"], "default": "coded" }, "includeTransfers": { "type": "boolean", "default": false }, "includeEvidence": { "type": "boolean", "default": true }, "includeRevenueInvoices": { "type": "boolean", "default": true }, "googleAccountId": { "type": "string", "description": "Optional compatibility value; the export always uses the authorization matching the signed-in ONE email." }, "destinationFolderId": { "type": "string" }, "destinationResourceKey": { "type": "string" }, "destinationName": { "type": "string" }, "rootName": { "type": "string", "default": "ONE Finance Exports - GeoTech BV" } } } } } },
        "responses": { "202": { "description": "Queued or idempotently reused export record. Poll its status until complete, partial, or failed." }, "409": { "description": "Google reauthorization, destination reselection, or idempotency correction is required." }, "413": { "description": "The monthly row or evidence-file limit was exceeded." } }
      }
    },
    "/finance/exports/drive/{exportId}": {
      "get": {
        "summary": "Get Finance Drive export status",
        "description": "Returns progress, counts, warnings, error summary, and protected Drive completion links for one export.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "exportId", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Finance Drive export record." }, "404": { "$ref": "#/components/responses/NotFound" } }
      }
    },
    "/accounting-tax/overview": {
      "get": {
        "summary": "Get the permissioned Accounting & Tax overview",
        "description": "Requires Accounting & Tax viewer or editor access. Performs one bounded Accounting & Tax root read and returns the audited balance close, account exceptions, assessment-year tax-account rollforwards, GL adjustments, tax-loss rows, last persisted book-to-tax, related-party, AP/AR ageing, treasury/fixed-asset, annual-accounts readiness, and equity/dividend decision snapshots, staged tax obligations, tax receivables, gross company debts, and restricted DGA controls. Finance remains the AP/AR and treasury system of record. This read never recalculates a snapshot, approves a distribution, or submits a statutory filing.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "query", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } }],
        "responses": {
          "200": { "description": "Accounting & Tax planning overview." },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/accounting-tax/audit-trail": {
      "get": {
        "summary": "Read the Accounting & Tax audit trail and methodology",
        "description": "Requires Accounting & Tax viewer or editor access. Performs one targeted Accounting & Tax audit-path read and returns a bounded newest-first append-only event history plus the versioned formulas, inputs, exclusions, evidence expectations, official sources, and snapshot/read contract. It never recalculates a snapshot or edits history.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [
          { "in": "query", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } },
          { "in": "query", "name": "limit", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 250, "default": 100 } }
        ],
        "responses": { "200": { "description": "Bounded immutable audit events and visible methodology." } }
      }
    },
    "/accounting-tax/audit-reviews": {
      "post": {
        "summary": "Append an immutable Accounting & Tax review",
        "description": "Requires Accounting & Tax editor access. Uses one atomic write to append a review note, question, or resolution linked to a methodology section, resource, and optional prior event. Existing history, business records, and persisted snapshots are never edited or recalculated.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxAuditReviewInput" } } } },
        "responses": { "201": { "description": "Immutable review event appended." } }
      }
    },
    "/accounting-tax/scenarios/{year}": {
      "put": {
        "summary": "Save an audited corporate-tax scenario",
        "description": "Stores the scenario inputs, actual/forecast source basis, as-of date, and workbook-validation result using exact euro cents. It atomically marks the persisted ledger bridge snapshot stale without recalculating it. Owner-only; no return is filed.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxScenarioInput" } } } },
        "responses": { "200": { "description": "Saved scenario and derived VPB calculation." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/accounting-tax/balance-closes/{year}": {
      "put": {
        "summary": "Save an audited balance-sheet close",
        "description": "Stores exact assets and equity-plus-liabilities totals, source fiscal year/basis, workbook-validation results, source-file provenance, close checks, and accountant evidence. Comparative, estimated, formula-error, or failed-validation sources cannot be adoption-ready. No statutory filing is performed.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxBalanceCloseInput" } } } },
        "responses": { "200": { "description": "Saved close and derived reconciliation readiness." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/accounting-tax/balance-close-exceptions": {
      "post": {
        "summary": "Create an audited balance-sheet exception",
        "description": "Records an account-level reconciliation or classification exception using exact debit and credit amounts.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxBalanceExceptionInput" } } } },
        "responses": { "201": { "description": "Created reconciliation exception." } }
      }
    },
    "/accounting-tax/balance-close-exceptions/{exceptionId}": {
      "patch": {
        "summary": "Update or resolve a balance-sheet exception",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "exceptionId", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxBalanceExceptionInput" } } } },
        "responses": { "200": { "description": "Updated reconciliation exception and immutable audit event." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/accounting-tax/tax-account-rollforwards": {
      "post": {
        "summary": "Create an assessment-year tax-account rollforward",
        "description": "Creates an audited rollforward for one legal entity, tax type, and assessment year. Positive signed positions are liabilities and negative positions are tax assets; unrelated tax accounts are never netted.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxRollforwardInput" } } } },
        "responses": { "201": { "description": "Created rollforward with calculated closing position and assessment reconciliation." } }
      }
    },
    "/accounting-tax/tax-account-rollforwards/{rollforwardId}": {
      "patch": {
        "summary": "Update or reconcile an assessment-year tax-account rollforward",
        "description": "Updates an audited rollforward using optimistic concurrency. Reconciled status requires a zero difference to the latest filed return or assessment plus complete source evidence.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "rollforwardId", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxRollforwardInput" } } } },
        "responses": { "200": { "description": "Updated rollforward and immutable audit event." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/accounting-tax/book-to-tax-adjustments": {
      "post": {
        "summary": "Create an audited GL-level book-to-tax adjustment",
        "description": "Creates an addition or deduction with its GL account, reason, evidence, owner, and review status. The existing snapshot is invalidated in the same atomic write; no calculation is run.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxBookToTaxAdjustmentInput" } } } },
        "responses": { "201": { "description": "Created adjustment and snapshot invalidation." } }
      }
    },
    "/accounting-tax/book-to-tax-adjustments/{adjustmentId}": {
      "patch": {
        "summary": "Update, approve, or reject a GL-level book-to-tax adjustment",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "adjustmentId", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxBookToTaxAdjustmentInput" } } } },
        "responses": { "200": { "description": "Updated adjustment and snapshot invalidation." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/accounting-tax/tax-losses": {
      "post": {
        "summary": "Create an audited tax-loss row by origin year",
        "description": "Records assessed loss, prior use, planned use, evidence, owner, and review status. The existing bridge snapshot is invalidated but not recalculated.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxLossInput" } } } },
        "responses": { "201": { "description": "Created tax-loss row and snapshot invalidation." } }
      }
    },
    "/accounting-tax/tax-losses/{taxLossId}": {
      "patch": {
        "summary": "Update or approve a tax-loss row",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "taxLossId", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxLossInput" } } } },
        "responses": { "200": { "description": "Updated tax-loss row and snapshot invalidation." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/accounting-tax/book-to-tax-bridge/{year}/refresh": {
      "post": {
        "summary": "Explicitly refresh the persisted book-to-tax bridge snapshot",
        "description": "Performs one Accounting & Tax root read, calculates from the saved scenario plus approved GL adjustments and tax-loss rows, then performs one atomic multi-location write for the snapshot, audit event, and invalidation removal. Page reads never invoke this operation.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } }],
        "responses": { "200": { "description": "Persisted bridge snapshot." } }
      }
    },
    "/accounting-tax/related-party-reconciliations": {
      "post": {
        "summary": "Create a related-party or current-account GL reconciliation",
        "description": "Links a fiscal-year GL control to an existing BV lending facility or shareholder current account. The existing related-party snapshot is marked stale in the same atomic write and is not recalculated.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxRelatedPartyReconciliationInput" } } } },
        "responses": { "201": { "description": "Created reconciliation control and snapshot invalidation." } }
      }
    },
    "/accounting-tax/related-party-reconciliations/{year}/{reconciliationId}": {
      "patch": {
        "summary": "Update, approve, or resolve a related-party reconciliation",
        "description": "Updates the linked GL, interest, agreement, counterparty-confirmation, tax-classification, and difference-resolution evidence using optimistic concurrency. The persisted snapshot is invalidated but not recalculated.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [
          { "in": "path", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } },
          { "in": "path", "name": "reconciliationId", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxRelatedPartyReconciliationInput" } } } },
        "responses": { "200": { "description": "Updated reconciliation control and snapshot invalidation." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/accounting-tax/related-party-snapshot/{year}/refresh": {
      "post": {
        "summary": "Explicitly refresh the persisted related-party reconciliation snapshot",
        "description": "Performs one Accounting & Tax root read, joins approved GL controls to the existing lending/current-account register and movements, calculates ledger, interest, and reciprocal-balance differences, then performs one atomic snapshot/audit write. Page reads never invoke this operation.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } }],
        "responses": { "200": { "description": "Persisted related-party reconciliation snapshot." } }
      }
    },
    "/accounting-tax/open-item-controls": {
      "post": {
        "summary": "Create an AP/AR ageing reconciliation control",
        "description": "Creates a fiscal-year overlay for an existing Finance bill/invoice, or a standalone supplier/customer credit or accrued payable/receivable. Finance remains the invoice system of record. The saved ageing snapshot is marked stale in the same atomic write and is not recalculated.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxOpenItemControlInput" } } } },
        "responses": { "201": { "description": "Created open-item control and snapshot invalidation." } }
      }
    },
    "/accounting-tax/open-item-controls/{year}/{controlId}": {
      "patch": {
        "summary": "Update an AP/AR ageing reconciliation control",
        "description": "Updates as-of credits/payments, FX, dispute, owner, evidence, or review data using optimistic concurrency. The saved snapshot becomes stale and is not recalculated.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [
          { "in": "path", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } },
          { "in": "path", "name": "controlId", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxOpenItemControlInput" } } } },
        "responses": { "200": { "description": "Updated open-item control and snapshot invalidation." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/accounting-tax/open-item-ageing/{year}/refresh": {
      "post": {
        "summary": "Explicitly refresh the persisted AP/AR ageing snapshot",
        "description": "Performs three targeted reads—Accounting & Tax controls, Finance bills, and Finance invoices—calculates historical open items for the requested as-of date, and performs one atomic snapshot/audit write. Page reads never invoke this operation. Gross payables, supplier credits, accruals, and receivables remain separately reported.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["asOfDate"], "properties": { "asOfDate": { "type": "string", "format": "date" } } } } } },
        "responses": { "200": { "description": "Persisted AP/AR ageing snapshot." } }
      }
    },
    "/accounting-tax/treasury-controls": {
      "post": {
        "summary": "Create a treasury GL and FX reconciliation control",
        "description": "Links year-end GL, closing-rate, accrued-interest, book profit/loss, Dutch corporate-tax treatment, owner, and evidence controls to an existing Finance deposit, investment, or non-EUR operating account. Ordinary deposit, portfolio, and FX results are recorded as already included in accounting profit; qualifying participation results can suggest a book-to-tax bridge adjustment. Finance remains the system of record and the persisted snapshot is only marked stale.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxTreasuryControlInput" } } } },
        "responses": { "201": { "description": "Created treasury control and snapshot invalidation." } }
      }
    },
    "/accounting-tax/treasury-controls/{year}/{controlId}": {
      "patch": {
        "summary": "Update a treasury GL and FX reconciliation control",
        "description": "Updates or approves an audited Finance-account reconciliation and corporate-tax overlay with optimistic concurrency without editing Finance or recalculating the snapshot.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } }, { "in": "path", "name": "controlId", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxTreasuryControlInput" } } } },
        "responses": { "200": { "description": "Updated treasury control and snapshot invalidation." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/accounting-tax/fixed-assets": {
      "post": {
        "summary": "Create a fixed-asset reconciliation row",
        "description": "Creates an audited fixed-asset and straight-line depreciation control inside Accounting & Tax. The snapshot compares commercial depreciation with the ordinary Dutch fiscal maximum of 20% of original acquisition cost per year. Finance has no fixed-asset register and remains unchanged.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxFixedAssetInput" } } } },
        "responses": { "201": { "description": "Created fixed asset and snapshot invalidation." } }
      }
    },
    "/accounting-tax/fixed-assets/{year}/{assetId}": {
      "patch": {
        "summary": "Update a fixed-asset reconciliation row",
        "description": "Updates or approves asset, depreciation, impairment, GL, owner, and evidence controls with optimistic concurrency; marks the saved snapshot stale.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } }, { "in": "path", "name": "assetId", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxFixedAssetInput" } } } },
        "responses": { "200": { "description": "Updated fixed asset and snapshot invalidation." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/accounting-tax/treasury-assets/{year}/refresh": {
      "post": {
        "summary": "Explicitly refresh the treasury and fixed-asset reconciliation snapshot",
        "description": "Performs four bounded reads—Accounting & Tax, Finance accounts, valuations, and account summaries—then one atomic snapshot/audit write. It persists treasury book results and their corporate-tax treatment without double-counting ordinary taxable income, suggests participation-exemption bridge adjustments, and applies the ordinary 20% annual fiscal-depreciation cap. Page reads never invoke this operation and Finance data is never changed.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["asOfDate"], "properties": { "asOfDate": { "type": "string", "format": "date" } } } } } },
        "responses": { "200": { "description": "Persisted treasury, FX, investment, and fixed-asset snapshot." } }
      }
    },
    "/accounting-tax/annual-accounts/{year}": {
      "put": {
        "summary": "Save the annual-accounts and KVK filing-readiness control",
        "description": "Creates or updates audited year-specific annual-accounts preparation, two-year business-class evidence, extension, signature and adoption dates, electronic KVK/SBR filing channel, taxonomy validation, accountant evidence, and external filing receipt. The saved readiness snapshot is marked stale; this operation never submits to KVK or Digipoort.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxAnnualAccountsInput" } } } },
        "responses": { "200": { "description": "Saved annual-accounts filing control and readiness invalidation." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/accounting-tax/annual-accounts-readiness/{year}/refresh": {
      "post": {
        "summary": "Explicitly refresh annual-accounts filing readiness",
        "description": "Performs exactly one bounded Accounting & Tax root read, evaluates the saved Priority 1-6 snapshots plus annual-accounts controls, calculates the BV preparation/adoption/8-day filing deadlines capped at 12 months, and performs one atomic readiness-snapshot/audit write. Page entry never recalculates and this route never submits a statutory filing.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } }],
        "requestBody": { "required": false, "content": { "application/json": { "schema": { "type": "object", "additionalProperties": false } } } },
        "responses": { "200": { "description": "Persisted annual-accounts filing-readiness snapshot." } }
      }
    },
    "/accounting-tax/equity-positions/{year}": {
      "put": {
        "summary": "Save the legal-equity position for dividend decisions",
        "description": "Creates or updates the fiscal-year equity composition, reserves required by law or the articles, exact ledger reconciliation, articles review, shareholder register, owner, and evidence. The saved equity-and-dividend snapshot is atomically marked stale; this operation never authorizes a distribution.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxEquityPositionInput" } } } },
        "responses": { "200": { "description": "Saved equity position and decision-snapshot invalidation." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/accounting-tax/dividend-decisions": {
      "post": {
        "summary": "Create an equity and dividend decision row",
        "description": "Records the proposed distribution, beneficiary and ownership, shareholder resolution, interim articles authority, Article 2:216 board approval, forward-looking liquidity, withholding, availability/payment, and dividend-tax evidence. It does not approve, pay, or file the distribution.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxDividendDecisionInput" } } } },
        "responses": { "201": { "description": "Created dividend decision and snapshot invalidation." } }
      }
    },
    "/accounting-tax/dividend-decisions/{year}/{decisionId}": {
      "patch": {
        "summary": "Update an equity and dividend decision row",
        "description": "Updates decision, board, liquidity, withholding, or filing evidence with optimistic concurrency and atomically marks the saved snapshot stale.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [
          { "in": "path", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } },
          { "in": "path", "name": "decisionId", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxDividendDecisionInput" } } } },
        "responses": { "200": { "description": "Updated dividend decision and snapshot invalidation." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/accounting-tax/equity-dividend/{year}/refresh": {
      "post": {
        "summary": "Explicitly refresh equity and dividend decision support",
        "description": "Performs exactly one bounded Accounting & Tax root read, calculates distributable equity, aggregate active distributions, the statutory balance test, board payment-capacity test, authorization, withholding, one-month tax follow-up, and DGA-plan difference, then performs one atomic snapshot/audit write. Page entry only reuses the saved result.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } }],
        "requestBody": { "required": false, "content": { "application/json": { "schema": { "type": "object", "additionalProperties": false } } } },
        "responses": { "200": { "description": "Persisted equity-and-dividend decision snapshot." } }
      }
    },
    "/accounting-tax/forecasts/{year}/refresh": {
      "post": {
        "summary": "Explicitly refresh the Finance-derived corporate-tax forecast",
        "description": "Requires Accounting & Tax editor access. Reads the selected fiscal year's Finance ledger forecast, applies the saved corporate-tax scenario and versioned calculation, and persists one audited deterministic snapshot. This route never files a return and does not provide tax advice.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } }],
        "requestBody": { "required": false, "content": { "application/json": { "schema": { "type": "object", "additionalProperties": false } } } },
        "responses": { "200": { "description": "Persisted Finance-derived corporate-tax forecast." } }
      }
    },
    "/accounting-tax/dga/{year}": {
      "put": {
        "summary": "Save restricted DGA planning controls",
        "description": "Stores customary-salary, shareholder current-account, connected borrowing, planned dividend, withholding, and indicative Box 2 inputs. Owner-only and not a personal tax filing.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "year", "required": true, "schema": { "type": "integer", "enum": [2025, 2026] } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true } } } },
        "responses": { "200": { "description": "Saved DGA controls and derived indicators." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/accounting-tax/obligations": {
      "post": {
        "summary": "Create a staged tax obligation",
        "description": "Creates an audited payable or receivable while preserving estimate, provision, filing, assessment, and settlement amounts separately.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxObligationInput" } } } },
        "responses": { "201": { "description": "Created obligation." } }
      }
    },
    "/accounting-tax/obligations/{obligationId}": {
      "patch": {
        "summary": "Update a staged tax obligation",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "obligationId", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxObligationInput" } } } },
        "responses": { "200": { "description": "Updated obligation." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/accounting-tax/debts": {
      "post": {
        "summary": "Create a gross company-debt record",
        "description": "Creates an audited liability record. Debt totals are never offset against tax assets or receivables.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxDebtInput" } } } },
        "responses": { "201": { "description": "Created company debt." } }
      }
    },
    "/accounting-tax/debts/{debtId}": {
      "patch": {
        "summary": "Update a gross company-debt record",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "debtId", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxDebtInput" } } } },
        "responses": { "200": { "description": "Updated company debt." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/accounting-tax/loans": {
      "post": {
        "summary": "Create an audited BV lending facility",
        "description": "Requires Accounting & Tax editor access. Creates an audited UBO, employee, external-person, or external-company loan. Tracks agreed facility, cumulative disbursements, outstanding principal, accrued interest, arm's-length rate review, repayment structure, and Dutch Box 2 treatment.",
        "security": [{ "firebaseAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxLoanInput" } } } },
        "responses": { "201": { "description": "Created BV lending record with derived interest and payment amounts." } }
      }
    },
    "/accounting-tax/loans/{loanId}": {
      "patch": {
        "summary": "Update BV lending terms and review metadata",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "loanId", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxLoanInput" } } } },
        "responses": { "200": { "description": "Updated BV lending record." }, "409": { "description": "The expected revision is stale." } }
      },
      "delete": {
        "summary": "Delete an active BV lending record",
        "description": "Removes the loan from active Accounting & Tax totals after exact borrower-name and revision confirmation. The archived loan, its movement history, deleting actor, and audit event remain preserved.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "loanId", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxLoanDeleteInput" } } } },
        "responses": { "200": { "description": "Loan removed from the active register with preserved history." }, "400": { "description": "Borrower confirmation does not match." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/accounting-tax/loans/{loanId}/movements": {
      "post": {
        "summary": "Record an audited BV loan movement",
        "description": "Records a drawdown, principal repayment, interest charge, or interest payment. Drawdowns increase cumulative disbursements and may explicitly extend the agreed facility.",
        "security": [{ "firebaseAuth": [] }],
        "parameters": [{ "in": "path", "name": "loanId", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountingTaxLoanMovementInput" } } } },
        "responses": { "201": { "description": "Recorded movement, updated balances, and immutable audit event." }, "409": { "description": "The expected revision is stale." } }
      }
    },
    "/finance/forecast/view": {
      "post": {
        "summary": "Calculate the Finance cash forecast",
        "description": "Return deterministic actual cash history plus a 13-week, 12-month, or custom 1-to-60-month future cash outlook calculated only from dated Finance cash events, issued Accounts Receivable, and approved Accounts Payable. Pending Accounts Payable remains separate non-cash exposure. The response also includes scenario paths, historical category context, FX provenance, and data-quality warnings. Requires finance:read, read, or write scope, or a Firebase user with Finance access.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FinanceCashForecastRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculated cash outlook.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FinanceCashForecastResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "description": "Required exchange-rate coverage is unavailable."
          }
        }
      }
    },
    "/finance/forecast/events": {
      "post": {
        "summary": "Create a planned Finance cash event",
        "description": "Create a retry-safe planned inflow or outflow. Requires finance:write or write scope, or a Firebase user with Finance access.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "parameters": [
          {
            "in": "header",
            "name": "X-Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 160
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FinanceCashPlanCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Cash plan created or an idempotent retry returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FinanceCashPlanMutationResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/finance/forecast/events/{eventId}": {
      "patch": {
        "summary": "Update, archive, or restore a Finance cash plan",
        "description": "Patch one cash plan using expectedUpdatedAt for optimistic concurrency. Requires finance:write or write scope, or a Firebase user with Finance access.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "eventId",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FinanceCashPlanUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cash plan updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FinanceCashPlanMutationResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The plan changed after the supplied revision."
          }
        }
      }
    },
    "/finance/forecast/settings": {
      "put": {
        "summary": "Update Finance cash forecast settings",
        "description": "Update the global minimum-cash threshold and default cash scope/horizon with optimistic concurrency. Requires finance:write or write scope, or a Firebase user with Finance access.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FinanceCashForecastSettingsUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Forecast settings updated."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "409": {
            "description": "The settings changed after the supplied revision."
          }
        }
      }
    },
    "/finance/investment-portfolios": {
      "post": {
        "summary": "Record a reconciled investment portfolio snapshot",
        "description": "Save executed positions, cost basis, available brokerage cash, disclosed purchase costs, annual ING/fund costs, and estimated sale costs. Position values plus other items must reconcile to investedValueMinor; invested value plus available cash must reconcile to balanceMinor. Flow includes only available cash, while optional estimated ING service costs can be forecast as cash spending. Requires finance:write or write scope, or a Firebase user with Finance access.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "accountId",
                  "date",
                  "currency",
                  "balanceMinor",
                  "investedValueMinor",
                  "availableCashMinor",
                  "positions"
                ],
                "properties": {
                  "accountId": {
                    "type": "string",
                    "example": "ing-investment"
                  },
                  "date": {
                    "type": "string",
                    "format": "date"
                  },
                  "currency": {
                    "type": "string",
                    "pattern": "^[A-Z]{3}$"
                  },
                  "balanceMinor": {
                    "type": "string",
                    "pattern": "^\\d+$"
                  },
                  "investedValueMinor": {
                    "type": "string",
                    "pattern": "^\\d+$"
                  },
                  "availableCashMinor": {
                    "type": "string",
                    "pattern": "^\\d+$"
                  },
                  "forecastAnnualCashCosts": {
                    "type": "boolean",
                    "description": "Project estimated ING cash service costs in Flow. Fund costs remain embedded in NAV."
                  },
                  "sourceNote": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "positions": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 100,
                    "items": {
                      "type": "object",
                      "required": [
                        "name",
                        "units",
                        "currency",
                        "currentPrice",
                        "currentValueMinor",
                        "costBasisMinor",
                        "costs"
                      ],
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "isin": {
                          "type": "string",
                          "pattern": "^[A-Z0-9]{12}$"
                        },
                        "symbol": {
                          "type": "string"
                        },
                        "role": {
                          "type": "string"
                        },
                        "units": {
                          "type": "string"
                        },
                        "currency": {
                          "type": "string"
                        },
                        "currentPrice": {
                          "type": "string"
                        },
                        "averagePurchasePrice": {
                          "type": "string"
                        },
                        "currentValueMinor": {
                          "type": "string",
                          "pattern": "^\\d+$"
                        },
                        "costBasisMinor": {
                          "type": "string",
                          "pattern": "^\\d+$"
                        },
                        "costs": {
                          "type": "object",
                          "required": [
                            "purchaseCostStatus",
                            "saleCostStatus"
                          ],
                          "description": "Disclosed or estimated purchase costs, annual ING/fund cost rates in basis points, and estimated sale costs."
                        }
                      }
                    }
                  },
                  "otherItems": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Investment portfolio snapshot saved and Finance recalculated."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/finance/market-quotes": {
      "get": {
        "summary": "Read delayed market prices for approved investment positions",
        "description": "Resolve approved portfolio ISIN mappings and return delayed Yahoo Finance prices. Quote failures are returned per position so clients can retain the latest ING statement price. Requires finance:read, read, or write scope, or a Firebase user with Finance access.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "isins",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated list of up to 20 security ISINs."
          },
          {
            "in": "query",
            "name": "isin",
            "required": false,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "pattern": "^[A-Z0-9]{12}$"
              }
            },
            "style": "form",
            "explode": true,
            "description": "Repeated ISIN query parameter. Use either isin or isins."
          }
        ],
        "responses": {
          "200": {
            "description": "Delayed quotes and per-position availability.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "source": {
                      "type": "string",
                      "example": "Yahoo Finance delayed quotes"
                    },
                    "fetchedAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "quotes": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "status",
                          "isin"
                        ],
                        "properties": {
                          "status": {
                            "type": "string",
                            "enum": [
                              "available",
                              "unavailable"
                            ]
                          },
                          "isin": {
                            "type": "string"
                          },
                          "symbol": {
                            "type": "string"
                          },
                          "currency": {
                            "type": "string"
                          },
                          "price": {
                            "type": "string"
                          },
                          "previousClose": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "dayChange": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "dayChangePercent": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "dayLow": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "dayHigh": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "fiftyTwoWeekLow": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "fiftyTwoWeekHigh": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "marketTime": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "fetchedAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "delayed": {
                            "type": "boolean"
                          },
                          "provider": {
                            "type": "string"
                          },
                          "providerUrl": {
                            "type": "string",
                            "format": "uri"
                          },
                          "error": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/finance/investment-cash": {
      "post": {
        "summary": "Record available cash in an investment account",
        "description": "Record an absolute, dated uninvested cash balance in minor units. Preserves the latest holdings and cost disclosures at that date. Total account value is invested assets plus cash; only cash enters liquid Flow. Does not create a deposit, trade or transaction. Repeating the same account, date and amount does not duplicate history. Uses the same bounded valuation write and Finance editor authorization as /finance/balances.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "accountId",
                  "date",
                  "availableCashMinor"
                ],
                "properties": {
                  "accountId": {
                    "type": "string",
                    "enum": [
                      "ing-investment"
                    ]
                  },
                  "date": {
                    "type": "string",
                    "format": "date"
                  },
                  "availableCashMinor": {
                    "type": "string",
                    "pattern": "^\\d{1,17}$",
                    "description": "Absolute cash balance, including zero; not an increment."
                  },
                  "currency": {
                    "type": "string",
                    "enum": [
                      "EUR"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Cash balance recorded; response includes balance and bounded-write diagnostics."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/finance/balances": {
      "post": {
        "summary": "Record a dated Bank account balance",
        "description": "Record or replace one dated account balance through a bounded valuation-only write that does not load or reconcile the full Finance transaction history. Investment accounts require investedValueMinor and availableCashMinor, and those components must add up to balanceMinor. Requires finance:write or write scope, or a Firebase user with current Finance editor access.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "accountId",
                  "date",
                  "currency",
                  "balanceMinor"
                ],
                "properties": {
                  "accountId": {
                    "type": "string",
                    "maxLength": 120,
                    "example": "ing-eur"
                  },
                  "date": {
                    "type": "string",
                    "format": "date"
                  },
                  "currency": {
                    "type": "string",
                    "pattern": "^[A-Z]{3}$"
                  },
                  "balanceMinor": {
                    "type": "string",
                    "pattern": "^-?\\d+$",
                    "description": "Signed integer minor units. Credit-card debt may be negative."
                  },
                  "investedValueMinor": {
                    "type": "string",
                    "pattern": "^\\d+$",
                    "description": "Required for investment accounts."
                  },
                  "availableCashMinor": {
                    "type": "string",
                    "pattern": "^\\d+$",
                    "description": "Required for investment accounts; this is the component included in Flow."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The dated balance was created, updated, or already unchanged.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "accountId",
                    "balance",
                    "updatedAt"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "accountId": {
                      "type": "string"
                    },
                    "balance": {
                      "type": "object",
                      "properties": {
                        "id": { "type": "string" },
                        "accountId": { "type": "string" },
                        "date": { "type": "string", "format": "date" },
                        "currency": { "type": "string" },
                        "valueMinor": { "type": "string" },
                        "investedValueMinor": { "type": "string" },
                        "availableCashMinor": { "type": "string" },
                        "status": { "type": "string", "enum": ["created", "updated", "unchanged"] }
                      }
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "diagnostics": {
                      "type": "object",
                      "description": "Includes mutationMode=valuation_patch and bounded database-read/update counts."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "description": "The bounded Finance valuation store is temporarily unavailable."
          }
        }
      }
    },
    "/finance/balance-screenshots": {
      "post": {
        "summary": "Recognize and save account balances from a bank screenshot",
        "description": "Validate a transient direct ING account, ING credit-card, or Wise screenshot, use Gemini to extract independently held current balances, deterministically match known Finance accounts, and add dated balance snapshots. ING investment Belegd/Gelddeel values are stored as investedValueMinor and availableCashMinor on one reconciled total, and only availableCashMinor enters cash forecasts. Credit cards use Current balance only (including zero), reject available credit, limits, and statement values, and normalize displayed debt as a negative cash position. The raw screenshot is never stored. Requires finance:write or write scope, or a Firebase user with Finance access.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "parameters": [
          {
            "in": "header",
            "name": "X-File-Name",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 180
            }
          },
          {
            "in": "header",
            "name": "X-Balance-Date",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Optional as-of date. Defaults to a visible screenshot date or the current UTC date."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "image/jpeg": {
              "schema": {
                "type": "string",
                "contentEncoding": "binary"
              }
            },
            "image/png": {
              "schema": {
                "type": "string",
                "contentEncoding": "binary"
              }
            },
            "image/webp": {
              "schema": {
                "type": "string",
                "contentEncoding": "binary"
              }
            },
            "image/tiff": {
              "schema": {
                "type": "string",
                "contentEncoding": "binary"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Recognized matches saved or returned unchanged for an idempotent same-day retry.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "asOfDate": {
                      "type": "string",
                      "format": "date"
                    },
                    "model": {
                      "type": "string"
                    },
                    "rawScreenshotStored": {
                      "type": "boolean",
                      "const": false
                    },
                    "applied": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "accountId": {
                            "type": "string"
                          },
                          "date": {
                            "type": "string",
                            "format": "date"
                          },
                          "currency": {
                            "type": "string"
                          },
                          "balanceMinor": {
                            "type": "string"
                          },
                          "investedValueMinor": {
                            "type": "string",
                            "description": "Investment-account securities value when a complete allocation was recognized."
                          },
                          "availableCashMinor": {
                            "type": "string",
                            "description": "Investment-account uninvested cash included in cash forecasts when a complete allocation was recognized."
                          },
                          "status": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "skipped": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "415": {
            "description": "The upload is not a supported image."
          },
          "422": {
            "description": "The screen is not a direct ING/Wise UI or no unambiguous balance could be matched."
          },
          "502": {
            "description": "Gemini recognition failed."
          }
        }
      }
    },
    "/finance/view": {
      "post": {
        "summary": "Search a bounded Finance transaction view",
        "description": "Return up to 500 filtered transactions, including the compact evidenceCount used by AssistHub to match a scan before upload. Requires finance:read or a Firebase user with Finance access.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FinanceViewRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Filtered Finance transaction window.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FinanceViewResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/finance/fin-results/preview": {
      "post": {
        "summary": "Validate a Fin Results CSV before import",
        "description": "Validate the Bank26 Fin Results schema, normalize rows in memory, deterministically match existing bank transactions, and preview safe legacy-category mappings. This endpoint performs no database write and requires a Firebase user with Finance access.",
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FinanceFinResultsFileRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Validated Fin Results matching and mapping summary."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/finance/fin-results/import": {
      "post": {
        "summary": "Import Fin Results as review evidence",
        "description": "Append normalized Fin Results rows, hashes, deterministic matches, and category-mapping evidence without creating, replacing, or deleting canonical bank transactions or Manual Decisions. Exact reimports are idempotent. Requires a Firebase user with Finance access.",
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FinanceFinResultsFileRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Fin Results review evidence imported or already present."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/finance/fin-results/transactions/{transactionId}/review": {
      "parameters": [
        {
          "name": "transactionId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "post": {
        "summary": "Confirm or withdraw one Fin Results mapping",
        "description": "A human confirmation applies the safely mapped economic category as an approved Manual Decision while preserving project allocations. Import alone never approves a decision. Withdrawal retains both the current Manual Decision and append-only confirmation history. Requires a Firebase user with Finance access.",
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "rowId": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean",
                    "default": true
                  }
                },
                "required": [
                  "rowId",
                  "active"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Fin Results review recorded; confirmation may also apply a Manual Decision."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The Fin Results match changed or has no safe category mapping."
          }
        }
      }
    },
    "/finance/transactions/{transactionId}/evidence": {
      "parameters": [
        {
          "name": "transactionId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "summary": "List private Finance evidence",
        "description": "List receipt/invoice metadata and authenticated API download paths. Storage paths and public URLs are never returned. Requires finance:evidence:read or a Firebase user with Finance access.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Evidence metadata for the transaction.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FinanceEvidenceListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "post": {
        "summary": "Upload private Finance evidence",
        "description": "Upload one raw PDF or supported image body, up to 20 MB. Requires finance:evidence:write or a Firebase user with Finance access. Send a stable X-Idempotency-Key so retries reuse the same record; reusing the key with different bytes returns 409.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-File-Name",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 180
            }
          },
          {
            "name": "X-Evidence-Type",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "receipt",
                "invoice",
                "other"
              ]
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 180
            }
          },
          {
            "name": "X-Source-Reference",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 180
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/pdf": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/jpeg": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/png": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/webp": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/tiff": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/heif": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Evidence stored or idempotently reused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FinanceEvidenceWriteResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "File limit reached or idempotency key reused with different bytes."
          },
          "413": {
            "description": "Evidence file exceeds 20 MB."
          }
        }
      }
    },
    "/finance/transactions/{transactionId}/evidence/{evidenceId}": {
      "parameters": [
        {
          "name": "transactionId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        },
        {
          "name": "evidenceId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "summary": "Preview or download private Finance evidence",
        "description": "Stream the original private PDF/image with no-store headers. Requires finance:evidence:read or a Firebase user with Finance access.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Original evidence bytes.",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/tiff": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/heif": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "summary": "Delete one private Finance evidence file",
        "description": "Permanently remove only the selected evidence object and metadata. The transaction, imports, decisions, and other evidence are preserved. Requires finance:evidence:write or a Firebase user with Finance access.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Evidence deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FinanceEvidenceDeleteResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/finance/categorization/retrieve": {
      "post": {
        "summary": "Match Finance transactions from vector memory",
        "description": "Page through uncategorized transactions in the supplied Finance filters, create transient query embeddings, and deterministically match only unambiguous exact history or strong multi-example vector consensus from current human-approved decision links. No categorization LLM is called. Results are saved as pending AI-provenance decisions for human review. Large, cash-treatment, Project, Payroll, allocation, weak, and conflicting matches abstain.",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "geoCrmKey": []
          },
          {
            "firebaseAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "filters": {
                    "type": "object"
                  },
                  "cursor": {
                    "type": "string",
                    "maxLength": 240
                  },
                  "limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 20,
                    "default": 20
                  },
                  "idempotencyKey": {
                    "type": "string",
                    "maxLength": 160
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "One bounded retrieval page with applied pending decisions, abstentions, and an optional continuation cursor."
          }
        }
      }
    },
    "/finance/categorization/retrieval-settings": {
      "post": {
        "summary": "Get Finance embedding and retrieval settings",
        "description": "Return immutable embedding identity, conservative defaults, allowed ranges, saved retrieval-quality controls, and update audit metadata. Requires finance:read or an authenticated Finance user.",
        "responses": {
          "200": {
            "description": "Current Finance retrieval settings and embedding identity."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/finance/categorization/retrieval-settings/update": {
      "post": {
        "summary": "Update Finance retrieval-quality settings",
        "description": "Persist one validated, audited global settings record used by both website vector retrieval and future MCP categorization contexts. Embedding model, dimensions, index version, and namespace remain immutable. Requires finance:apply API scope or Firebase owner access.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "settings"
                ],
                "properties": {
                  "settings": {
                    "type": "object",
                    "required": [
                      "minimumSemanticSimilarity",
                      "requiredSemanticExamples",
                      "semanticConflictMargin",
                      "minimumCorrectionSimilarity",
                      "requiredCorrectionExamples"
                    ],
                    "properties": {
                      "minimumSemanticSimilarity": {
                        "type": "number",
                        "minimum": 0.75,
                        "maximum": 0.95,
                        "default": 0.82
                      },
                      "requiredSemanticExamples": {
                        "type": "integer",
                        "minimum": 2,
                        "maximum": 5,
                        "default": 2
                      },
                      "semanticConflictMargin": {
                        "type": "number",
                        "minimum": 0.02,
                        "maximum": 0.15,
                        "default": 0.05
                      },
                      "minimumCorrectionSimilarity": {
                        "type": "number",
                        "minimum": 0.85,
                        "maximum": 0.98,
                        "default": 0.9
                      },
                      "requiredCorrectionExamples": {
                        "type": "integer",
                        "minimum": 2,
                        "maximum": 5,
                        "default": 2
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved Finance retrieval settings and update audit metadata."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/finance/categorization/vector-memory/stats": {
      "post": {
        "summary": "Get Finance vector-memory stats",
        "description": "Return the active embedding namespace, model, dimensions, vector count, and latest operation. Requires finance:read or an authenticated Finance user.",
        "responses": {
          "200": {
            "description": "Current Finance vector-memory statistics."
          }
        }
      }
    },
    "/finance/categorization/vector-memory/sync": {
      "post": {
        "summary": "Sync Finance vector memory",
        "description": "Create or reuse embeddings for explicit human-approved transactions or one bounded YYYY-MM page with finance:suggest. With exactly one transaction ID and replaceExisting=true, remove its previous decision vector/link revisions and generate a fresh replacement; this mode requires finance:apply. Authenticated Finance users may use either mode.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "transactionIds": {
                    "type": "array",
                    "maxItems": 100,
                    "items": {
                      "type": "string"
                    }
                  },
                  "month": {
                    "type": "string",
                    "pattern": "^\\d{4}-(0[1-9]|1[0-2])$"
                  },
                  "cursor": {
                    "type": "string",
                    "maxLength": 240
                  },
                  "limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100
                  },
                  "replaceExisting": {
                    "type": "boolean",
                    "description": "Replace vector memory for exactly one transaction ID."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Embedding sync counts and optional month-page cursor."
          }
        }
      }
    },
    "/finance/categorization/vector-memory/clear": {
      "post": {
        "summary": "Clear Finance vector memory",
        "description": "Remove all generated embeddings and vector links while preserving Finance source data and reset audit history. Requires finance:apply or Firebase owner access.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirmation": {
                    "type": "string",
                    "enum": [
                      "CLEAR EMBEDDINGS"
                    ]
                  }
                },
                "required": [
                  "confirmation"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Embedding reset summary."
          },
          "400": {
            "description": "The exact destructive confirmation was not supplied."
          }
        }
      }
    },
    "/me/agent-keys": {
      "get": {
        "summary": "List personal agent keys",
        "description": "Firebase-authenticated. Returns the signed-in user's personal keys and last-used metadata without secrets.",
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Personal agent keys."
          }
        }
      },
      "post": {
        "summary": "Create a personal agent key",
        "description": "Firebase-authenticated. Returns the durable secret once. mode defaults to assigned_tasks for the existing assigned-task contract; member_mcp creates a 90-day key that re-evaluates the owner's live ONE role and grants on every request.",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": { "type": "string", "maxLength": 120 },
                  "mode": { "type": "string", "enum": ["assigned_tasks", "member_mcp"], "default": "assigned_tasks" }
                }
              }
            }
          }
        },
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "responses": {
          "201": {
            "description": "Personal key and one-time secret."
          }
        }
      }
    },
    "/me/agent-keys/{keyId}": {
      "delete": {
        "summary": "Revoke a personal agent key",
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "parameters": [
          {
            "name": "keyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Personal key revoked."
          }
        }
      }
    },
    "/me/work": {
      "get": {
        "summary": "Get My Work",
        "description": "Firebase user or personal-key endpoint returning validated current focus and open assignments across permitted active projects. Internal accounts receive company-wide active-internal team focus; project-only accounts remain restricted to permitted projects. Set includeCompleted=true to page through both open and completed current assignments while the compatibility assignments field remains open-only.",
        "parameters": [
          {
            "name": "includeCompleted",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Page size for allAssignments when includeCompleted is true.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Opaque allAssignments cursor returned by the prior page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cross-project work dashboard data."
          }
        }
      }
    },
    "/me/focus": {
      "get": {
        "summary": "Get current focus tasks",
        "description": "Returns only the calling Firebase user's or personal-key owner's validated focus tasks, limited to one task per project. Service keys are rejected. The legacy focus field contains the most recently updated entry and focuses contains the complete list.",
        "responses": {
          "200": {
            "description": "Validated current focus tasks."
          }
        }
      },
      "put": {
        "summary": "Set current focus",
        "description": "Sets focus only for the calling Firebase user or the owner of the calling personal key. The task must be assigned to that same person and must not be Done. Setting focus replaces only that person's current task for the same project; callers cannot nominate focus for another person.",
        "responses": {
          "200": {
            "description": "Current focus set."
          }
        }
      },
      "delete": {
        "summary": "Clear current focus",
        "description": "Clears only the calling person's own focus. Supply both boardId and projectId to clear one project's focus. Omit both to clear every focus task for that person.",
        "parameters": [
          {
            "name": "boardId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "projectId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current focus cleared."
          }
        }
      }
    },
    "/team-focus": {
      "get": {
        "summary": "List visible team focus",
        "description": "With no filters, active internal accounts receive validated focus for active internal people across active Project Tracker projects; project-only callers remain permission-scoped. A board-only filter preserves legacy permission-scoped behavior. An exact boardId and projectId requires project read access and may include active project-only participants assigned in that project.",
        "parameters": [
          {
            "name": "boardId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "projectId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Validated team focus records for the requested scope."
          }
        }
      }
    },
    "/boards/{boardId}/projects/{projectId}/source-control": {
      "patch": {
        "summary": "Update a project's source-control configuration",
        "description": "Firebase-authenticated project-editor endpoint. Stores one GitHub repository or one Perforce configuration with multiple depot paths, but no connector credentials.",
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ProjectId"
          }
        ],
        "responses": {
          "200": {
            "description": "Source-control configuration updated."
          },
          "400": {
            "description": "More than one source-control configuration was supplied."
          },
          "403": {
            "description": "Project editor access is required."
          }
        }
      }
    },
    "/webhooks/github": {
      "post": {
        "summary": "Receive GitHub source events",
        "description": "Requires a valid X-Hub-Signature-256. Tracks branch, commit, and pull-request metadata without accepting diffs or file content.",
        "security": [],
        "responses": {
          "202": {
            "description": "GitHub event accepted."
          }
        }
      }
    },
    "/source-events/perforce": {
      "post": {
        "summary": "Ingest sanitized Perforce changelist metadata",
        "description": "Service-key endpoint for pending, shelved, or submitted changelists. File contents and diffs are not accepted.",
        "responses": {
          "202": {
            "description": "Perforce events accepted."
          }
        }
      }
    },
    "/boards/{boardId}/projects/{projectId}/tasks/{taskId}/automation/undo": {
      "post": {
        "summary": "Undo the latest AI-managed task values",
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ProjectId"
          },
          {
            "$ref": "#/components/parameters/TaskId"
          }
        ],
        "responses": {
          "200": {
            "description": "AI-managed values restored."
          }
        }
      }
    },
    "/boards/{boardId}/projects/{projectId}/tasks/{taskId}/automation/suggestions/{fingerprint}/{decision}": {
      "post": {
        "summary": "Accept or reject an inferred work link",
        "security": [
          {
            "firebaseAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/BoardId"
          },
          {
            "$ref": "#/components/parameters/ProjectId"
          },
          {
            "$ref": "#/components/parameters/TaskId"
          },
          {
            "name": "fingerprint",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "decision",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "accept",
                "reject"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Suggestion decision recorded."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Use Authorization: Bearer <GEOCRM_API_KEY_OR_ONE_OAUTH_ACCESS_TOKEN>. Each route still enforces credential type, scope, person status and current board permission."
      },
      "geoCrmKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-GeoCRM-Key",
        "description": "Alternative API key header."
      },
      "firebaseAuth": {
        "type": "http",
        "scheme": "bearer",
        "format": "JWT",
        "description": "Firebase ID token for signed-in ONE browser users."
      }
    },
    "parameters": {
      "BoardId": {
        "name": "boardId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 120
        }
      },
      "ColumnId": {
        "name": "columnId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "Column ID or exact column title."
      },
      "ItemId": {
        "name": "itemId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "UpdateId": {
        "name": "updateId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "ProjectId": {
        "name": "projectId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "CalendarProjectId": {
        "name": "projectId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 160
        }
      },
      "TaskId": {
        "name": "taskId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "SubtaskId": {
        "name": "subtaskId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "TeamId": {
        "name": "teamId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "ChannelId": {
        "name": "channelId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "ProposalId": {
        "name": "proposalId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "AssetId": {
        "name": "assetId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "HardwareAssetId": {
        "name": "assetId",
        "in": "path",
        "required": true,
        "schema": { "type": "string", "minLength": 1, "maxLength": 200 }
      },
      "DocumentId": {
        "name": "documentId",
        "in": "path",
        "required": true,
        "schema": { "type": "string", "minLength": 1, "maxLength": 200 }
      },
      "PeopleDocumentColumnId": {
        "name": "column_id",
        "in": "query",
        "required": true,
        "schema": { "type": "string", "minLength": 1, "maxLength": 200 }
      },
      "IdempotencyKey": {
        "name": "X-Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "Stable caller-generated key. A retry with the same request returns the prior result; reuse with different input is rejected.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 180
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing, inactive, or invalid credential.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The credential, signed-in person, or current board grant does not permit this operation.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "BadRequest": {
        "description": "The request body or parameters are invalid.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Board or item was not found.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Conflict": {
        "description": "The project revision, import key, or semantic target conflicts with current state. The request does not partially mutate the project.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "ProcurementDestinationInput": {
        "type": "object",
        "required": ["type", "id"],
        "properties": {
          "type": { "type": "string", "enum": ["person", "office"] },
          "id": { "type": "string", "minLength": 1, "maxLength": 200 }
        }
      },
      "ProcurementApproverInput": {
        "type": "object",
        "required": ["personId"],
        "properties": { "personId": { "type": "string", "minLength": 1, "maxLength": 200 } }
      },
      "ProcurementRequestCreateInput": {
        "type": "object",
        "required": ["category", "title", "amount", "currency", "approvers"],
        "properties": {
          "category": { "type": "string", "minLength": 1, "maxLength": 80 },
          "title": { "type": "string", "minLength": 1, "maxLength": 180 },
          "purpose": { "type": "string", "maxLength": 6000 },
          "amount": { "type": "number", "exclusiveMinimum": 0, "maximum": 1000000000 },
          "currency": { "type": "string", "enum": ["EUR", "USD", "GBP", "CAD", "AUD"] },
          "vendor": { "type": "string", "maxLength": 180 },
          "neededBy": { "type": "string", "maxLength": 32 },
          "linkUrl": { "type": "string", "format": "uri" },
          "linkLabel": { "type": "string", "maxLength": 120 },
          "equipmentCategory": { "type": "string", "maxLength": 160, "description": "Required when category is Hardware." },
          "quantity": { "type": "integer", "minimum": 1, "maximum": 1000, "description": "Required when category is Hardware." },
          "destination": { "$ref": "#/components/schemas/ProcurementDestinationInput" },
          "approvers": { "type": "array", "minItems": 1, "maxItems": 12, "items": { "$ref": "#/components/schemas/ProcurementApproverInput" } },
          "initialComment": { "type": "string", "maxLength": 4000 }
        }
      },
      "ProcurementRequestUpdateInput": {
        "type": "object",
        "required": ["category", "title", "amount", "currency"],
        "properties": {
          "category": { "type": "string", "minLength": 1, "maxLength": 80 },
          "title": { "type": "string", "minLength": 1, "maxLength": 180 },
          "purpose": { "type": "string", "maxLength": 6000 },
          "amount": { "type": "number", "exclusiveMinimum": 0, "maximum": 1000000000 },
          "currency": { "type": "string", "enum": ["EUR", "USD", "GBP", "CAD", "AUD"] },
          "vendor": { "type": "string", "maxLength": 180 },
          "neededBy": { "type": "string", "maxLength": 32 },
          "linkUrl": { "type": "string", "format": "uri" },
          "linkLabel": { "type": "string", "maxLength": 120 },
          "equipmentCategory": { "type": "string", "maxLength": 160, "description": "Required when category is Hardware." },
          "quantity": { "type": "integer", "minimum": 1, "maximum": 1000, "description": "Required when category is Hardware." },
          "destination": { "$ref": "#/components/schemas/ProcurementDestinationInput" }
        }
      },
      "ProcurementCommentInput": {
        "type": "object",
        "required": ["text"],
        "properties": {
          "text": { "type": "string", "minLength": 1, "maxLength": 4000 },
          "mentions": { "type": "array", "maxItems": 50, "items": { "$ref": "#/components/schemas/ProcurementApproverInput" } }
        }
      },
      "ProcurementRequest": {
        "type": "object",
        "required": ["id", "category", "title", "amount", "currency", "status", "requester", "approvers", "updatedAt"],
        "properties": {
          "id": { "type": "string" },
          "category": { "type": "string" },
          "title": { "type": "string" },
          "amount": { "type": "number" },
          "currency": { "type": "string" },
          "status": { "type": "string", "enum": ["pending", "requested", "approved", "rejected", "changes_requested", "ordered", "delivered", "complete", "cancelled"] },
          "requester": { "type": "object", "additionalProperties": true },
          "approvers": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "comments": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "attachments": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "updatedAt": { "type": "string", "format": "date-time" },
          "permissions": { "type": "object", "additionalProperties": { "type": "boolean" } }
        },
        "additionalProperties": true
      },
      "ProcurementRequestResponse": {
        "type": "object",
        "required": ["request"],
        "properties": { "request": { "$ref": "#/components/schemas/ProcurementRequest" } },
        "additionalProperties": true
      },
      "ProcurementListResponse": {
        "type": "object",
        "required": ["requests", "people", "offices", "categories", "canManageCategories"],
        "properties": {
          "requests": { "type": "array", "items": { "$ref": "#/components/schemas/ProcurementRequest" } },
          "people": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "offices": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "categories": { "type": "array", "items": { "type": "string" } },
          "canManageCategories": { "type": "boolean" }
        }
      },
      "AdministrationAudit": {
        "type": "object",
        "required": ["generatedAt", "authorization", "security", "summary", "boards", "users", "permissionGroups", "invitations", "bootstrapAdministrators", "apiKeys", "findings", "truncation"],
        "properties": {
          "generatedAt": { "type": "string", "format": "date-time" },
          "authorization": {
            "type": "object",
            "required": ["credential", "roles", "readOnly"],
            "properties": {
              "credential": { "type": "string", "const": "oauth_user" },
              "roles": { "type": "array", "items": { "type": "string", "enum": ["owner", "admin"] } },
              "readOnly": { "type": "boolean", "const": true }
            }
          },
          "security": {
            "type": "object",
            "required": ["redactedFields", "omittedSurfaces"],
            "properties": {
              "redactedFields": { "type": "array", "items": { "type": "string" } },
              "omittedSurfaces": { "type": "array", "items": { "type": "string" } }
            }
          },
          "summary": { "type": "object", "additionalProperties": true },
          "boards": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "users": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "permissionGroups": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "invitations": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "bootstrapAdministrators": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "apiKeys": {
            "type": "array",
            "description": "Redacted API-key metadata. Hashes and reusable secrets are never returned.",
            "items": {
              "type": "object",
              "required": ["id", "name", "kind", "prefix", "scopes", "allowedBoardIds", "allowedProjects", "status", "useCount"],
              "properties": {
                "id": { "type": "string" },
                "name": { "type": "string" },
                "kind": { "type": "string", "enum": ["service", "personal"] },
                "prefix": { "type": "string" },
                "scopes": { "type": "array", "items": { "type": "string" } },
                "allowedBoardIds": { "type": "array", "items": { "type": "string" } },
                "allowedProjects": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
                "owner": { "type": ["object", "null"], "additionalProperties": true },
                "status": { "type": "string" },
                "createdAt": { "type": "string" },
                "createdByEmail": { "type": "string" },
                "revokedAt": { "type": "string" },
                "revokedByEmail": { "type": "string" },
                "lastUsedAt": { "type": "string" },
                "useCount": { "type": "number", "minimum": 0 }
              }
            }
          },
          "findings": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "truncation": { "type": "object", "additionalProperties": true }
        }
      },
      "HardwareCustodian": {
        "type": "object",
        "required": ["type", "name"],
        "properties": {
          "type": { "type": "string", "enum": ["person", "office", "unassigned"] },
          "id": { "type": "string", "maxLength": 200 },
          "name": { "type": "string", "minLength": 1, "maxLength": 200 }
        }
      },
      "HardwareAsset": {
        "type": "object",
        "required": ["id", "title", "description", "category", "status", "custodian", "revision", "archived", "documentCount"],
        "properties": {
          "id": { "type": "string" },
          "title": { "type": "string" },
          "description": { "type": "string" },
          "category": { "type": "string" },
          "serialNumber": { "type": "string" },
          "acquiredDate": { "type": ["string", "null"], "format": "date" },
          "costAmount": { "type": ["number", "null"], "minimum": 0 },
          "costCurrency": { "type": ["string", "null"] },
          "condition": { "type": ["string", "null"] },
          "notes": { "type": "string" },
          "status": { "type": "string", "enum": ["assigned", "available", "returned", "transferred", "bought_out", "removed", "archived"] },
          "custodian": { "$ref": "#/components/schemas/HardwareCustodian" },
          "officeId": { "type": ["string", "null"] },
          "procurementRequestId": { "type": ["string", "null"] },
          "procurementStatus": { "type": ["string", "null"] },
          "quantity": { "type": "integer", "minimum": 1 },
          "vendor": { "type": "string" },
          "productUrl": { "type": "string" },
          "createdAt": { "type": ["string", "null"] },
          "updatedAt": { "type": ["string", "null"] },
          "archived": { "type": "boolean" },
          "archivedAt": { "type": ["string", "null"] },
          "archivedReason": { "type": "string" },
          "revision": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
          "documentCount": { "type": "integer", "minimum": 0 },
          "movements": { "type": "array", "items": { "type": "object" } },
          "documents": { "type": "array", "items": { "$ref": "#/components/schemas/HardwareDocumentRecord" } }
        }
      },
      "HardwareAssetResponse": {
        "type": "object",
        "required": ["ok", "board", "asset"],
        "properties": {
          "ok": { "type": "boolean" },
          "created": { "type": "boolean" },
          "updated": { "type": "boolean" },
          "moved": { "type": "boolean" },
          "replayed": { "type": "boolean" },
          "archived": { "type": "boolean" },
          "movementId": { "type": "string" },
          "board": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" } } },
          "asset": { "$ref": "#/components/schemas/HardwareAsset" }
        }
      },
      "HardwareAssetListResponse": {
        "type": "object",
        "required": ["ok", "count", "returned", "truncated", "assets"],
        "properties": {
          "ok": { "type": "boolean" },
          "count": { "type": "integer" },
          "returned": { "type": "integer" },
          "truncated": { "type": "boolean" },
          "assets": { "type": "array", "items": { "$ref": "#/components/schemas/HardwareAsset" } },
          "offices": { "type": "array", "items": { "type": "object" } }
        }
      },
      "HardwareAssetCreateInput": {
        "type": "object",
        "required": ["description", "category", "target"],
        "properties": {
          "description": { "type": "string", "minLength": 1, "maxLength": 300 },
          "category": { "type": "string", "minLength": 1, "maxLength": 120 },
          "serialNumber": { "type": "string", "maxLength": 180 },
          "acquiredDate": { "type": "string", "format": "date" },
          "costAmount": { "type": "number", "minimum": 0, "maximum": 1000000000 },
          "costCurrency": { "type": "string", "minLength": 3, "maxLength": 3 },
          "condition": { "type": "string", "maxLength": 120 },
          "notes": { "type": "string", "maxLength": 4000 },
          "vendor": { "type": "string", "maxLength": 240 },
          "productUrl": { "type": "string", "maxLength": 2000 },
          "procurementRequestId": { "type": "string", "maxLength": 200 },
          "procurementStatus": { "type": "string", "maxLength": 80 },
          "quantity": { "type": "integer", "minimum": 1, "maximum": 10000 },
          "target": { "$ref": "#/components/schemas/HardwareCustodian" },
          "effectiveDate": { "type": "string", "format": "date" },
          "note": { "type": "string", "maxLength": 2000 }
        }
      },
      "HardwareAssetUpdateInput": {
        "type": "object",
        "required": ["expectedRevision"],
        "description": "Change at least one non-custody field. Custody changes use the move route.",
        "properties": {
          "expectedRevision": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
          "description": { "type": "string", "minLength": 1, "maxLength": 300 },
          "category": { "type": "string", "minLength": 1, "maxLength": 120 },
          "serialNumber": { "type": "string", "maxLength": 180 },
          "acquiredDate": { "type": "string", "format": "date" },
          "costAmount": { "type": "number", "minimum": 0, "maximum": 1000000000 },
          "costCurrency": { "type": "string", "minLength": 3, "maxLength": 3 },
          "condition": { "type": "string", "maxLength": 120 },
          "notes": { "type": "string", "maxLength": 4000 },
          "vendor": { "type": "string", "maxLength": 240 },
          "productUrl": { "type": "string", "maxLength": 2000 },
          "procurementRequestId": { "type": "string", "maxLength": 200 },
          "procurementStatus": { "type": "string", "maxLength": 80 },
          "quantity": { "type": "integer", "minimum": 1, "maximum": 10000 }
        }
      },
      "HardwareAssetMoveInput": {
        "type": "object",
        "required": ["expectedRevision", "to", "idempotencyKey"],
        "properties": {
          "expectedRevision": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
          "to": { "$ref": "#/components/schemas/HardwareCustodian" },
          "effectiveDate": { "type": "string", "format": "date" },
          "note": { "type": "string", "maxLength": 2000 },
          "idempotencyKey": { "type": "string", "minLength": 12, "maxLength": 160 }
        }
      },
      "HardwareAssetArchiveInput": {
        "type": "object",
        "required": ["expectedRevision", "confirmAssetId", "reason"],
        "properties": {
          "expectedRevision": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
          "confirmAssetId": { "type": "string", "minLength": 1, "maxLength": 200 },
          "reason": { "type": "string", "minLength": 1, "maxLength": 2000 },
          "effectiveDate": { "type": "string", "format": "date" }
        }
      },
      "HardwareDocumentRecord": {
        "type": "object",
        "required": ["id", "boardId", "assetId", "name", "contentType", "size", "sha256", "revision", "createdAt", "downloadPath"],
        "properties": {
          "id": { "type": "string" },
          "boardId": { "type": "string" },
          "assetId": { "type": "string" },
          "name": { "type": "string" },
          "contentType": { "type": "string" },
          "size": { "type": "integer", "minimum": 1, "maximum": 20971520 },
          "sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
          "revision": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
          "createdAt": { "type": "string", "format": "date-time" },
          "downloadPath": { "type": "string" }
        }
      },
      "HardwareDocumentListResponse": {
        "type": "object",
        "required": ["ok", "boardId", "assetId", "count", "documents"],
        "properties": {
          "ok": { "type": "boolean" },
          "boardId": { "type": "string" },
          "assetId": { "type": "string" },
          "count": { "type": "integer" },
          "documents": { "type": "array", "items": { "$ref": "#/components/schemas/HardwareDocumentRecord" } }
        }
      },
      "PeopleDocumentRecord": {
        "type": "object",
        "required": ["id", "name", "ownerType", "boardId", "folderId", "folderName", "contentType", "size", "createdAt", "revision", "managed"],
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "ownerType": { "type": "string", "enum": ["person", "company"] },
          "boardId": { "type": "string" },
          "itemId": { "type": "string" },
          "columnId": { "type": "string" },
          "folderId": { "type": "string" },
          "folderName": { "type": "string" },
          "contentType": { "type": "string" },
          "size": { "type": "integer", "minimum": 0, "maximum": 20971520 },
          "createdAt": { "type": "string" },
          "sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
          "revision": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
          "managed": { "type": "boolean" }
        }
      },
      "PeopleDocumentListResponse": {
        "type": "object",
        "required": ["ok", "ownerType", "boardId", "count", "documents"],
        "properties": {
          "ok": { "type": "boolean" },
          "ownerType": { "type": "string", "enum": ["person", "company"] },
          "boardId": { "type": "string" },
          "itemId": { "type": "string" },
          "columnId": { "type": "string" },
          "count": { "type": "integer" },
          "documents": { "type": "array", "items": { "$ref": "#/components/schemas/PeopleDocumentRecord" } }
        }
      },
      "PeopleDocumentUploadInput": {
        "type": "object",
        "required": ["folderId", "fileName", "contentType", "dataBase64"],
        "properties": {
          "folderId": { "type": "string", "minLength": 1, "maxLength": 200 },
          "folderName": { "type": "string", "maxLength": 180 },
          "fileName": { "type": "string", "minLength": 1, "maxLength": 180 },
          "contentType": { "type": "string", "minLength": 1, "maxLength": 160 },
          "dataBase64": { "type": "string", "minLength": 1, "maxLength": 28000000 }
        }
      },
      "PeopleDocumentDeleteInput": {
        "type": "object",
        "required": ["expectedRevision", "confirmName"],
        "properties": {
          "expectedRevision": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
          "confirmName": { "type": "string", "minLength": 1, "maxLength": 180 }
        }
      },
      "RemoteMachinesBoard": {
        "type": "object",
        "required": ["id", "name", "kind", "url"],
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "kind": { "type": "string", "const": "remote_machines" },
          "url": { "type": "string", "format": "uri" }
        }
      },
      "RemoteMachineSession": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "user": { "type": "string" },
          "domain": { "type": "string" },
          "state": { "type": "string" },
          "clientName": { "type": "string" },
          "interactive": { "type": "boolean" },
          "startedAt": { "type": "string", "format": "date-time" },
          "updatedAt": { "type": "string", "format": "date-time" }
        }
      },
      "RemoteMachineMetric": {
        "type": "object",
        "required": ["at", "atMs", "cpuUtilization"],
        "properties": {
          "at": { "type": "string", "format": "date-time" },
          "atMs": { "type": "integer" },
          "cpuUtilization": { "type": "number", "minimum": 0, "maximum": 100 },
          "cpuTemperatureCelsius": { "type": "number", "minimum": -20, "maximum": 150 },
          "gpuTemperatureCelsius": { "type": "number", "minimum": -20, "maximum": 150 }
        }
      },
      "RemoteMachineBooking": {
        "type": "object",
        "required": ["id", "machineId", "title", "startsAt", "endsAt", "timezone", "status", "userUid", "userEmail", "createdAt", "updatedAt"],
        "properties": {
          "id": { "type": "string" },
          "machineId": { "type": "string" },
          "title": { "type": "string" },
          "purpose": { "type": "string" },
          "startsAt": { "type": "string", "format": "date-time" },
          "endsAt": { "type": "string", "format": "date-time" },
          "timezone": { "type": "string" },
          "status": { "type": "string", "enum": ["booked", "cancelled", "completed"] },
          "userUid": { "type": "string" },
          "userEmail": { "type": "string" },
          "userName": { "type": "string" },
          "createdAt": { "type": "string", "format": "date-time" },
          "updatedAt": { "type": "string", "format": "date-time" },
          "source": { "type": "string" },
          "cancellationReason": { "type": "string" }
        }
      },
      "RemoteMachine": {
        "type": "object",
        "required": ["id", "aliases", "name", "online", "inUse", "role", "bookable", "availability", "activeSessions", "network"],
        "properties": {
          "id": { "type": "string" },
          "aliases": { "type": "array", "items": { "type": "string" } },
          "name": { "type": "string" },
          "online": { "type": "boolean" },
          "inUse": { "type": "boolean" },
          "role": { "type": "string", "enum": ["graphics", "runner", "unclassified"] },
          "bookable": { "type": "boolean" },
          "availability": { "type": "string", "enum": ["available", "in_use", "offline", "booked", "not_bookable"] },
          "lastSeenAt": { "type": "string" },
          "agentVersion": { "type": "string" },
          "os": { "type": "string" },
          "osVersion": { "type": "string" },
          "cpuName": { "type": "string" },
          "gpuName": { "type": "string" },
          "cpuUtilization": { "type": ["number", "null"], "minimum": 0, "maximum": 100 },
          "cpuTemperatureCelsius": { "type": ["number", "null"], "minimum": -20, "maximum": 150 },
          "gpuTemperatureCelsius": { "type": ["number", "null"], "minimum": -20, "maximum": 150 },
          "uptimeSeconds": { "type": ["integer", "null"], "minimum": 0 },
          "storage": {
            "type": "object",
            "description": "Aggregate free and total capacity for all readable local volumes as last reported by OneClient, with per-volume detail.",
            "properties": {
              "path": { "type": "string", "examples": ["C:\\", "/"] },
              "totalBytes": { "type": ["integer", "null"], "minimum": 0 },
              "availableBytes": { "type": ["integer", "null"], "minimum": 0 },
              "volumes": {
                "type": "array",
                "maxItems": 32,
                "items": {
                  "type": "object",
                  "required": ["path", "totalBytes", "availableBytes"],
                  "properties": {
                    "path": { "type": "string", "examples": ["C:\\", "D:\\", "/Volumes/Render"] },
                    "totalBytes": { "type": "integer", "minimum": 1 },
                    "availableBytes": { "type": "integer", "minimum": 0 }
                  }
                }
              }
            }
          },
          "network": {
            "type": "object",
            "properties": {
              "ipAddress": { "type": "string" },
              "localIpAddresses": { "type": "array", "items": { "type": "string" } },
              "vpnIpAddresses": { "type": "array", "items": { "type": "string" } }
            }
          },
          "color": { "type": "string" },
          "activeSessions": { "type": "array", "items": { "$ref": "#/components/schemas/RemoteMachineSession" } },
          "bookings": { "type": "array", "items": { "$ref": "#/components/schemas/RemoteMachineBooking" } },
          "metrics": { "type": "array", "maxItems": 60, "items": { "$ref": "#/components/schemas/RemoteMachineMetric" } }
        }
      },
      "RemoteMachineListResponse": {
        "type": "object",
        "required": ["board", "generatedAt", "machines"],
        "properties": {
          "board": { "$ref": "#/components/schemas/RemoteMachinesBoard" },
          "generatedAt": { "type": "string", "format": "date-time" },
          "window": { "type": "object", "properties": { "from": { "type": "string", "format": "date-time" }, "to": { "type": "string", "format": "date-time" } } },
          "machines": { "type": "array", "items": { "$ref": "#/components/schemas/RemoteMachine" } }
        }
      },
      "RemoteMachineResponse": {
        "type": "object",
        "required": ["board", "generatedAt", "machine"],
        "properties": {
          "board": { "$ref": "#/components/schemas/RemoteMachinesBoard" },
          "generatedAt": { "type": "string", "format": "date-time" },
          "machine": { "$ref": "#/components/schemas/RemoteMachine" }
        }
      },
      "RemoteMachineBookingListResponse": {
        "type": "object",
        "required": ["board", "bookings"],
        "properties": {
          "board": { "$ref": "#/components/schemas/RemoteMachinesBoard" },
          "window": { "type": "object", "properties": { "from": { "type": "string", "format": "date-time" }, "to": { "type": "string", "format": "date-time" } } },
          "bookings": { "type": "array", "items": { "$ref": "#/components/schemas/RemoteMachineBooking" } }
        }
      },
      "RemoteMachineBookingCreate": {
        "type": "object",
        "required": ["machine_id", "title", "starts_at", "ends_at", "timezone"],
        "properties": {
          "machine_id": { "type": "string" },
          "title": { "type": "string", "minLength": 1, "maxLength": 160 },
          "purpose": { "type": "string", "maxLength": 1000 },
          "starts_at": { "type": "string", "format": "date-time" },
          "ends_at": { "type": "string", "format": "date-time" },
          "timezone": { "type": "string", "maxLength": 120, "example": "Europe/Berlin" },
          "idempotency_key": { "type": "string", "minLength": 8, "maxLength": 160 }
        },
        "additionalProperties": false
      },
      "RemoteMachineBookingUpdate": {
        "type": "object",
        "properties": {
          "machine_id": { "type": "string" },
          "title": { "type": "string", "minLength": 1, "maxLength": 160 },
          "purpose": { "type": "string", "maxLength": 1000 },
          "starts_at": { "type": "string", "format": "date-time" },
          "ends_at": { "type": "string", "format": "date-time" },
          "timezone": { "type": "string", "maxLength": 120 },
          "expected_updated_at": { "type": "string", "format": "date-time" }
        },
        "additionalProperties": false
      },
      "RemoteMachineBookingCancel": {
        "type": "object",
        "properties": {
          "expected_updated_at": { "type": "string", "format": "date-time" },
          "reason": { "type": "string", "maxLength": 500 }
        },
        "additionalProperties": false
      },
      "RemoteMachineBookingMutationResponse": {
        "type": "object",
        "required": ["board", "booking"],
        "properties": {
          "board": { "$ref": "#/components/schemas/RemoteMachinesBoard" },
          "created": { "type": "boolean" },
          "cancelled": { "type": "boolean" },
          "duplicate": { "type": "boolean" },
          "booking": { "$ref": "#/components/schemas/RemoteMachineBooking" }
        }
      },
      "FinanceFinResultsFileRequest": {
        "type": "object",
        "properties": {
          "file": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "maxLength": 180
              },
              "byteSize": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2097152
              },
              "contentBase64": {
                "type": "string",
                "contentEncoding": "base64"
              }
            },
            "required": [
              "name",
              "byteSize",
              "contentBase64"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "file"
        ],
        "additionalProperties": false
      },
      "FinanceCashForecastRequest": {
        "type": "object",
        "properties": {
          "reportingCurrency": {
            "type": "string",
            "pattern": "^[A-Z]{3}$",
            "default": "EUR"
          },
          "horizon": {
            "type": "string",
            "enum": [
              "13w",
              "12m",
              "custom"
            ],
            "default": "13w"
          },
          "forecastMonths": {
            "type": "integer",
            "minimum": 1,
            "maximum": 60,
            "description": "Required when horizon is custom; number of monthly forecast buckets."
          },
          "historyFromMonth": {
            "type": "string",
            "pattern": "^(19|20)[0-9]{2}-(0[1-9]|1[0-2])$",
            "description": "Inclusive first historical month. Supply together with historyToMonth for a monthly horizon; 1 to 120 completed months. Display history does not change the trailing forecast model window."
          },
          "historyToMonth": {
            "type": "string",
            "pattern": "^(19|20)[0-9]{2}-(0[1-9]|1[0-2])$",
            "description": "Inclusive last historical month, before the current month. Future buckets start in the current month."
          },
          "cashScope": {
            "type": "string",
            "enum": [
              "liquid",
              "treasury"
            ],
            "default": "liquid"
          },
          "includeArchivedEvents": {
            "type": "boolean",
            "default": false
          }
        },
        "additionalProperties": false
      },
      "FinanceCashPlan": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "enum": [
              "inflow",
              "outflow"
            ]
          },
          "amountMinor": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Positive amount in currency minor units."
          },
          "currency": {
            "type": "string",
            "pattern": "^[A-Z]{3}$"
          },
          "startDate": {
            "type": "string",
            "format": "date"
          },
          "recurrence": {
            "type": "string",
            "enum": [
              "one_off",
              "weekly",
              "monthly",
              "quarterly",
              "annual"
            ]
          },
          "endDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "certainty": {
            "type": "string",
            "enum": [
              "committed",
              "expected",
              "possible"
            ]
          },
          "categoryId": {
            "type": "string"
          },
          "subcategoryId": {
            "type": "string"
          },
          "accountId": {
            "type": "string"
          },
          "planKind": {
            "type": "string",
            "enum": [
              "cash",
              "investment_purchase"
            ]
          },
          "investmentIsin": {
            "type": "string",
            "pattern": "^[A-Z0-9]{12}$"
          },
          "note": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "archived"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "title",
          "direction",
          "amountMinor",
          "currency",
          "startDate",
          "recurrence",
          "certainty",
          "status",
          "createdAt",
          "updatedAt"
        ],
        "additionalProperties": true
      },
      "FinanceCashPlanCreate": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 160
          },
          "direction": {
            "type": "string",
            "enum": [
              "inflow",
              "outflow"
            ]
          },
          "amountMinor": {
            "type": "string",
            "pattern": "^[0-9]+$"
          },
          "currency": {
            "type": "string",
            "pattern": "^[A-Z]{3}$"
          },
          "startDate": {
            "type": "string",
            "format": "date"
          },
          "recurrence": {
            "type": "string",
            "enum": [
              "one_off",
              "weekly",
              "monthly",
              "quarterly",
              "annual"
            ]
          },
          "endDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "certainty": {
            "type": "string",
            "enum": [
              "committed",
              "expected",
              "possible"
            ]
          },
          "categoryId": {
            "type": "string"
          },
          "subcategoryId": {
            "type": "string"
          },
          "accountId": {
            "type": "string"
          },
          "planKind": {
            "type": "string",
            "enum": [
              "cash",
              "investment_purchase"
            ],
            "default": "cash"
          },
          "investmentIsin": {
            "type": "string",
            "pattern": "^[A-Z0-9]{12}$"
          },
          "note": {
            "type": "string",
            "maxLength": 1000
          },
          "idempotencyKey": {
            "type": "string",
            "minLength": 8,
            "maxLength": 160,
            "description": "Optional body mirror of the required X-Idempotency-Key header."
          }
        },
        "required": [
          "title",
          "direction",
          "amountMinor",
          "currency",
          "startDate",
          "recurrence",
          "certainty"
        ],
        "additionalProperties": false
      },
      "FinanceCashPlanUpdate": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 160
          },
          "direction": {
            "type": "string",
            "enum": [
              "inflow",
              "outflow"
            ]
          },
          "amountMinor": {
            "type": "string",
            "pattern": "^[0-9]+$"
          },
          "currency": {
            "type": "string",
            "pattern": "^[A-Z]{3}$"
          },
          "startDate": {
            "type": "string",
            "format": "date"
          },
          "recurrence": {
            "type": "string",
            "enum": [
              "one_off",
              "weekly",
              "monthly",
              "quarterly",
              "annual"
            ]
          },
          "endDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "certainty": {
            "type": "string",
            "enum": [
              "committed",
              "expected",
              "possible"
            ]
          },
          "categoryId": {
            "type": "string"
          },
          "subcategoryId": {
            "type": "string"
          },
          "accountId": {
            "type": "string"
          },
          "planKind": {
            "type": "string",
            "enum": [
              "cash",
              "investment_purchase"
            ]
          },
          "investmentIsin": {
            "type": "string",
            "pattern": "^[A-Z0-9]{12}$"
          },
          "note": {
            "type": "string",
            "maxLength": 1000
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "archived"
            ]
          },
          "expectedUpdatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "expectedUpdatedAt"
        ],
        "additionalProperties": false
      },
      "FinanceCashForecastSettingsUpdate": {
        "type": "object",
        "properties": {
          "minimumCashMinor": {
            "type": "string",
            "pattern": "^-?[0-9]+$"
          },
          "minimumCashCurrency": {
            "type": "string",
            "pattern": "^[A-Z]{3}$"
          },
          "defaultScope": {
            "type": "string",
            "enum": [
              "liquid",
              "treasury"
            ]
          },
          "defaultHorizon": {
            "type": "string",
            "enum": [
              "13w",
              "12m"
            ]
          },
          "expectedUpdatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "expectedUpdatedAt"
        ],
        "additionalProperties": false
      },
      "FinanceCashPlanMutationResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "event": {
            "$ref": "#/components/schemas/FinanceCashPlan"
          },
          "requestId": {
            "type": "string"
          }
        },
        "required": [
          "ok",
          "event"
        ],
        "additionalProperties": true
      },
      "FinanceCashForecastResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "forecast": {
            "type": "object",
            "properties": {
              "calculationVersion": {
                "type": "integer"
              },
              "asOfDate": {
                "type": "string",
                "format": "date"
              },
              "reportingCurrency": {
                "type": "string"
              },
              "horizon": {
                "type": "string",
                "enum": [
                  "13w",
                  "12m",
                  "custom"
                ]
              },
              "forecastMonths": {
                "type": "integer",
                "minimum": 1,
                "maximum": 60
              },
              "historyFromMonth": {
                "type": "string",
                "pattern": "^(19|20)[0-9]{2}-(0[1-9]|1[0-2])$"
              },
              "historyToMonth": {
                "type": "string",
                "pattern": "^(19|20)[0-9]{2}-(0[1-9]|1[0-2])$"
              },
              "cashScope": {
                "type": "string",
                "enum": [
                  "liquid",
                  "treasury"
                ]
              },
              "startingBalance": {
                "type": "object",
                "properties": {
                  "totalMinor": {
                    "type": "string"
                  },
                  "thresholdMinor": {
                    "type": "string"
                  },
                  "includedAccountCount": {
                    "type": "integer"
                  },
                  "coveredAccountCount": {
                    "type": "integer"
                  },
                  "accounts": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                },
                "required": [
                  "totalMinor",
                  "thresholdMinor",
                  "includedAccountCount",
                  "coveredAccountCount",
                  "accounts"
                ],
                "additionalProperties": true
              },
              "payables": {
                "type": "object",
                "description": "Open Accounts Payable bills placed on the Flow timeline. Approved bills are committed forecast outflows; bills needing approval are returned as pending exposure but remain excluded from spending, net movement, and cash balances until approved.",
                "properties": {
                  "paymentPolicy": {
                    "type": "string",
                    "enum": [
                      "approval_gated_bill_due_date"
                    ]
                  },
                  "openBillCount": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "approvedBillCount": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "pendingApprovalBillCount": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "forecastApprovedBillCount": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "forecastPendingBillCount": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "outsideHorizonBillCount": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "overdueBillCount": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "unforecastableBillCount": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "openBalanceMinor": {
                    "type": "string",
                    "pattern": "^[0-9]+$"
                  },
                  "approvedBalanceMinor": {
                    "type": "string",
                    "pattern": "^[0-9]+$"
                  },
                  "pendingApprovalBalanceMinor": {
                    "type": "string",
                    "pattern": "^[0-9]+$"
                  },
                  "forecastApprovedBalanceMinor": {
                    "type": "string",
                    "pattern": "^[0-9]+$"
                  },
                  "forecastPendingBalanceMinor": {
                    "type": "string",
                    "pattern": "^[0-9]+$"
                  },
                  "overdueBalanceMinor": {
                    "type": "string",
                    "pattern": "^[0-9]+$"
                  },
                  "payments": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "billId": {
                          "type": "string"
                        },
                        "invoiceNumber": {
                          "type": "string"
                        },
                        "vendorName": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "approved",
                            "needs_review"
                          ]
                        },
                        "dueDate": {
                          "type": "string",
                          "format": "date"
                        },
                        "forecastDate": {
                          "type": "string",
                          "format": "date"
                        },
                        "paymentBasis": {
                          "type": "string",
                          "enum": [
                            "due_date",
                            "overdue_as_of"
                          ]
                        },
                        "overdueDays": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "currency": {
                          "type": "string"
                        },
                        "sourceAmountMinor": {
                          "type": "string"
                        },
                        "amountMinor": {
                          "type": "string"
                        },
                        "withinHorizon": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "billId",
                        "vendorName",
                        "status",
                        "dueDate",
                        "forecastDate",
                        "paymentBasis",
                        "currency",
                        "sourceAmountMinor",
                        "amountMinor",
                        "withinHorizon"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "required": [
                  "paymentPolicy",
                  "openBillCount",
                  "approvedBillCount",
                  "pendingApprovalBillCount",
                  "forecastApprovedBillCount",
                  "forecastPendingBillCount",
                  "outsideHorizonBillCount",
                  "overdueBillCount",
                  "unforecastableBillCount",
                  "openBalanceMinor",
                  "approvedBalanceMinor",
                  "pendingApprovalBalanceMinor",
                  "forecastApprovedBalanceMinor",
                  "forecastPendingBalanceMinor",
                  "overdueBalanceMinor",
                  "payments"
                ],
                "additionalProperties": false
              },
              "receivables": {
                "type": "object",
                "description": "Outstanding issued Accounts Receivable balances represented as expected cash payments. Due invoices use their invoice due date; overdue invoices use the forecast as-of date; matched, paid, void, draft, and zero-balance invoices are excluded.",
                "properties": {
                  "collectionPolicy": {
                    "type": "string",
                    "enum": [
                      "invoice_due_date"
                    ]
                  },
                  "openInvoiceCount": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "forecastInvoiceCount": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "outsideHorizonInvoiceCount": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "overdueInvoiceCount": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "unforecastableInvoiceCount": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "openBalanceMinor": {
                    "type": "string",
                    "pattern": "^[0-9]+$"
                  },
                  "forecastBalanceMinor": {
                    "type": "string",
                    "pattern": "^[0-9]+$"
                  },
                  "overdueBalanceMinor": {
                    "type": "string",
                    "pattern": "^[0-9]+$"
                  },
                  "payments": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "invoiceId": {
                          "type": "string"
                        },
                        "invoiceNumber": {
                          "type": "string"
                        },
                        "clientName": {
                          "type": "string"
                        },
                        "dueDate": {
                          "type": "string",
                          "format": "date"
                        },
                        "forecastDate": {
                          "type": "string",
                          "format": "date"
                        },
                        "collectionBasis": {
                          "type": "string",
                          "enum": [
                            "due_date",
                            "overdue_as_of"
                          ]
                        },
                        "overdueDays": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "currency": {
                          "type": "string"
                        },
                        "sourceAmountMinor": {
                          "type": "string"
                        },
                        "amountMinor": {
                          "type": "string"
                        },
                        "withinHorizon": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "invoiceId",
                        "clientName",
                        "dueDate",
                        "forecastDate",
                        "collectionBasis",
                        "currency",
                        "sourceAmountMinor",
                        "amountMinor",
                        "withinHorizon"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "required": [
                  "collectionPolicy",
                  "openInvoiceCount",
                  "forecastInvoiceCount",
                  "outsideHorizonInvoiceCount",
                  "overdueInvoiceCount",
                  "unforecastableInvoiceCount",
                  "openBalanceMinor",
                  "forecastBalanceMinor",
                  "overdueBalanceMinor",
                  "payments"
                ],
                "additionalProperties": false
              },
              "actualBuckets": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": true
                }
              },
              "monthlyReviewBuckets": {
                "type": "array",
                "description": "Twelve calendar months of external cash movement and exact manual-verification coverage for the selected cash scope.",
                "items": {
                  "type": "object",
                  "additionalProperties": true
                }
              },
              "scenarios": {
                "type": "object",
                "properties": {
                  "base": {
                    "type": "object",
                    "additionalProperties": true
                  },
                  "upside": {
                    "type": "object",
                    "additionalProperties": true
                  },
                  "downside": {
                    "type": "object",
                    "additionalProperties": true
                  }
                },
                "required": [
                  "base",
                  "upside",
                  "downside"
                ]
              },
              "categoryDrivers": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": true
                }
              },
              "recurringPatterns": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": true
                }
              },
              "events": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/FinanceCashPlan"
                }
              },
              "dataQuality": {
                "type": "object",
                "additionalProperties": true
              },
              "fx": {
                "type": "object",
                "additionalProperties": true
              }
            },
            "required": [
              "calculationVersion",
              "asOfDate",
              "reportingCurrency",
              "horizon",
              "cashScope",
              "startingBalance",
              "payables",
              "receivables",
              "actualBuckets",
              "monthlyReviewBuckets",
              "scenarios",
              "categoryDrivers",
              "recurringPatterns",
              "events",
              "dataQuality",
              "fx"
            ],
            "additionalProperties": true
          }
        },
        "required": [
          "ok",
          "forecast"
        ],
        "additionalProperties": true
      },
      "FinanceViewRequest": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "transactions",
              "review"
            ],
            "default": "transactions"
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500,
            "default": 500
          },
          "query": {
            "type": "string",
            "maxLength": 240
          },
          "accountFilter": {
            "type": "string",
            "maxLength": 120
          },
          "classificationFilter": {
            "type": "string",
            "maxLength": 80
          },
          "categoryFilter": {
            "type": "string",
            "maxLength": 120
          },
          "dateFilterMode": {
            "type": "string",
            "enum": [
              "all",
              "range",
              "month",
              "day"
            ]
          },
          "dateFilterValue": {
            "type": "string",
            "maxLength": 10
          },
          "dateRangeStart": {
            "type": "string",
            "maxLength": 10
          },
          "dateRangeEnd": {
            "type": "string",
            "maxLength": 10
          },
          "amountFilter": {
            "type": "string",
            "enum": [
              "",
              "incoming",
              "outgoing",
              "zero"
            ]
          },
          "sort": {
            "type": "object",
            "properties": {
              "column": {
                "type": "string",
                "enum": [
                  "date",
                  "account",
                  "description",
                  "classification",
                  "amount"
                ]
              },
              "direction": {
                "type": "string",
                "enum": [
                  "asc",
                  "desc"
                ]
              }
            }
          }
        },
        "additionalProperties": false
      },
      "FinanceViewResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "transactions": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "postedDate": {
                  "type": "string"
                },
                "amountMinor": {
                  "type": "string"
                },
                "currency": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                },
                "counterpartyName": {
                  "type": "string"
                },
                "evidenceCount": {
                  "type": "integer",
                  "minimum": 0
                },
                "evidenceUpdatedAt": {
                  "type": "string",
                  "format": "date-time"
                }
              },
              "additionalProperties": true
            }
          },
          "matchingTransactionCount": {
            "type": "integer",
            "minimum": 0
          },
          "matchingEvidenceTransactionCount": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of matching transaction rows with at least one evidence file."
          },
          "matchingVerifiedEvidenceFileCount": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of evidence files attached to matching transactions that are not pending verification."
          },
          "truncated": {
            "type": "boolean"
          }
        },
        "required": [
          "ok",
          "transactions",
          "matchingTransactionCount",
          "matchingEvidenceTransactionCount",
          "matchingVerifiedEvidenceFileCount",
          "truncated"
        ],
        "additionalProperties": true
      },
      "FinanceEvidence": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "transactionId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "receipt",
              "invoice",
              "other"
            ]
          },
          "contentType": {
            "type": "string"
          },
          "size": {
            "type": "integer",
            "minimum": 1,
            "maximum": 20971520
          },
          "sha256": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "uploadedBy": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "email": {
                "type": "string",
                "format": "email"
              },
              "source": {
                "type": "string",
                "enum": [
                  "user",
                  "api_key"
                ]
              }
            },
            "required": [
              "name",
              "source"
            ]
          },
          "sourceReference": {
            "type": "string"
          },
          "downloadPath": {
            "type": "string",
            "pattern": "^/api/finance/transactions/"
          }
        },
        "required": [
          "id",
          "transactionId",
          "name",
          "kind",
          "contentType",
          "size",
          "sha256",
          "createdAt",
          "downloadPath"
        ],
        "additionalProperties": false
      },
      "FinanceEvidenceListResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "transactionId": {
            "type": "string"
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 20
          },
          "evidence": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "$ref": "#/components/schemas/FinanceEvidence"
            }
          }
        },
        "required": [
          "ok",
          "transactionId",
          "count",
          "evidence"
        ]
      },
      "FinanceEvidenceWriteResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "reused": {
            "type": "boolean"
          },
          "transactionId": {
            "type": "string"
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 20
          },
          "evidence": {
            "$ref": "#/components/schemas/FinanceEvidence"
          }
        },
        "required": [
          "ok",
          "reused",
          "transactionId",
          "count",
          "evidence"
        ]
      },
      "FinanceEvidenceDeleteResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "deleted": {
            "type": "boolean"
          },
          "transactionId": {
            "type": "string"
          },
          "evidenceId": {
            "type": "string"
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 20
          }
        },
        "required": [
          "ok",
          "deleted",
          "transactionId",
          "evidenceId",
          "count"
        ]
      },
      "ProjectTrackingPerson": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" }
        },
        "required": ["id", "name"],
        "additionalProperties": false
      },
      "ProjectTrackingImportRecord": {
        "type": "object",
        "description": "Safe import provenance only. Raw import keys, payload hashes, rationales, and credentials are never returned.",
        "properties": {
          "key_fingerprint": { "type": "string", "pattern": "^[a-f0-9]{16}$" },
          "target_id": { "type": "string" },
          "entry_type": { "type": "string", "description": "Lower-case ledger entry type. Current tracker imports use task or milestone; legacy records may use another value." },
          "tombstone_state": { "type": "string", "enum": ["active", "missing", "deleted"] }
        },
        "required": ["key_fingerprint", "target_id", "entry_type", "tombstone_state"],
        "additionalProperties": false
      },
      "ProjectTrackingContext": {
        "type": "object",
        "properties": {
          "board": { "type": "object", "additionalProperties": true },
          "project": {
            "type": "object",
            "properties": {
              "id": { "type": "string" },
              "name": { "type": "string" },
              "archived": { "type": "boolean" }
            },
            "required": ["id", "name", "archived"],
            "additionalProperties": true
          },
          "statuses": { "type": "array", "items": { "type": "string" } },
          "sprints": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "milestones": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "people": { "type": "array", "maxItems": 12, "items": { "$ref": "#/components/schemas/ProjectTrackingPerson" } },
          "import_records": { "type": "array", "maxItems": 500, "items": { "$ref": "#/components/schemas/ProjectTrackingImportRecord" } },
          "import_records_total": { "type": "integer", "minimum": 0, "description": "Total safe import-ledger records available before the deterministic 500-record response cap." },
          "import_records_truncated": { "type": "boolean", "description": "True exactly when import_records omits records because the safe import ledger exceeds 500 entries." },
          "tasks": { "type": "array", "maxItems": 100, "items": { "type": "object", "additionalProperties": true } },
          "total": { "type": "integer", "minimum": 0 },
          "has_more": { "type": "boolean" },
          "next_cursor": { "type": ["string", "null"] },
          "project_revision": { "type": "string", "description": "SHA-256 revision over the complete mutable project tracking record." }
        },
        "required": ["board", "project", "statuses", "sprints", "milestones", "people", "import_records", "import_records_total", "import_records_truncated", "tasks", "total", "has_more", "next_cursor", "project_revision"]
      },
      "LegacyProjectTaskListResponse": {
        "type": "object",
        "properties": {
          "board": { "type": "object", "additionalProperties": true },
          "project": { "type": "object", "additionalProperties": true },
          "tasks": { "type": "array", "items": { "type": "object", "additionalProperties": true } }
        },
        "required": ["board", "project", "tasks"]
      },
      "TrackerPersonReference": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "minLength": 1, "maxLength": 160 },
          "name": { "type": "string", "minLength": 1, "maxLength": 160 }
        },
        "required": ["id", "name"],
        "additionalProperties": false
      },
      "TrackerSlackWorkLinkMetadata": {
        "type": "object",
        "description": "Bounded Slack thread metadata retained within the canonical work link.",
        "properties": {
          "team_id": { "type": "string", "maxLength": 120 },
          "channel_id": { "type": "string", "maxLength": 120 },
          "thread_ts": { "type": "string", "maxLength": 80 },
          "channel_name": { "type": "string", "maxLength": 160 },
          "latest_activity_at": { "type": "string", "maxLength": 80 },
          "synced_at": { "type": "string", "maxLength": 80 }
        },
        "additionalProperties": false
      },
      "TrackerWorkLink": {
        "type": "object",
        "properties": {
          "provider": { "type": "string", "enum": ["github", "perforce", "slack"] },
          "kind": { "type": "string", "enum": ["branch", "commit", "pull_request", "changelist", "slack_thread"] },
          "external_id": { "type": "string", "minLength": 1, "maxLength": 500 },
          "url": { "type": "string", "format": "uri", "maxLength": 2000 },
          "repository": { "type": "string", "maxLength": 300 },
          "depot": { "type": "string", "maxLength": 500 },
          "title": { "type": "string", "maxLength": 500 },
          "state": { "type": "string", "maxLength": 120 },
          "slack": { "$ref": "#/components/schemas/TrackerSlackWorkLinkMetadata" }
        },
        "required": ["provider", "kind", "external_id"],
        "additionalProperties": false,
        "allOf": [
          {
            "if": { "properties": { "provider": { "const": "slack" } }, "required": ["provider"] },
            "then": {
              "properties": {
                "kind": { "const": "slack_thread" },
                "url": { "type": "string", "format": "uri", "maxLength": 2000, "pattern": "^https://(?:[^/]+\\.)?slack\\.com/archives/[A-Za-z0-9]+/p[0-9]+" }
              },
              "required": ["url"]
            },
            "else": { "not": { "required": ["slack"] } }
          },
          {
            "if": { "properties": { "provider": { "const": "github" } }, "required": ["provider"] },
            "then": { "properties": { "kind": { "enum": ["branch", "commit", "pull_request"] } } }
          },
          {
            "if": { "properties": { "provider": { "const": "perforce" } }, "required": ["provider"] },
            "then": { "properties": { "kind": { "const": "changelist" } } }
          }
        ]
      },
      "TrackerSubtaskImport": {
        "type": "object",
        "properties": {
          "title": { "type": "string", "minLength": 1, "maxLength": 500 },
          "details": { "type": "string", "maxLength": 20000 },
          "assignee": { "oneOf": [{ "$ref": "#/components/schemas/TrackerPersonReference" }, { "type": "null" }] },
          "participants": { "type": "array", "maxItems": 100, "items": { "$ref": "#/components/schemas/TrackerPersonReference" } },
          "priority": { "oneOf": [{ "type": "string", "enum": ["Low", "Medium", "High", "Critical"] }, { "type": "null" }] },
          "due_date": { "type": "string", "maxLength": 80, "pattern": "^(?:|\\d{4}-\\d{2}-\\d{2})$" }
        },
        "required": ["title", "details", "assignee", "participants", "priority", "due_date"],
        "additionalProperties": false
      },
      "TrackerSubtaskUpdate": {
        "type": "object",
        "properties": {
          "subtask_id": { "type": "string", "minLength": 1, "maxLength": 160, "description": "Stable ID of an existing subtask. Supply it when renaming that subtask so server-managed metadata stays with the same record. Omit it for an unchanged-title match, or for a new subtask only when no unmatched existing subtask could be mistaken for a replacement." },
          "title": { "type": "string", "minLength": 1, "maxLength": 500 },
          "details": { "type": "string", "maxLength": 20000 },
          "assignee": { "oneOf": [{ "$ref": "#/components/schemas/TrackerPersonReference" }, { "type": "null" }] },
          "participants": { "type": "array", "maxItems": 100, "items": { "$ref": "#/components/schemas/TrackerPersonReference" } },
          "priority": { "oneOf": [{ "type": "string", "enum": ["Low", "Medium", "High", "Critical"] }, { "type": "null" }] },
          "due_date": { "type": "string", "maxLength": 80, "pattern": "^(?:|\\d{4}-\\d{2}-\\d{2})$" }
        },
        "required": ["title", "details", "assignee", "participants", "priority", "due_date"],
        "additionalProperties": false
      },
      "TrackerTaskImport": {
        "type": "object",
        "properties": {
          "import_key": { "type": "string", "minLength": 1, "maxLength": 160, "description": "Immutable caller key. Stored only as a one-way fingerprint." },
          "title": { "type": "string", "minLength": 1, "maxLength": 500 },
          "details": { "type": "string", "maxLength": 20000 },
          "assignee": { "oneOf": [{ "$ref": "#/components/schemas/TrackerPersonReference" }, { "type": "null" }] },
          "participants": { "type": "array", "maxItems": 100, "items": { "$ref": "#/components/schemas/TrackerPersonReference" } },
          "priority": { "oneOf": [{ "type": "string", "enum": ["Low", "Medium", "High", "Critical"] }, { "type": "null" }] },
          "milestone": { "type": "string", "maxLength": 500 },
          "sprint_start": { "type": "string", "maxLength": 80, "pattern": "^(?:|\\d{4}-\\d{2}-\\d{2})$" },
          "sprint_end": { "type": "string", "maxLength": 80, "pattern": "^(?:|\\d{4}-\\d{2}-\\d{2})$" },
          "due_date": { "type": "string", "maxLength": 80, "pattern": "^(?:|\\d{4}-\\d{2}-\\d{2})$" },
          "subtasks": { "type": "array", "maxItems": 24, "items": { "$ref": "#/components/schemas/TrackerSubtaskImport" } },
          "initial_status": { "type": "string", "minLength": 1, "maxLength": 160, "description": "Must exactly match a configured project status after normalization." },
          "initial_status_rationale": { "type": "string", "minLength": 1, "maxLength": 2000 },
          "work_links": { "type": "array", "maxItems": 100, "items": { "$ref": "#/components/schemas/TrackerWorkLink" } }
        },
        "required": ["import_key", "title", "details", "assignee", "participants", "priority", "milestone", "sprint_start", "sprint_end", "due_date", "subtasks", "initial_status", "initial_status_rationale", "work_links"],
        "additionalProperties": false
      },
      "TrackerTaskCreateRequest": {
        "type": "object",
        "properties": {
          "expected_project_revision": { "type": "string", "minLength": 1, "maxLength": 128 },
          "tasks": { "type": "array", "minItems": 1, "maxItems": 12, "items": { "$ref": "#/components/schemas/TrackerTaskImport" } }
        },
        "required": ["expected_project_revision", "tasks"],
        "additionalProperties": false
      },
      "TrackerTaskCreateResponse": {
        "type": "object",
        "properties": {
          "tasks": {
            "type": "array",
            "minItems": 1,
            "maxItems": 12,
            "items": {
              "type": "object",
              "properties": { "action": { "type": "string", "enum": ["created", "existing"] } },
              "required": ["action"],
              "additionalProperties": true
            }
          },
          "project_revision": { "type": "string" }
        },
        "required": ["tasks", "project_revision"]
      },
      "TrackerTaskUpdate": {
        "type": "object",
        "properties": {
          "update_import_key": { "type": "string", "minLength": 1, "maxLength": 160, "description": "Immutable caller key for this exact update. Stored only as a one-way fingerprint." },
          "task_id": { "type": "string", "minLength": 1, "maxLength": 160 },
          "title": { "type": "string", "minLength": 1, "maxLength": 500 },
          "details": { "type": "string", "maxLength": 20000 },
          "assignee": { "oneOf": [{ "$ref": "#/components/schemas/TrackerPersonReference" }, { "type": "null" }] },
          "participants": { "type": "array", "maxItems": 100, "items": { "$ref": "#/components/schemas/TrackerPersonReference" } },
          "priority": { "oneOf": [{ "type": "string", "enum": ["Low", "Medium", "High", "Critical"] }, { "type": "null" }] },
          "milestone": { "type": "string", "maxLength": 500 },
          "sprint_start": { "type": "string", "maxLength": 80, "pattern": "^(?:|\\d{4}-\\d{2}-\\d{2})$" },
          "sprint_end": { "type": "string", "maxLength": 80, "pattern": "^(?:|\\d{4}-\\d{2}-\\d{2})$" },
          "due_date": { "type": "string", "maxLength": 80, "pattern": "^(?:|\\d{4}-\\d{2}-\\d{2})$" },
          "subtasks": { "type": "array", "maxItems": 24, "items": { "$ref": "#/components/schemas/TrackerSubtaskUpdate" } },
          "status": { "type": "string", "minLength": 1, "maxLength": 160, "description": "Must exactly match a configured project status after normalization." },
          "status_rationale": { "type": "string", "minLength": 1, "maxLength": 2000 },
          "work_links": { "type": "array", "maxItems": 100, "items": { "$ref": "#/components/schemas/TrackerWorkLink" } }
        },
        "required": ["update_import_key", "task_id", "title", "details", "assignee", "participants", "priority", "milestone", "sprint_start", "sprint_end", "due_date", "subtasks", "status", "status_rationale", "work_links"],
        "additionalProperties": false
      },
      "TrackerTaskUpdateRequest": {
        "type": "object",
        "properties": {
          "expected_project_revision": { "type": "string", "minLength": 1, "maxLength": 128 },
          "updates": { "type": "array", "minItems": 1, "maxItems": 12, "items": { "$ref": "#/components/schemas/TrackerTaskUpdate" } }
        },
        "required": ["expected_project_revision", "updates"],
        "additionalProperties": false
      },
      "TrackerTaskUpdateResponse": {
        "type": "object",
        "properties": {
          "tasks": {
            "type": "array",
            "minItems": 1,
            "maxItems": 12,
            "items": {
              "type": "object",
              "properties": { "action": { "type": "string", "enum": ["updated", "existing"] } },
              "required": ["action"],
              "additionalProperties": true
            }
          },
          "project_revision": { "type": "string" }
        },
        "required": ["tasks", "project_revision"]
      },
      "LegacyProjectTaskCreateRequest": {
        "type": "object",
        "properties": {
          "tasks": { "type": "array", "minItems": 1, "maxItems": 12, "items": { "type": "object", "additionalProperties": true } }
        },
        "required": ["tasks"],
        "additionalProperties": false
      },
      "LegacyProjectTaskCreateResponse": {
        "type": "object",
        "properties": { "tasks": { "type": "array", "items": { "type": "object", "additionalProperties": true } } },
        "required": ["tasks"]
      },
      "TrackerMilestoneImport": {
        "type": "object",
        "properties": {
          "import_key": { "type": "string", "minLength": 1, "maxLength": 160, "description": "Immutable caller key. Stored only as a one-way fingerprint." },
          "title": { "type": "string", "minLength": 1, "maxLength": 240 },
          "date": { "type": "string", "format": "date" },
          "end_date": { "type": "string", "format": "date", "description": "Optional inclusive range end; must not precede date." }
        },
        "required": ["import_key", "title", "date"],
        "additionalProperties": false
      },
      "TrackerMilestoneUpsertRequest": {
        "type": "object",
        "properties": {
          "expected_project_revision": { "type": "string", "minLength": 1, "maxLength": 128 },
          "rationale": { "type": "string", "minLength": 1, "maxLength": 2000 },
          "milestones": { "type": "array", "minItems": 1, "maxItems": 100, "items": { "$ref": "#/components/schemas/TrackerMilestoneImport" } }
        },
        "required": ["expected_project_revision", "rationale", "milestones"],
        "additionalProperties": false
      },
      "TrackerMilestoneUpsertResponse": {
        "type": "object",
        "properties": {
          "milestones": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": {
              "type": "object",
              "properties": {
                "action": { "type": "string", "enum": ["created", "existing"] },
                "id": { "type": "string" },
                "title": { "type": "string" },
                "date": { "type": "string", "format": "date" },
                "endDate": { "type": "string", "format": "date", "description": "Optional inclusive range end." }
              },
              "required": ["action", "id", "title", "date"],
              "additionalProperties": true
            }
          },
          "project_revision": { "type": "string" }
        },
        "required": ["milestones", "project_revision"]
      },
      "ProjectCalendarCreate": {
        "oneOf": [
          {
            "title": "Create milestone",
            "type": "object",
            "required": ["item_type", "expected_project_revision", "idempotency_key", "title", "date"],
            "properties": {
              "item_type": { "type": "string", "const": "milestone" },
              "expected_project_revision": { "type": "string", "minLength": 1, "maxLength": 128 },
              "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 160 },
              "title": { "type": "string", "minLength": 1, "maxLength": 240 },
              "date": { "type": "string", "format": "date" },
              "end_date": { "type": "string", "format": "date" },
              "details": { "type": "string", "maxLength": 2000 },
              "color": { "type": "string", "maxLength": 20 }
            },
            "additionalProperties": false
          },
          {
            "title": "Create manual calendar event",
            "type": "object",
            "required": ["item_type", "expected_project_revision", "idempotency_key", "title", "start_date", "kind"],
            "properties": {
              "item_type": { "type": "string", "const": "calendar_event" },
              "expected_project_revision": { "type": "string", "minLength": 1, "maxLength": 128 },
              "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 160 },
              "title": { "type": "string", "minLength": 1, "maxLength": 240 },
              "start_date": { "type": "string", "format": "date" },
              "end_date": { "type": "string", "format": "date" },
              "kind": { "type": "string", "enum": ["time_off", "company", "blocker", "other"] },
              "details": { "type": "string", "maxLength": 2000 },
              "color": { "type": "string", "maxLength": 20 },
              "person": { "type": "object", "required": ["id", "name"], "properties": { "id": { "type": "string", "minLength": 1, "maxLength": 160 }, "name": { "type": "string", "minLength": 1, "maxLength": 200 } }, "additionalProperties": false }
            },
            "additionalProperties": false
          },
          {
            "title": "Create calendar event from safe source",
            "type": "object",
            "required": ["item_type", "expected_project_revision", "idempotency_key", "source_key"],
            "properties": {
              "item_type": { "type": "string", "const": "calendar_event" },
              "expected_project_revision": { "type": "string", "minLength": 1, "maxLength": 128 },
              "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 160 },
              "source_key": { "type": "string", "pattern": "^[a-f0-9]{64}$" }
            },
            "additionalProperties": false
          }
        ]
      },
      "ProjectCalendarUpdate": {
        "oneOf": [
          {
            "title": "Update milestone",
            "type": "object",
            "required": ["item_type", "expected_project_revision", "idempotency_key"],
            "properties": {
              "item_type": { "type": "string", "const": "milestone" },
              "expected_project_revision": { "type": "string", "minLength": 1, "maxLength": 128 },
              "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 160 },
              "title": { "type": "string", "minLength": 1, "maxLength": 240 },
              "date": { "type": "string", "format": "date" },
              "end_date": { "type": "string", "format": "date" },
              "details": { "type": "string", "maxLength": 2000 },
              "color": { "type": "string", "maxLength": 20 }
            },
            "anyOf": [
              { "required": ["title"] }, { "required": ["date"] }, { "required": ["end_date"] },
              { "required": ["details"] }, { "required": ["color"] }
            ],
            "additionalProperties": false
          },
          {
            "title": "Update calendar event",
            "type": "object",
            "required": ["item_type", "expected_project_revision", "idempotency_key"],
            "properties": {
              "item_type": { "type": "string", "const": "calendar_event" },
              "expected_project_revision": { "type": "string", "minLength": 1, "maxLength": 128 },
              "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 160 },
              "title": { "type": "string", "minLength": 1, "maxLength": 240 },
              "start_date": { "type": "string", "format": "date" },
              "end_date": { "type": "string", "format": "date" },
              "kind": { "type": "string", "enum": ["time_off", "company", "blocker", "other"] },
              "details": { "type": "string", "maxLength": 2000 },
              "color": { "type": "string", "maxLength": 20 },
              "person": {
                "oneOf": [
                  { "type": "object", "required": ["id", "name"], "properties": { "id": { "type": "string", "minLength": 1, "maxLength": 160 }, "name": { "type": "string", "minLength": 1, "maxLength": 200 } }, "additionalProperties": false },
                  { "type": "null" }
                ],
                "description": "Set null to remove the optional person association."
              }
            },
            "anyOf": [
              { "required": ["title"] }, { "required": ["start_date"] }, { "required": ["end_date"] },
              { "required": ["kind"] }, { "required": ["details"] }, { "required": ["color"] },
              { "required": ["person"] }
            ],
            "additionalProperties": false
          }
        ]
      },
      "ProjectCalendarDelete": {
        "type": "object",
        "required": ["item_type", "expected_project_revision", "idempotency_key", "current_title"],
        "properties": {
          "item_type": { "type": "string", "enum": ["milestone", "calendar_event"] },
          "expected_project_revision": { "type": "string", "minLength": 1, "maxLength": 128 },
          "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 160 },
          "current_title": { "type": "string", "minLength": 1, "maxLength": 240 }
        },
        "additionalProperties": false
      },
      "ProjectCalendarListResponse": {
        "type": "object",
        "required": ["board", "project", "items", "project_revision"],
        "properties": {
          "board": { "type": "object" }, "project": { "type": "object" },
          "items": { "type": "array", "items": { "$ref": "#/components/schemas/ProjectCalendarItem" } },
          "project_revision": { "type": "string" }
        }
      },
      "ProjectCalendarSourcesResponse": {
        "type": "object",
        "required": ["sources", "project_revision"],
        "properties": {
          "sources": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/ProjectCalendarSource" }
          },
          "project_revision": { "type": "string", "description": "SHA-256 revision over the complete mutable project tracking record." }
        },
        "additionalProperties": false
      },
      "ProjectCalendarSource": {
        "type": "object",
        "required": ["sourceKey", "title", "kind", "startDate"],
        "properties": {
          "sourceKey": { "type": "string", "pattern": "^[a-f0-9]{64}$", "description": "Opaque non-sensitive source fingerprint." },
          "title": { "type": "string", "minLength": 1, "maxLength": 240 },
          "kind": { "type": "string", "enum": ["time_off", "company"] },
          "startDate": { "type": "string", "format": "date" },
          "endDate": { "type": "string", "format": "date", "description": "Optional inclusive range end; omitted for a one-day source." },
          "person": {
            "type": "object",
            "required": ["id", "name"],
            "properties": {
              "id": { "type": "string", "minLength": 1, "maxLength": 160 },
              "name": { "type": "string", "minLength": 1, "maxLength": 200 }
            },
            "additionalProperties": false
          }
        },
        "additionalProperties": false
      },
      "ProjectCalendarItem": {
        "oneOf": [
          { "$ref": "#/components/schemas/ProjectCalendarMilestone" },
          { "$ref": "#/components/schemas/ProjectCalendarEvent" }
        ],
        "discriminator": {
          "propertyName": "itemType",
          "mapping": {
            "milestone": "#/components/schemas/ProjectCalendarMilestone",
            "calendar_event": "#/components/schemas/ProjectCalendarEvent"
          }
        }
      },
      "ProjectCalendarMilestone": {
        "type": "object",
        "required": ["itemType", "id", "title", "date", "details", "createdAt"],
        "properties": {
          "itemType": { "type": "string", "const": "milestone" },
          "id": { "type": "string", "minLength": 1, "maxLength": 160 },
          "title": { "type": "string", "minLength": 1, "maxLength": 240 },
          "date": { "type": "string", "format": "date", "description": "Inclusive range start." },
          "endDate": { "type": "string", "format": "date", "description": "Optional inclusive range end; omitted for a one-day milestone." },
          "details": { "type": "string", "maxLength": 2000 },
          "color": { "type": "string", "maxLength": 20 },
          "createdAt": { "type": "string" }
        },
        "additionalProperties": false
      },
      "ProjectCalendarEvent": {
        "type": "object",
        "required": ["itemType", "id", "title", "kind", "startDate", "details", "createdAt"],
        "properties": {
          "itemType": { "type": "string", "const": "calendar_event" },
          "id": { "type": "string", "minLength": 1, "maxLength": 160 },
          "title": { "type": "string", "minLength": 1, "maxLength": 240 },
          "kind": { "type": "string", "enum": ["time_off", "company", "blocker", "other"] },
          "startDate": { "type": "string", "format": "date", "description": "Inclusive range start." },
          "endDate": { "type": "string", "format": "date", "description": "Optional inclusive range end; omitted for a one-day event." },
          "details": { "type": "string", "maxLength": 2000 },
          "color": { "type": "string", "maxLength": 20 },
          "person": { "$ref": "#/components/schemas/ProjectCalendarPerson" },
          "createdAt": { "type": "string" },
          "createdBy": { "$ref": "#/components/schemas/ProjectCalendarPerson" },
          "sourceType": { "type": "string", "enum": ["people_time_off", "company_event"] },
          "sourceFingerprint": { "type": "string", "pattern": "^[a-f0-9]{16,64}$", "description": "Non-sensitive source fingerprint retained for deduplication and audit." }
        },
        "additionalProperties": false
      },
      "ProjectCalendarPerson": {
        "type": "object",
        "required": ["id", "name"],
        "properties": {
          "id": { "type": "string", "minLength": 1, "maxLength": 160 },
          "name": { "type": "string", "minLength": 1, "maxLength": 200 }
        },
        "additionalProperties": false
      },
      "ProjectCalendarMutationResponse": {
        "type": "object",
        "required": ["ok", "project_revision", "revision", "project", "result", "generated_ids"],
        "properties": {
          "ok": { "type": "boolean", "const": true },
          "project_revision": { "type": "string" },
          "revision": { "type": "string" },
          "project": { "type": "object", "additionalProperties": true },
          "result": {
            "type": "object",
            "properties": {
              "milestoneId": { "type": "string" },
              "calendarEventId": { "type": "string" },
              "changedTaskCount": { "type": "integer", "minimum": 0 },
              "changedSubtaskCount": { "type": "integer", "minimum": 0 }
            },
            "additionalProperties": true
          },
          "generated_ids": {
            "type": "object",
            "required": ["item_id"],
            "properties": { "item_id": { "type": "string" } },
            "additionalProperties": false
          }
        },
        "additionalProperties": false
      },
      "TaskAutomationState": {
        "type": "string",
        "enum": [
          "queued",
          "cancelled"
        ]
      },
      "TaskAutomationAssignmentRequest": {
        "type": "object",
        "properties": {
          "boardId": {
            "type": "string"
          },
          "projectId": {
            "type": "string"
          },
          "taskId": {
            "type": "string"
          },
          "assigned": {
            "type": "boolean",
            "default": true
          },
          "triggerType": {
            "type": "string",
            "enum": [
              "assignment",
              "mention",
              "manual"
            ],
            "default": "assignment"
          },
          "triggerId": {
            "type": "string",
            "maxLength": 160
          },
          "idempotencyKey": {
            "type": "string",
            "maxLength": 160
          }
        },
        "required": [
          "boardId",
          "projectId",
          "taskId",
          "assigned"
        ],
        "additionalProperties": false
      },
      "TaskAttachment": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "fileExtension": { "type": "string" },
          "fileSize": { "type": ["integer", "null"], "minimum": 0 },
          "createdAt": { "type": ["string", "null"] },
          "uploadedBy": { "type": ["object", "null"], "additionalProperties": true },
          "source": { "type": "string", "enum": ["task_description", "comment"] },
          "commentId": { "type": ["string", "null"] },
          "kind": { "type": "string", "enum": ["image", "video", "pdf", "text"] },
          "contentType": { "type": "string" },
          "attachmentPath": { "type": "string", "description": "Authenticated ONE API path for the attachment bytes." },
          "imagePath": { "type": "string", "description": "Authenticated visual-image path, present only when kind is image." }
        },
        "required": ["id", "name", "kind", "contentType", "attachmentPath"]
      },
      "TaskContext": {
        "type": "object",
        "properties": {
          "taskUrl": {
            "type": "string",
            "format": "uri"
          },
          "revision": {
            "type": "string",
            "description": "SHA-256 task revision used for optimistic concurrency."
          },
          "board": {
            "type": "object",
            "additionalProperties": true
          },
          "project": {
            "type": "object",
            "additionalProperties": true
          },
          "task": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "fields": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                }
              },
              "valuesByColumnId": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                }
              },
              "automation": {
                "type": "object",
                "properties": {
                  "agentId": {
                    "type": "string",
                    "const": "agent_codex_local"
                  },
                  "agentName": {
                    "type": "string",
                    "const": "Codex"
                  },
                  "assigned": {
                    "type": "boolean"
                  },
                  "status": {
                    "oneOf": [
                      {
                        "$ref": "#/components/schemas/TaskAutomationState"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "updatedAt": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "agentId",
                  "agentName",
                  "assigned",
                  "status",
                  "updatedAt"
                ]
              },
              "comments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": true
                }
              },
              "attachments": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TaskAttachment"
                }
              },
              "images": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TaskAttachment"
                }
              }
            },
            "required": [
              "id",
              "name",
              "fields",
              "automation",
              "comments",
              "attachments",
              "images"
            ],
            "additionalProperties": true
          }
        },
        "required": [
          "taskUrl",
          "revision",
          "board",
          "project",
          "task"
        ]
      },
      "TaskCommentRequest": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 8000
          },
          "expectedRevision": {
            "type": "string"
          },
          "idempotencyKey": {
            "type": "string",
            "maxLength": 160
          },
          "agentRunId": {
            "type": "string",
            "maxLength": 160
          }
        },
        "required": [
          "text"
        ]
      },
      "TaskReviewStateRequest": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "In Progress",
              "Review"
            ]
          },
          "expectedRevision": {
            "type": "string"
          }
        },
        "required": [
          "status"
        ]
      },
      "TaskWriteResponse": {
        "type": "object",
        "properties": {
          "revision": {
            "type": "string"
          },
          "duplicate": {
            "type": "boolean"
          },
          "status": {
            "type": "string"
          },
          "comment": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "required": [
          "revision"
        ],
        "additionalProperties": true
      },
      "PersonalProfileUpdate": {
        "type": "object",
        "properties": {
          "homeEmail": { "type": ["string", "null"], "format": "email", "maxLength": 320 },
          "mobilePhone": { "type": ["string", "null"], "maxLength": 80 },
          "workPhone": { "type": ["string", "null"], "maxLength": 80 },
          "homePhone": { "type": ["string", "null"], "maxLength": 80 },
          "birthDate": { "type": ["string", "null"], "format": "date" },
          "tShirtSize": { "type": ["string", "null"], "maxLength": 40 },
          "photoUrl": { "type": ["string", "null"], "description": "Optional bounded JPEG data URL used by the browser profile editor." },
          "address": {
            "type": "object",
            "properties": {
              "street": { "type": ["string", "null"], "maxLength": 300 },
              "city": { "type": ["string", "null"], "maxLength": 160 },
              "provinceState": { "type": ["string", "null"], "maxLength": 160 },
              "postalCode": { "type": ["string", "null"], "maxLength": 40 },
              "country": { "type": ["string", "null"], "maxLength": 120 }
            },
            "additionalProperties": false
          },
          "emergencyContact": {
            "type": "object",
            "properties": {
              "name": { "type": ["string", "null"], "maxLength": 160 },
              "relationship": { "type": ["string", "null"], "maxLength": 120 },
              "email": { "type": ["string", "null"], "format": "email", "maxLength": 320 },
              "mobilePhone": { "type": ["string", "null"], "maxLength": 80 },
              "workPhone": { "type": ["string", "null"], "maxLength": 80 }
            },
            "additionalProperties": false
          }
        },
        "additionalProperties": false
      },
      "PersonalTimeOffRequestInput": {
        "type": "object",
        "required": ["timeOffType", "startDate", "endDate"],
        "properties": {
          "timeOffType": { "type": "string", "enum": ["Paid Time Off", "Sick Time", "Unpaid Time Off"] },
          "startDate": { "type": "string", "format": "date" },
          "endDate": { "type": "string", "format": "date" },
          "notes": { "type": "string", "maxLength": 2000 }
        },
        "additionalProperties": false
      },
      "PersonalHardwareRequestInput": {
        "type": "object",
        "required": ["title", "equipmentCategory", "quantity", "amount", "currency"],
        "properties": {
          "title": { "type": "string", "minLength": 1, "maxLength": 180 },
          "equipmentCategory": { "type": "string", "minLength": 1, "maxLength": 160 },
          "quantity": { "type": "integer", "minimum": 1, "maximum": 1000 },
          "amount": { "type": "number", "exclusiveMinimum": 0, "maximum": 1000000000 },
          "currency": { "type": "string", "enum": ["EUR", "USD", "GBP", "CAD", "AUD"] },
          "purpose": { "type": "string", "maxLength": 6000 },
          "neededBy": { "type": "string", "maxLength": 32 },
          "linkUrl": { "type": "string", "format": "uri", "maxLength": 2000 },
          "initialComment": { "type": "string", "maxLength": 4000 }
        },
        "additionalProperties": false
      },
      "DirectReportTimeOffDecision": {
        "type": "object",
        "required": ["decision"],
        "properties": { "decision": { "type": "string", "enum": ["approve", "deny"] } },
        "additionalProperties": false
      },
      "TimeOffPolicySettings": {
        "type": "object",
        "required": ["id", "name", "timeOffType", "annualDays", "balanceCapDays", "allowNegative"],
        "properties": {
          "id": { "type": "string", "enum": ["paid", "sick"] },
          "name": { "type": "string" },
          "timeOffType": { "type": "string" },
          "annualDays": { "type": "number" },
          "balanceCapDays": { "type": "number" },
          "carryoverCapDays": { "type": "number" },
          "resetMonth": { "type": "integer" },
          "resetDay": { "type": "integer" },
          "allowNegative": { "type": "boolean" }
        },
        "additionalProperties": true
      },
      "TimeOffAdministration": {
        "type": "object",
        "required": ["settings", "lastRunAt", "lastRunThrough", "people"],
        "properties": {
          "settings": { "type": "object", "required": ["paid", "sick"], "properties": { "paid": { "$ref": "#/components/schemas/TimeOffPolicySettings" }, "sick": { "$ref": "#/components/schemas/TimeOffPolicySettings" } }, "additionalProperties": false },
          "lastRunAt": { "type": "string" },
          "lastRunThrough": { "type": "string" },
          "people": { "type": "array", "items": { "type": "object", "required": ["personId", "personName", "workEmail", "assignments", "balances"], "properties": { "personId": { "type": "string" }, "personName": { "type": "string" }, "workEmail": { "type": "string" }, "assignments": { "type": "object", "additionalProperties": { "type": "object" } }, "balances": { "type": "array", "items": { "$ref": "#/components/schemas/PersonalTimeOffBalance" } } }, "additionalProperties": false } }
        },
        "additionalProperties": false
      },
      "TimeOffHistorySummary": {
        "type": "object",
        "required": ["total", "byCategory"],
        "properties": {
          "total": { "type": "integer", "minimum": 0 },
          "byCategory": {
            "type": "object",
            "required": ["accrual", "request", "carryover_loss", "carryover", "adjustment", "balance", "policy", "other"],
            "properties": {
              "accrual": { "type": "integer", "minimum": 0 },
              "request": { "type": "integer", "minimum": 0 },
              "carryover_loss": { "type": "integer", "minimum": 0 },
              "carryover": { "type": "integer", "minimum": 0 },
              "adjustment": { "type": "integer", "minimum": 0 },
              "balance": { "type": "integer", "minimum": 0 },
              "policy": { "type": "integer", "minimum": 0 },
              "other": { "type": "integer", "minimum": 0 }
            },
            "additionalProperties": false
          }
        },
        "additionalProperties": false
      },
      "TimeOffPersonHistory": {
        "type": "object",
        "required": ["personId", "personName", "workEmail", "source", "syncedAt", "assignments", "balances", "policies", "summary", "history"],
        "properties": {
          "personId": { "type": "string" },
          "personName": { "type": "string" },
          "workEmail": { "type": "string" },
          "source": { "type": "string" },
          "syncedAt": { "type": "string" },
          "assignments": { "type": "object", "additionalProperties": { "type": "object" } },
          "balances": { "type": "array", "items": { "$ref": "#/components/schemas/PersonalTimeOffBalance" } },
          "policies": { "type": "array", "items": { "$ref": "#/components/schemas/PersonalTimeOffPolicy" } },
          "summary": { "$ref": "#/components/schemas/TimeOffHistorySummary" },
          "history": { "type": "array", "items": { "$ref": "#/components/schemas/PersonalTimeOffEntry" } }
        },
        "additionalProperties": false
      },
      "TimeOffPolicyUpdate": {
        "type": "object",
        "properties": { "name": { "type": "string", "maxLength": 120 }, "annualDays": { "type": "number", "minimum": 0, "maximum": 100 }, "balanceCapDays": { "type": "number", "minimum": 0, "maximum": 365 }, "carryoverCapDays": { "type": "number", "minimum": 0, "maximum": 365 } },
        "additionalProperties": false
      },
      "TimeOffPolicyAssignment": {
        "type": "object",
        "required": ["enabled", "reason"],
        "properties": { "enabled": { "type": "boolean" }, "startDate": { "type": "string", "format": "date" }, "reason": { "type": "string", "minLength": 1, "maxLength": 1000 } },
        "additionalProperties": false
      },
      "TimeOffBalanceAdjustment": {
        "type": "object",
        "required": ["policyId", "balance", "date", "reason"],
        "properties": { "policyId": { "type": "string", "enum": ["paid", "sick"] }, "balance": { "type": "number", "minimum": -1000, "maximum": 1000 }, "date": { "type": "string", "format": "date" }, "reason": { "type": "string", "minLength": 1, "maxLength": 1000 } },
        "additionalProperties": false
      },
      "CompanyCalendarOutToday": {
        "type": "object",
        "required": ["personId", "personName", "timeOffType", "startDate", "endDate"],
        "properties": {
          "personId": { "type": "string" },
          "personName": { "type": "string" },
          "timeOffType": { "type": "string" },
          "startDate": { "type": "string", "format": "date" },
          "endDate": { "type": "string", "format": "date" }
        },
        "additionalProperties": false
      },
      "CompanyCalendarEvent": {
        "type": "object",
        "required": ["id", "kind", "date", "personName", "title"],
        "properties": {
          "id": { "type": "string" },
          "kind": { "type": "string", "enum": ["birthday", "anniversary", "out"] },
          "date": { "type": "string", "format": "date" },
          "endDate": { "type": "string", "format": "date" },
          "personName": { "type": "string" },
          "title": { "type": "string" },
          "timeOffType": { "type": "string" },
          "years": { "type": "integer", "minimum": 1 }
        },
        "additionalProperties": false
      },
      "CompanyCalendar": {
        "type": "object",
        "required": ["today", "outToday", "events"],
        "properties": {
          "today": { "type": "string", "format": "date" },
          "outToday": { "type": "array", "items": { "$ref": "#/components/schemas/CompanyCalendarOutToday" } },
          "events": { "type": "array", "items": { "$ref": "#/components/schemas/CompanyCalendarEvent" } }
        },
        "additionalProperties": false
      },
      "PersonalWorkspace": {
        "type": "object",
        "required": ["profile", "general", "timeOff", "hardware", "approvals"],
        "properties": {
          "profile": {
            "type": "object",
            "additionalProperties": true
          },
          "general": {
            "type": "object",
            "required": ["companyLinks", "calendar"],
            "properties": {
              "companyLinks": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
              "calendar": { "$ref": "#/components/schemas/CompanyCalendar" }
            },
            "additionalProperties": true
          },
          "timeOff": {
            "type": "object",
            "required": ["balances", "requests", "history", "accruals", "carryoverLosses", "policies", "source", "syncedAt"],
            "properties": {
              "balances": { "type": "array", "items": { "$ref": "#/components/schemas/PersonalTimeOffBalance" } },
              "requests": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
              "history": { "type": "array", "items": { "$ref": "#/components/schemas/PersonalTimeOffEntry" } },
              "accruals": { "type": "array", "items": { "$ref": "#/components/schemas/PersonalTimeOffEntry" } },
              "carryoverLosses": { "type": "array", "items": { "$ref": "#/components/schemas/PersonalTimeOffEntry" } },
              "policies": { "type": "array", "items": { "$ref": "#/components/schemas/PersonalTimeOffPolicy" } },
              "source": { "type": "string" },
              "syncedAt": { "type": "string", "format": "date-time" },
              "admin": { "oneOf": [{ "$ref": "#/components/schemas/TimeOffAdministration" }, { "type": "null" }] }
            },
            "additionalProperties": true
          },
          "hardware": {
            "type": "object",
            "required": ["assigned", "requests"],
            "properties": {
              "assigned": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
              "requests": { "type": "array", "items": { "type": "object", "additionalProperties": true } }
            },
            "additionalProperties": true
          },
          "approvals": {
            "type": "object",
            "required": ["directReports", "timeOff"],
            "properties": {
              "directReports": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
              "timeOff": { "type": "array", "items": { "type": "object", "additionalProperties": true } }
            },
            "additionalProperties": true
          }
        },
        "additionalProperties": false
      },
      "PersonalTimeOffBalance": {
        "type": "object",
        "required": ["type", "policyName", "synced", "usedThisYear"],
        "properties": {
          "type": { "type": "string" },
          "policyName": { "type": "string" },
          "balance": { "type": "number", "description": "Current ONE ledger balance in working days when recorded." },
          "synced": { "type": "boolean" },
          "usedThisYear": { "type": "number", "description": "Approved usage in the current calendar year, using explicit ledger totals when available." }
        },
        "additionalProperties": false
      },
      "PersonalTimeOffEntry": {
        "type": "object",
        "required": ["id", "date", "eventType", "eventCategory", "timeOffType", "description", "units", "policyName", "policyId", "timeOffTypeId", "startDate", "endDate", "status", "notes", "requestedAt"],
        "properties": {
          "id": { "type": "string" },
          "date": { "type": "string" },
          "eventType": { "type": "string" },
          "eventCategory": { "type": "string", "enum": ["accrual", "request", "carryover_loss", "carryover", "adjustment", "balance", "policy", "other"] },
          "timeOffType": { "type": "string" },
          "description": { "type": "string" },
          "usedDays": { "type": "number" },
          "earnedDays": { "type": "number" },
          "balance": { "type": "number" },
          "usedYearToDate": { "type": "number", "description": "Explicit ledger usage for the calendar year in working days when present." },
          "changeDays": { "type": "number", "description": "Signed balance change for automatic and manual events." },
          "units": { "type": "string", "const": "days" },
          "policyName": { "type": "string" },
          "policyId": { "type": "string" },
          "policyType": { "type": "string", "description": "Legacy imported policy classification when present." },
          "timeOffTypeId": { "type": "string" },
          "startDate": { "type": "string" },
          "endDate": { "type": "string" },
          "status": { "type": "string" },
          "notes": { "type": "string" },
          "requestedAt": { "type": "string" },
          "reason": { "type": "string" },
          "automated": { "type": "boolean" }
        },
        "additionalProperties": false
      },
      "PersonalTimeOffPolicy": {
        "type": "object",
        "required": ["type", "timeOffType", "policyName", "policyId", "startedOn", "accrualMode", "explanation"],
        "properties": {
          "type": { "type": "string" },
          "timeOffType": { "type": "string" },
          "policyName": { "type": "string" },
          "policyId": { "type": "string" },
          "startedOn": { "type": "string" },
          "assigned": { "type": "boolean" },
          "accrualMode": { "type": "string", "enum": ["automatic", "not-assigned", "no-accrual", "managed-in-bamboohr"] },
          "explanation": { "type": "string" }
        },
        "additionalProperties": false
      },
      "BackupStats": {
        "type": "object",
        "properties": {
          "boards": { "type": "integer", "minimum": 0 },
          "items": { "type": "integer", "minimum": 0 },
          "tasks": { "type": "integer", "minimum": 0 },
          "updates": { "type": "integer", "minimum": 0 },
          "hiringJobs": { "type": "integer", "minimum": 0 },
          "hiringApplications": { "type": "integer", "minimum": 0 },
          "hiringTalentPools": { "type": "integer", "minimum": 0 },
          "hiringBytes": { "type": "integer", "minimum": 0 },
          "dataRoots": { "type": "integer", "minimum": 0 },
          "bytes": { "type": "integer", "minimum": 0 }
        },
        "additionalProperties": false
      },
      "BackupSummary": {
        "type": "object",
        "required": ["id", "version", "mode", "label", "source", "createdAt", "contentPolicy", "rootNames", "stats"],
        "properties": {
          "id": { "type": "string" },
          "version": { "type": "integer" },
          "mode": { "type": "string", "enum": ["compact", "full"] },
          "label": { "type": "string" },
          "source": { "type": "string" },
          "createdAt": { "type": "string", "format": "date-time" },
          "createdByUid": { "type": "string" },
          "createdByEmail": { "type": "string" },
          "createdByName": { "type": "string" },
          "contentPolicy": { "type": "string", "const": "data_only" },
          "boardSignature": { "type": "string" },
          "rootNames": {
            "type": "array",
            "items": { "type": "string" }
          },
          "stats": { "$ref": "#/components/schemas/BackupStats" }
        },
        "additionalProperties": false
      },
      "BackupListResponse": {
        "type": "object",
        "required": ["ok", "backups", "nextCursor"],
        "properties": {
          "ok": { "type": "boolean", "const": true },
          "backups": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/BackupSummary" }
          },
          "nextCursor": {
            "oneOf": [
              { "type": "string" },
              { "type": "null" }
            ]
          }
        },
        "additionalProperties": false
      },
      "BackupMetadataResponse": {
        "type": "object",
        "required": ["ok", "backup"],
        "properties": {
          "ok": { "type": "boolean", "const": true },
          "backup": { "$ref": "#/components/schemas/BackupSummary" }
        },
        "additionalProperties": false
      },
      "BackupExport": {
        "type": "object",
        "required": ["app", "version", "exportedAt", "backup"],
        "properties": {
          "app": { "type": "string", "const": "ONE" },
          "version": { "type": "integer", "const": 1 },
          "exportedAt": { "type": "string", "format": "date-time" },
          "backup": {
            "type": "object",
            "description": "Complete protected backup snapshot, including workspace and dataRoots, in the same shape accepted by the ONE Backups panel.",
            "additionalProperties": true
          }
        },
        "additionalProperties": false
      },
      "Health": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "service": {
            "type": "string",
            "const": "geocrm-api"
          }
        },
        "required": [
          "ok",
          "service"
        ]
      },
      "AppInfo": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "const": "ONE"
          },
          "product": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "urls": {
            "type": "object",
            "properties": {
              "primaryApp": {
                "type": "string",
                "format": "uri",
                "description": "Primary ONE website and login page."
              },
              "defaultHostingApp": {
                "type": "string",
                "format": "uri",
                "description": "Firebase Hosting fallback URL."
              },
              "apiBase": {
                "type": "string",
                "format": "uri"
              },
              "bridge": {
                "type": "string",
                "format": "uri"
              },
              "docs": {
                "type": "string",
                "format": "uri"
              },
              "llms": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "mcpManifest": {
                "type": "string",
                "format": "uri"
              }
            },
            "required": [
              "primaryApp",
              "defaultHostingApp",
              "apiBase",
              "bridge",
              "docs",
              "llms",
              "openapi",
              "mcpManifest"
            ]
          },
          "answerHints": {
            "type": "object",
            "properties": {
              "websiteQuestion": {
                "type": "string",
                "description": "Short natural-language answer for ONE website/login URL questions."
              }
            }
          }
        },
        "required": [
          "name",
          "product",
          "description",
          "urls",
          "answerHints"
        ]
      },
      "AppInfoResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "service": {
            "type": "string",
            "const": "geocrm-api"
          },
          "app": {
            "$ref": "#/components/schemas/AppInfo"
          }
        },
        "required": [
          "ok",
          "service",
          "app"
        ]
      },
      "BrandStandardsResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "standards": {
            "type": "object",
            "properties": {
              "schemaVersion": { "type": "string" },
              "brand": { "type": "string", "const": "GeoTech" },
              "title": { "type": "string" },
              "effectiveDate": { "type": "string", "format": "date" },
              "source": { "type": "object", "additionalProperties": true },
              "identity": { "type": "object", "additionalProperties": true },
              "requiredUsage": { "type": "object", "additionalProperties": true },
              "logo": { "type": "object", "additionalProperties": true },
              "colours": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "name": { "type": "string" },
                    "hex": { "type": "string", "pattern": "^#[0-9A-F]{6}$" },
                    "rgb": { "type": "array", "items": { "type": "integer" }, "minItems": 3, "maxItems": 3 },
                    "cmyk": { "type": "array", "items": { "type": "integer" }, "minItems": 4, "maxItems": 4 },
                    "pantone": { "type": "string" }
                  },
                  "required": ["name", "hex", "rgb", "cmyk", "pantone"]
                }
              },
              "typography": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
              "designSystem": {
                "type": "object",
                "properties": {
                  "title": { "type": "string" },
                  "description": { "type": "string" },
                  "appliesTo": { "type": "array", "items": { "type": "string" } },
                  "foundations": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
                  "workflow": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
                  "guardrails": { "type": "array", "items": { "type": "string" } },
                  "pages": {
                    "type": "object",
                    "description": "The Cover, Getting Started, Foundations, and Tokens design-system pages.",
                    "properties": {
                      "cover": { "type": "object", "additionalProperties": true },
                      "gettingStarted": { "type": "object", "additionalProperties": true },
                      "foundations": { "type": "object", "additionalProperties": true },
                      "tokens": { "type": "object", "additionalProperties": true }
                    },
                    "required": ["cover", "gettingStarted", "foundations", "tokens"]
                  },
                  "tokenCollections": {
                    "type": "array",
                    "description": "All 89 design variables grouped into Brand, Color, Scale, and Typography collections.",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": { "type": "string", "enum": ["Brand", "Color", "Scale", "Typography"] },
                        "role": { "type": "string" },
                        "modes": { "type": "array", "items": { "type": "string" } },
                        "tokens": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "name": { "type": "string" },
                              "resolvedType": { "type": "string", "enum": ["COLOR", "FLOAT", "STRING"] },
                              "scopes": { "type": "array", "items": { "type": "string" } },
                              "codeSyntax": {
                                "type": "object",
                                "properties": { "web": { "type": "string" } },
                                "required": ["web"]
                              },
                              "values": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "mode": { "type": "string" },
                                    "value": { "oneOf": [{ "type": "string" }, { "type": "number" }] },
                                    "alias": { "type": "string" }
                                  },
                                  "required": ["mode", "value"]
                                }
                              },
                              "unit": { "type": "string" }
                            },
                            "required": ["name", "resolvedType", "scopes", "codeSyntax", "values"]
                          }
                        }
                      },
                      "required": ["name", "role", "modes", "tokens"]
                    }
                  },
                  "visualLanguage": { "type": "object", "additionalProperties": true }
                },
                "required": ["title", "description", "appliesTo", "foundations", "workflow", "guardrails", "pages", "tokenCollections", "visualLanguage"]
              },
              "pattern": { "type": "object", "additionalProperties": true },
              "resources": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
              "agentAccess": { "type": "object", "additionalProperties": true }
            },
            "required": ["schemaVersion", "brand", "title", "effectiveDate", "source", "requiredUsage", "logo", "colours", "typography", "designSystem", "pattern", "resources", "agentAccess"]
          }
        },
        "required": ["ok", "standards"]
      },
      "ApiKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": ["assigned_tasks", "member_mcp"]
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "read",
                "write",
                "tasks:read",
                "tasks:write",
                "tasks:comment",
                "tasks:review",
                "tasks:run",
                "brain_dump:read",
                "brain_dump:write",
                "finance:read",
                "finance:write",
                "finance:invoices:send",
                "finance:suggest",
                "finance:apply",
                "finance:evidence:read",
                "finance:evidence:write",
                "decks:read",
                "decks:write",
                "decks:publish",
                "decks:access-admin",
                "backups:read",
                "backups:write",
                "tasks:create",
                "tasks:milestones:write",
                "tasks:import_status",
                "tasks:update_assigned",
                "tasks:comment_assigned",
                "tasks:review_assigned"
              ]
            }
          },
          "prefix": {
            "type": "string"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "allowedBoardIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional board allowlist for task-scoped or Brain Dump-only keys. Empty means all boards."
          },
          "allowedProjects": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "boardId": { "type": "string" },
                "projectId": { "type": "string" }
              },
              "required": ["boardId", "projectId"],
              "additionalProperties": false
            },
            "description": "Exact board/project allowlist. Required and non-empty for tasks-profile tracker creation with tasks:create, tasks:milestones:write, and tasks:import_status."
          }
        },
        "required": [
          "id",
          "name",
          "scopes"
        ]
      },
      "LogEntry": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "at": {
            "type": "string",
            "format": "date-time"
          },
          "atMs": {
            "type": "integer"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAtMs": {
            "type": "integer"
          },
          "level": {
            "type": "string",
            "enum": [
              "debug",
              "info",
              "warn",
              "error"
            ]
          },
          "category": {
            "type": "string",
            "enum": [
              "app",
              "llm",
              "connector",
              "system"
            ]
          },
          "connector": {
            "type": "string",
            "description": "Connector or integration name, such as slack, gmail, openrouter, codex, api, or web."
          },
          "source": {
            "type": "string",
            "description": "Source component, such as web, bridge, mcp, or geoCrmApi."
          },
          "message": {
            "type": "string"
          },
          "details": {
            "description": "Optional diagnostic details. Do not include secrets or live tokens."
          },
          "userUid": {
            "type": "string"
          },
          "userEmail": {
            "type": "string"
          },
          "apiKeyId": {
            "type": "string"
          },
          "apiKeyName": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "at",
          "atMs",
          "level",
          "category",
          "source",
          "message"
        ]
      },
      "LogListResponse": {
        "type": "object",
        "properties": {
          "retentionSeconds": {
            "type": "integer",
            "const": 3600
          },
          "pruned": {
            "type": "integer"
          },
          "window": {
            "type": "object",
            "properties": {
              "from": {
                "type": "string",
                "format": "date-time"
              },
              "to": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "filters": {
            "type": "object"
          },
          "logs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LogEntry"
            }
          }
        },
        "required": [
          "retentionSeconds",
          "window",
          "logs"
        ]
      },
      "WriteLogRequest": {
        "type": "object",
        "properties": {
          "level": {
            "type": "string",
            "enum": [
              "debug",
              "info",
              "warn",
              "error"
            ],
            "default": "info"
          },
          "category": {
            "type": "string",
            "enum": [
              "app",
              "llm",
              "connector",
              "system"
            ],
            "default": "system"
          },
          "connector": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "default": "api"
          },
          "message": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2000
          },
          "details": {
            "description": "Optional JSON-serializable diagnostic details. Do not include secrets or live tokens."
          },
          "at": {
            "type": "string",
            "format": "date-time"
          },
          "atMs": {
            "type": "integer"
          }
        },
        "required": [
          "message"
        ]
      },
      "WriteLogResponse": {
        "type": "object",
        "properties": {
          "retentionSeconds": {
            "type": "integer",
            "const": 3600
          },
          "log": {
            "$ref": "#/components/schemas/LogEntry"
          }
        },
        "required": [
          "retentionSeconds",
          "log"
        ]
      },
      "BoardStructureContext": {
        "type": "object",
        "properties": {
          "directoryRevision": {
            "type": "string",
            "description": "Canonical SHA-256 revision for board creation and reorder concurrency."
          },
          "reorderableBoardIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Complete current ordered board-ID set accepted by the reorder operation."
          }
        },
        "required": [
          "directoryRevision",
          "reorderableBoardIds"
        ]
      },
      "CreateBoardRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 300
          },
          "description": {
            "type": "string",
            "maxLength": 2000
          },
          "expectedDirectoryRevision": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "name",
          "expectedDirectoryRevision"
        ]
      },
      "CreateBoardResponse": {
        "type": "object",
        "properties": {
          "created": {
            "type": "boolean"
          },
          "board": {
            "$ref": "#/components/schemas/BoardSummary"
          },
          "structure": {
            "$ref": "#/components/schemas/BoardStructureContext"
          }
        },
        "required": [
          "created",
          "board",
          "structure"
        ]
      },
      "RenameBoardRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 300
          },
          "expectedRevision": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "name",
          "expectedRevision"
        ]
      },
      "RenameBoardResponse": {
        "type": "object",
        "properties": {
          "renamed": {
            "type": "boolean"
          },
          "board": {
            "$ref": "#/components/schemas/BoardSummary"
          }
        },
        "required": [
          "renamed",
          "board"
        ]
      },
      "ReorderBoardsRequest": {
        "type": "object",
        "properties": {
          "orderedBoardIds": {
            "type": "array",
            "minItems": 1,
            "maxItems": 500,
            "uniqueItems": true,
            "items": {
              "type": "string"
            }
          },
          "expectedDirectoryRevision": {
            "type": "string",
            "minLength": 1
          },
          "dryRun": {
            "type": "boolean",
            "default": true
          }
        },
        "required": [
          "orderedBoardIds",
          "expectedDirectoryRevision"
        ]
      },
      "ReorderBoardsResponse": {
        "type": "object",
        "properties": {
          "dryRun": {
            "type": "boolean"
          },
          "changed": {
            "type": "integer"
          },
          "changes": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "boardId": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "from": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "to": {
                  "type": "number"
                }
              },
              "required": [
                "boardId",
                "name",
                "from",
                "to"
              ]
            }
          },
          "structure": {
            "$ref": "#/components/schemas/BoardStructureContext"
          }
        },
        "required": [
          "dryRun",
          "changed",
          "changes",
          "structure"
        ]
      },
      "RenameColumnRequest": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 160
          },
          "expectedRevision": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "title",
          "expectedRevision"
        ]
      },
      "RenameColumnResponse": {
        "type": "object",
        "properties": {
          "renamed": {
            "type": "boolean"
          },
          "column": {
            "$ref": "#/components/schemas/Column"
          },
          "board": {
            "$ref": "#/components/schemas/BoardSummary"
          }
        },
        "required": [
          "renamed",
          "column",
          "board"
        ]
      },
      "DuplicateItemRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 500,
            "description": "Optional duplicate name; defaults to the source name plus ' copy'."
          },
          "expectedRevision": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "expectedRevision"
        ]
      },
      "DuplicateItemResponse": {
        "type": "object",
        "properties": {
          "duplicated": {
            "type": "boolean"
          },
          "source": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "revision": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "revision"
            ]
          },
          "item": {
            "$ref": "#/components/schemas/ItemDetail"
          },
          "skippedManagedFiles": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "duplicated",
          "source",
          "item",
          "skippedManagedFiles"
        ]
      },
      "EditItemUpdateRequest": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1
          },
          "expectedRevision": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "text",
          "expectedRevision"
        ]
      },
      "EditItemUpdateResponse": {
        "type": "object",
        "properties": {
          "edited": {
            "type": "boolean"
          },
          "update": {
            "$ref": "#/components/schemas/Update"
          },
          "itemRevision": {
            "type": "string"
          }
        },
        "required": [
          "edited",
          "update",
          "itemRevision"
        ]
      },
      "DeleteItemUpdateRequest": {
        "type": "object",
        "properties": {
          "confirmText": {
            "type": "string",
            "description": "Must exactly match the current update text."
          },
          "expectedRevision": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "confirmText",
          "expectedRevision"
        ]
      },
      "DeleteItemUpdateResponse": {
        "type": "object",
        "properties": {
          "deleted": {
            "type": "boolean"
          },
          "update": {
            "$ref": "#/components/schemas/Update"
          },
          "itemRevision": {
            "type": "string"
          }
        },
        "required": [
          "deleted",
          "update",
          "itemRevision"
        ]
      },
      "BoardSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "itemCount": {
            "type": "integer"
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "position": {
            "type": [
              "number",
              "null"
            ]
          },
          "revision": {
            "type": "string",
            "description": "Canonical SHA-256 structural revision required by board and column mutations."
          },
          "columns": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Column"
            }
          },
          "groups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Group"
            }
          }
        },
        "required": [
          "id",
          "name",
          "itemCount",
          "revision",
          "columns",
          "groups"
        ]
      },
      "DeleteBoardRequest": {
        "type": "object",
        "properties": {
          "confirmName": {
            "type": "string",
            "minLength": 1,
            "description": "Must match the board name."
          },
          "reason": {
            "type": "string",
            "description": "Optional audit reason stored with the archived board copy."
          },
          "expectedRevision": {
            "type": "string",
            "minLength": 1,
            "description": "Exact current board revision returned by GET /boards/{boardId}."
          }
        },
        "required": [
          "confirmName",
          "expectedRevision"
        ]
      },
      "DeleteBoardResponse": {
        "type": "object",
        "properties": {
          "deleted": {
            "type": "boolean"
          },
          "board": {
            "$ref": "#/components/schemas/BoardSummary"
          },
          "deletedAt": {
            "type": "string",
            "format": "date-time"
          },
          "deletedBy": {
            "type": "object",
            "additionalProperties": true
          },
          "archivedPath": {
            "type": "string"
          }
        },
        "required": [
          "deleted",
          "board",
          "deletedAt",
          "deletedBy",
          "archivedPath"
        ]
      },
      "Column": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "type": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "title",
          "type"
        ]
      },
      "EnsureColumnRequest": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1
          },
          "type": {
            "type": "string",
            "default": "text"
          },
          "id": {
            "type": "string",
            "description": "Optional explicit column ID."
          },
          "expectedRevision": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "title",
          "expectedRevision"
        ]
      },
      "EnsureColumnResponse": {
        "type": "object",
        "properties": {
          "column": {
            "$ref": "#/components/schemas/Column"
          },
          "created": {
            "type": "boolean"
          },
          "board": {
            "$ref": "#/components/schemas/BoardSummary"
          }
        },
        "required": [
          "column",
          "created",
          "board"
        ]
      },
      "ArchiveColumnRequest": {
        "type": "object",
        "properties": {
          "confirmTitle": {
            "type": "string",
            "minLength": 1,
            "description": "Must match the current column title."
          },
          "expectedRevision": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "confirmTitle",
          "expectedRevision"
        ]
      },
      "ArchiveColumnResponse": {
        "type": "object",
        "properties": {
          "archived": {
            "type": "boolean"
          },
          "column": {
            "$ref": "#/components/schemas/Column"
          },
          "board": {
            "$ref": "#/components/schemas/BoardSummary"
          }
        },
        "required": [
          "archived",
          "column",
          "board"
        ]
      },
      "FieldMap": {
        "type": "object",
        "additionalProperties": {
          "type": [
            "string",
            "number",
            "boolean",
            "null"
          ]
        }
      },
      "FieldFilterMap": {
        "type": "object",
        "additionalProperties": {
          "oneOf": [
            {
              "type": [
                "string",
                "number",
                "boolean",
                "null"
              ]
            },
            {
              "type": "array",
              "items": {
                "type": [
                  "string",
                  "number",
                  "boolean",
                  "null"
                ]
              }
            }
          ]
        },
        "description": "Exact field filters keyed by column ID or column title. Array values match any listed value."
      },
      "Group": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "title"
        ]
      },
      "ItemSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "boardId": {
            "type": "string"
          },
          "boardName": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "group": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "title": {
                "type": "string"
              }
            }
          },
          "state": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "revision": {
            "type": "string",
            "description": "Canonical item revision used by guarded item operations."
          },
          "fields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "valuesByColumnId": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "updateCount": {
            "type": "integer"
          }
        },
        "required": [
          "id",
          "boardId",
          "boardName",
          "name",
          "revision",
          "fields",
          "valuesByColumnId",
          "updateCount"
        ]
      },
      "ItemDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ItemSummary"
          },
          {
            "type": "object",
            "properties": {
              "updates": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Update"
                }
              },
              "assets": {
                "type": "array",
                "items": {
                  "type": "object"
                }
              },
              "subitems": {
                "type": "array",
                "items": {
                  "type": "object"
                }
              }
            },
            "required": [
              "updates",
              "assets",
              "subitems"
            ]
          }
        ]
      },
      "UpsertContactRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Contact display name."
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Primary contact email. Used for duplicate detection when provided."
          },
          "companyName": {
            "type": "string",
            "description": "Company name or lookup text. Existing Companies rows are matched by name or domain text."
          },
          "companyDomain": {
            "type": "string",
            "description": "Optional company domain, such as thefamousgroup.com."
          },
          "fields": {
            "$ref": "#/components/schemas/FieldMap"
          },
          "companyFields": {
            "$ref": "#/components/schemas/FieldMap"
          },
          "note": {
            "type": "string",
            "description": "Optional contact update note."
          }
        },
        "required": [
          "name"
        ]
      },
      "UpsertContactResponse": {
        "type": "object",
        "properties": {
          "contact": {
            "$ref": "#/components/schemas/ItemDetail"
          },
          "company": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ItemSummary"
              },
              {
                "type": "null"
              }
            ]
          },
          "createdContact": {
            "type": "boolean"
          },
          "createdCompany": {
            "type": "boolean"
          }
        },
        "required": [
          "contact",
          "company",
          "createdContact",
          "createdCompany"
        ]
      },
      "DuplicateCandidateResponse": {
        "type": "object",
        "properties": {
          "board": {
            "$ref": "#/components/schemas/BoardSummary"
          },
          "candidateGroups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactDuplicateGroup"
            }
          },
          "totalCandidateGroups": {
            "type": "integer"
          },
          "nameThreshold": {
            "type": "number"
          }
        },
        "required": [
          "board",
          "candidateGroups",
          "totalCandidateGroups",
          "nameThreshold"
        ]
      },
      "ContactDuplicateGroup": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string"
          },
          "reason": {
            "type": "string",
            "enum": [
              "shared_email",
              "shared_phone",
              "same_name",
              "similar_name"
            ]
          },
          "confidence": {
            "type": "string",
            "enum": [
              "high",
              "medium"
            ]
          },
          "similarity": {
            "type": "number",
            "description": "Present for similar-name matches."
          },
          "emails": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "phones": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "normalizedName": {
            "type": "string"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemSummary"
            }
          }
        },
        "required": [
          "key",
          "reason",
          "confidence",
          "items"
        ]
      },
      "BoardItemDuplicateMergeRequest": {
        "type": "object",
        "properties": {
          "primaryItemId": {
            "type": "string",
            "description": "Primary board item ID to keep."
          },
          "duplicateItemIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "description": "Duplicate board item IDs to merge into the primary item."
          },
          "dryRun": {
            "type": "boolean",
            "default": false,
            "description": "Preview the merge without writing to Firebase."
          },
          "mergedCandidatesColumnTitle": {
            "type": "string",
            "default": "Merged candidate entities"
          }
        },
        "required": [
          "primaryItemId",
          "duplicateItemIds"
        ]
      },
      "BoardItemDuplicateMergeResponse": {
        "type": "object",
        "properties": {
          "dryRun": {
            "type": "boolean"
          },
          "board": {
            "$ref": "#/components/schemas/BoardSummary"
          },
          "primaryItem": {
            "$ref": "#/components/schemas/ItemDetail"
          },
          "mergedItemIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "createdColumns": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Column"
            }
          },
          "mergedCandidatesColumn": {
            "$ref": "#/components/schemas/Column"
          },
          "plannedUpdateCount": {
            "type": "integer"
          },
          "auditUpdate": {
            "$ref": "#/components/schemas/Update"
          }
        },
        "required": [
          "dryRun",
          "board",
          "primaryItem",
          "mergedItemIds",
          "createdColumns",
          "mergedCandidatesColumn",
          "plannedUpdateCount",
          "auditUpdate"
        ]
      },
      "ContactDuplicateMergeRequest": {
        "type": "object",
        "properties": {
          "boardId": {
            "type": "string",
            "description": "Optional Contacts board ID. Defaults to the board named Contacts."
          },
          "primaryItemId": {
            "type": "string",
            "description": "Primary contact item ID to keep."
          },
          "duplicateItemIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "description": "Duplicate contact item IDs to merge into the primary contact."
          },
          "dryRun": {
            "type": "boolean",
            "default": false,
            "description": "Preview the merge without writing to Firebase."
          },
          "secondaryEmailsColumnTitle": {
            "type": "string",
            "default": "Secondary emails"
          },
          "mergedCandidatesColumnTitle": {
            "type": "string",
            "default": "Merged candidate entities"
          }
        },
        "required": [
          "primaryItemId",
          "duplicateItemIds"
        ]
      },
      "ContactDuplicateMergeResponse": {
        "type": "object",
        "properties": {
          "dryRun": {
            "type": "boolean"
          },
          "board": {
            "$ref": "#/components/schemas/BoardSummary"
          },
          "primaryItem": {
            "$ref": "#/components/schemas/ItemDetail"
          },
          "mergedItemIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "secondaryEmails": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "createdColumns": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Column"
            }
          },
          "mergedCandidatesColumn": {
            "$ref": "#/components/schemas/Column"
          },
          "plannedUpdateCount": {
            "type": "integer"
          },
          "auditUpdate": {
            "$ref": "#/components/schemas/Update"
          }
        },
        "required": [
          "dryRun",
          "board",
          "primaryItem",
          "mergedItemIds",
          "secondaryEmails",
          "createdColumns",
          "mergedCandidatesColumn",
          "plannedUpdateCount",
          "auditUpdate"
        ]
      },
      "Update": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "revision": {
            "type": "string",
            "description": "Canonical update revision required by edit and delete operations."
          },
          "creator": {
            "type": [
              "object",
              "null"
            ]
          },
          "replies": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "required": [
          "id",
          "text",
          "revision"
        ]
      },
      "ItemFileRecord": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "boardId": {
            "type": "string"
          },
          "itemId": {
            "type": "string"
          },
          "columnId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "contentType": {
            "type": "string"
          },
          "size": {
            "type": "integer",
            "minimum": 1,
            "maximum": 20971520
          },
          "sha256": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "source": {
            "type": "string",
            "enum": [
              "upload",
              "google_drive"
            ]
          },
          "sourceName": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "downloadPath": {
            "type": "string",
            "description": "Authenticated relative API path. No storage path or public token is exposed."
          }
        },
        "required": [
          "id",
          "boardId",
          "itemId",
          "columnId",
          "name",
          "contentType",
          "size",
          "sha256",
          "source",
          "createdAt",
          "downloadPath"
        ]
      },
      "SetFileFieldRequest": {
        "type": "object",
        "properties": {
          "columnTitle": {
            "type": "string",
            "default": "Picture"
          },
          "columnId": {
            "type": "string"
          },
          "fileName": {
            "type": "string",
            "minLength": 1
          },
          "mimeType": {
            "type": "string",
            "default": "application/octet-stream"
          },
          "dataUrl": {
            "type": "string",
            "description": "Data URL for authenticated ONE-only storage."
          },
          "url": {
            "type": "string",
            "description": "External URL for linked file storage."
          },
          "thumbnailUrl": {
            "type": "string"
          },
          "thumbnailDataUrl": {
            "type": "string"
          },
          "fileSize": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "fileName"
        ]
      },
      "SetFileFieldResponse": {
        "type": "object",
        "properties": {
          "item": {
            "$ref": "#/components/schemas/ItemDetail"
          },
          "column": {
            "$ref": "#/components/schemas/Column"
          },
          "asset": {
            "type": "object"
          }
        },
        "required": [
          "item",
          "column",
          "asset"
        ]
      },
      "UpdateItemRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "fields": {
            "type": "object",
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "boolean",
                "null"
              ]
            },
            "description": "Field values keyed by column ID or column title."
          }
        },
        "minProperties": 1
      },
      "MoveItemsRequest": {
        "type": "object",
        "properties": {
          "itemIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional explicit item IDs to consider."
          },
          "query": {
            "type": "string",
            "description": "Optional text query that matching items must satisfy."
          },
          "fieldFilters": {
            "$ref": "#/components/schemas/FieldFilterMap"
          },
          "status": {
            "type": "string",
            "description": "Convenience shortcut for fieldFilters.Status."
          },
          "fromGroupId": {
            "type": "string",
            "description": "Optional source group ID, or active/archived virtual group."
          },
          "fromGroupTitle": {
            "type": "string",
            "description": "Optional source group title, or Active/Archived."
          },
          "toGroupId": {
            "type": "string",
            "description": "Target group ID. Use archived to move into the Archived section."
          },
          "toGroupTitle": {
            "type": "string",
            "description": "Target group title. Use Archived to move into the Archived section."
          },
          "dryRun": {
            "type": "boolean",
            "default": false,
            "description": "Preview matched items without writing changes."
          },
          "maxItems": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500,
            "default": 500,
            "description": "Safety cap for moved items."
          },
          "reason": {
            "type": "string",
            "description": "Optional audit reason appended to each moved item update."
          }
        },
        "anyOf": [
          {
            "required": [
              "itemIds"
            ]
          },
          {
            "required": [
              "fieldFilters"
            ]
          },
          {
            "required": [
              "status"
            ]
          },
          {
            "required": [
              "fromGroupId"
            ]
          },
          {
            "required": [
              "fromGroupTitle"
            ]
          },
          {
            "required": [
              "query"
            ]
          }
        ],
        "example": {
          "toGroupTitle": "Archived",
          "fieldFilters": {
            "Status": "Done"
          },
          "dryRun": true
        }
      },
      "MoveItemsResponse": {
        "type": "object",
        "properties": {
          "dryRun": {
            "type": "boolean"
          },
          "board": {
            "$ref": "#/components/schemas/BoardSummary"
          },
          "targetGroup": {
            "$ref": "#/components/schemas/Group"
          },
          "sourceGroup": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Group"
              },
              {
                "type": "null"
              }
            ]
          },
          "fieldFilters": {
            "$ref": "#/components/schemas/FieldFilterMap"
          },
          "query": {
            "type": [
              "string",
              "null"
            ]
          },
          "maxItems": {
            "type": "integer"
          },
          "matchedItemCount": {
            "type": "integer"
          },
          "movedItemCount": {
            "type": "integer"
          },
          "skippedAlreadyInTargetCount": {
            "type": "integer"
          },
          "exceedsMaxItems": {
            "type": "boolean"
          },
          "movedItemIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "movedItems": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemSummary"
            }
          },
          "createdGroup": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Group"
              },
              {
                "type": "null"
              }
            ]
          },
          "plannedUpdateCount": {
            "type": "integer"
          },
          "auditNote": {
            "type": "string"
          }
        },
        "required": [
          "dryRun",
          "board",
          "targetGroup",
          "matchedItemCount",
          "movedItemCount",
          "movedItemIds",
          "movedItems"
        ]
      },
      "AddUpdateRequest": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "text"
        ]
      },
      "SignatureRecipient": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "contactId": {
            "type": "string"
          },
          "personId": {
            "type": "string"
          },
          "action": {
            "type": "string",
            "enum": [
              "sign",
              "receive_copy"
            ]
          },
          "routingOrder": {
            "type": "integer",
            "minimum": 1,
            "maximum": 20
          },
          "roleName": {
            "type": "string"
          },
          "privateMessage": {
            "type": "string"
          },
          "canDecline": {
            "type": "boolean"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "sent",
              "delivered",
              "signed",
              "declined"
            ]
          }
        },
        "required": [
          "name",
          "email"
        ]
      },
      "SignatureSettings": {
        "type": "object",
        "properties": {
          "routingMode": {
            "type": "string",
            "enum": [
              "parallel",
              "sequential"
            ]
          },
          "reminders": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "delayDays": {
                "type": "integer",
                "minimum": 1,
                "maximum": 30
              },
              "frequencyDays": {
                "type": "integer",
                "minimum": 1,
                "maximum": 30
              }
            }
          },
          "expiration": {
            "type": "object",
            "properties": {
              "days": {
                "type": "integer",
                "minimum": 1,
                "maximum": 365
              },
              "warningDays": {
                "type": "integer",
                "minimum": 0,
                "maximum": 30
              }
            }
          },
          "allowDownload": {
            "type": "boolean",
            "default": false,
            "description": "Show recipient downloads and allow completed signed-PDF download."
          },
          "aiAssistantEnabled": {
            "type": "boolean",
            "default": false,
            "description": "Opt in to the token-scoped recipient contract assistant."
          }
        }
      },
      "SignatureField": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "signature",
              "initials",
              "text",
              "name",
              "email",
              "title",
              "date_signed",
              "checkbox"
            ]
          },
          "signerId": {
            "type": "string"
          },
          "documentId": {
            "type": "string"
          },
          "page": {
            "type": "integer",
            "minimum": 1
          },
          "x": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "y": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "width": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 1
          },
          "height": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 1
          },
          "label": {
            "type": "string"
          },
          "required": {
            "type": "boolean"
          }
        },
        "required": [
          "type",
          "signerId",
          "documentId",
          "page",
          "x",
          "y",
          "width",
          "height"
        ]
      },
      "SignatureRequest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "fileName": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "sent",
              "delivered",
              "completed",
              "declined",
              "voided",
              "expired"
            ]
          },
          "documents": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "contentType": {
                  "type": "string"
                },
                "size": {
                  "type": "integer"
                },
                "pageCount": {
                  "type": "integer"
                }
              }
            }
          },
          "signers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SignatureRecipient"
            }
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SignatureField"
            }
          },
          "subject": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "settings": {
            "$ref": "#/components/schemas/SignatureSettings"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "sentAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": "string",
            "format": "date-time"
          },
          "history": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "required": [
          "id",
          "name",
          "status",
          "documents",
          "signers",
          "history"
        ]
      },
      "SignatureRequestResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "request": {
            "$ref": "#/components/schemas/SignatureRequest"
          }
        },
        "required": [
          "ok",
          "request"
        ]
      },
      "SignatureRequestListResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "count": {
            "type": "integer"
          },
          "requests": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SignatureRequest"
            }
          }
        },
        "required": [
          "ok",
          "count",
          "requests"
        ]
      },
      "AccountingTaxScenarioInput": {
        "type": "object",
        "required": ["legalEntityName", "accountingProfitMinor", "taxableAdditionsMinor", "taxableDeductionsMinor", "lossOffsetMinor", "taxCreditsMinor", "vpbPaymentsMinor"],
        "properties": {
          "legalEntityName": { "type": "string", "maxLength": 180 },
          "accountingProfitMinor": { "type": "string", "pattern": "^-?[0-9]+$", "description": "Accounting profit in exact euro cents." },
          "taxableAdditionsMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "taxableDeductionsMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "lossOffsetMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "taxCreditsMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "vpbPaymentsMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "sourceBasis": { "type": "string", "enum": ["manual", "actual", "forecast", "mixed_actual_forecast"], "default": "manual" },
          "sourceAsOfDate": { "type": "string", "format": "date", "description": "Cut-off date distinguishing actual and forecast periods." },
          "sourceValidationStatus": { "type": "string", "enum": ["not_checked", "passed", "warning", "failed"], "default": "not_checked" },
          "sourceFormulaErrorCount": { "type": "integer", "minimum": 0, "maximum": 1000000, "default": 0 },
          "sourceValidationNote": { "type": "string", "maxLength": 1000 },
          "source": { "type": "string", "maxLength": 500 },
          "note": { "type": "string", "maxLength": 2000 },
          "expectedRevision": { "type": "integer", "minimum": 0 }
        }
      },
      "AccountingTaxBalanceCloseInput": {
        "type": "object",
        "required": ["legalEntityName", "periodLabel", "reportingDate", "status", "totalAssetsMinor", "totalEquityLiabilitiesMinor", "priorYearResultStatus", "currentTaxProvisionStatus"],
        "properties": {
          "legalEntityName": { "type": "string", "maxLength": 180 },
          "periodLabel": { "type": "string", "maxLength": 120 },
          "reportingDate": { "type": "string", "format": "date" },
          "status": { "type": "string", "enum": ["draft", "review", "adjusted", "adopted", "filed"] },
          "totalAssetsMinor": { "type": "string", "pattern": "^[0-9]+$", "description": "Total assets in exact euro cents." },
          "totalEquityLiabilitiesMinor": { "type": "string", "pattern": "^[0-9]+$", "description": "Total equity and liabilities in exact euro cents." },
          "sourceFiscalYear": { "type": "integer", "enum": [2025, 2026], "description": "Fiscal year represented by the imported balance source." },
          "sourceBasis": { "type": "string", "enum": ["current_close", "opening_comparative", "management_estimate"], "default": "current_close" },
          "sourceFileName": { "type": "string", "maxLength": 260 },
          "sourceFileHash": { "type": "string", "pattern": "^[a-fA-F0-9]{64}$", "description": "SHA-256 of the reviewed source file." },
          "importedAt": { "type": "string", "format": "date-time" },
          "importedBy": { "type": "string", "maxLength": 180 },
          "sourceValidationStatus": { "type": "string", "enum": ["not_checked", "passed", "warning", "failed"], "default": "not_checked" },
          "sourceFormulaErrorCount": { "type": "integer", "minimum": 0, "maximum": 1000000, "default": 0 },
          "sourceValidationNote": { "type": "string", "maxLength": 1000 },
          "priorYearResultStatus": { "type": "string", "enum": ["pending", "complete", "not_applicable"] },
          "currentTaxProvisionStatus": { "type": "string", "enum": ["pending", "complete", "not_applicable"] },
          "accountantName": { "type": "string", "maxLength": 180 },
          "accountantReviewedAt": { "type": "string", "format": "date" },
          "evidenceReference": { "type": "string", "maxLength": 500 },
          "note": { "type": "string", "maxLength": 2000 },
          "expectedRevision": { "type": "integer", "minimum": 0 }
        }
      },
      "AccountingTaxBalanceExceptionInput": {
        "type": "object",
        "required": ["fiscalYear", "type", "severity", "status", "accountName", "expectedClassification", "debitMinor", "creditMinor", "description"],
        "properties": {
          "fiscalYear": { "type": "integer", "enum": [2025, 2026] },
          "type": { "type": "string", "enum": ["balance_difference", "debit_in_liability", "credit_in_asset", "unprocessed_prior_result", "missing_tax_provision", "other"] },
          "severity": { "type": "string", "enum": ["info", "warning", "critical"] },
          "status": { "type": "string", "enum": ["open", "resolved", "accepted_risk"] },
          "accountNumber": { "type": "string", "maxLength": 80 },
          "accountName": { "type": "string", "maxLength": 180 },
          "expectedClassification": { "type": "string", "enum": ["asset", "liability", "equity", "income", "expense", "other"] },
          "debitMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "creditMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "description": { "type": "string", "maxLength": 1000 },
          "source": { "type": "string", "maxLength": 500 },
          "evidenceReference": { "type": "string", "maxLength": 500 },
          "note": { "type": "string", "maxLength": 1000 },
          "expectedRevision": { "type": "integer", "minimum": 0 }
        }
      },
      "AccountingTaxRollforwardInput": {
        "type": "object",
        "required": ["assessmentYear", "legalEntityName", "taxType", "accountLabel", "openingPositionMinor", "currentYearProvisionMinor", "advancePaymentsMinor", "refundsMinor", "interestMinor", "penaltiesMinor", "cashSettlementMinor"],
        "properties": {
          "assessmentYear": { "type": "integer", "enum": [2025, 2026] },
          "legalEntityName": { "type": "string", "maxLength": 180 },
          "taxType": { "type": "string", "enum": ["vpb", "vat", "payroll", "dividend", "other"] },
          "accountNumber": { "type": "string", "maxLength": 80 },
          "accountLabel": { "type": "string", "maxLength": 180 },
          "reviewStatus": { "type": "string", "enum": ["draft", "review", "reconciled"] },
          "openingPositionMinor": { "type": "string", "pattern": "^-?[0-9]+$", "description": "Opening signed tax position in exact euro cents; positive is a liability and negative is an asset." },
          "currentYearProvisionMinor": { "type": "string", "pattern": "^-?[0-9]+$" },
          "advancePaymentsMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "refundsMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "returnStatus": { "type": "string", "enum": ["not_filed", "prepared", "filed", "amended"] },
          "filedReturnPositionMinor": { "type": "string", "pattern": "^-?[0-9]+$" },
          "returnReference": { "type": "string", "maxLength": 240 },
          "returnFiledAt": { "type": "string", "format": "date" },
          "assessmentStatus": { "type": "string", "enum": ["none", "provisional", "final", "objection", "settled"] },
          "provisionalAssessmentPositionMinor": { "type": "string", "pattern": "^-?[0-9]+$" },
          "finalAssessmentPositionMinor": { "type": "string", "pattern": "^-?[0-9]+$" },
          "assessmentReference": { "type": "string", "maxLength": 240 },
          "assessmentDate": { "type": "string", "format": "date" },
          "interestMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "penaltiesMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "cashSettlementMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "source": { "type": "string", "maxLength": 500 },
          "evidenceReference": { "type": "string", "maxLength": 500 },
          "note": { "type": "string", "maxLength": 2000 },
          "expectedRevision": { "type": "integer", "minimum": 0 }
        }
      },
      "AccountingTaxBookToTaxAdjustmentInput": {
        "type": "object",
        "required": ["fiscalYear", "legalEntityName", "direction", "category", "sourceAccountNumber", "sourceAccountName", "amountMinor", "reason", "ownerName"],
        "properties": {
          "fiscalYear": { "type": "integer", "enum": [2025, 2026] },
          "legalEntityName": { "type": "string", "maxLength": 180 },
          "direction": { "type": "string", "enum": ["addition", "deduction"] },
          "category": { "type": "string", "enum": ["other_adjustment", "exempt_income", "non_deductible_cost", "partly_deductible_cost", "depreciation_difference", "valuation_difference"] },
          "sourceAccountNumber": { "type": "string", "maxLength": 80 },
          "sourceAccountName": { "type": "string", "maxLength": 180 },
          "amountMinor": { "type": "string", "pattern": "^[0-9]+$", "description": "Positive magnitude in exact euro cents; direction determines the bridge sign." },
          "reason": { "type": "string", "maxLength": 1000 },
          "source": { "type": "string", "maxLength": 500 },
          "evidenceReference": { "type": "string", "maxLength": 500 },
          "ownerName": { "type": "string", "maxLength": 180 },
          "reviewStatus": { "type": "string", "enum": ["draft", "review", "approved", "rejected"] },
          "note": { "type": "string", "maxLength": 1000 },
          "expectedRevision": { "type": "integer", "minimum": 0 }
        }
      },
      "AccountingTaxLossInput": {
        "type": "object",
        "required": ["fiscalYear", "originYear", "legalEntityName", "originalLossMinor", "utilizedBeforeMinor", "plannedUtilizationMinor", "ownerName"],
        "properties": {
          "fiscalYear": { "type": "integer", "enum": [2025, 2026] },
          "originYear": { "type": "integer", "minimum": 1900, "maximum": 2025 },
          "legalEntityName": { "type": "string", "maxLength": 180 },
          "originalLossMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "utilizedBeforeMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "plannedUtilizationMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "assessmentReference": { "type": "string", "maxLength": 240 },
          "evidenceReference": { "type": "string", "maxLength": 500 },
          "ownerName": { "type": "string", "maxLength": 180 },
          "reviewStatus": { "type": "string", "enum": ["draft", "review", "approved"] },
          "note": { "type": "string", "maxLength": 1000 },
          "expectedRevision": { "type": "integer", "minimum": 0 }
        }
      },
      "AccountingTaxRelatedPartyReconciliationInput": {
        "type": "object",
        "required": ["fiscalYear", "subjectType", "purposeType", "taxClassification", "glAccountNumber", "glAccountName", "openingPrincipalMinor", "registerMovementMinor", "ledgerMovementMinor", "ledgerClosingBalanceMinor", "interestBaseMinor", "interestPostedMinor", "counterpartyConfirmedBalanceMinor", "ownerName"],
        "properties": {
          "fiscalYear": { "type": "integer", "enum": [2025, 2026] },
          "subjectType": { "type": "string", "enum": ["loan", "current_account"] },
          "loanId": { "type": "string", "maxLength": 200, "description": "Required when subjectType is loan; references the existing BV lending register." },
          "lenderEntityName": { "type": "string", "maxLength": 180, "description": "Required for a shareholder current account; derived from the lending register for loans." },
          "borrowerEntityName": { "type": "string", "maxLength": 180, "description": "Required for a shareholder current account; derived from the lending register for loans." },
          "purposeType": { "type": "string", "enum": ["shareholder_current_account", "group_loan", "employee_loan", "external_loan", "escrow", "director_expense", "external_receivable", "suspense", "reclassification", "other"] },
          "taxClassification": { "type": "string", "enum": ["box_2", "business_receivable", "group_receivable", "employee_benefit_review", "own_home_debt", "non_loan_reclassification", "other"] },
          "glAccountNumber": { "type": "string", "maxLength": 80 },
          "glAccountName": { "type": "string", "maxLength": 180 },
          "counterpartyGlAccountNumber": { "type": "string", "maxLength": 80 },
          "openingPrincipalMinor": { "type": "string", "pattern": "^[0-9]+$", "description": "Opening principal in exact euro cents." },
          "registerMovementMinor": { "type": "string", "pattern": "^-?[0-9]+$", "description": "Signed fiscal-year principal movement for current accounts; loan movement is derived from the linked lending register." },
          "ledgerMovementMinor": { "type": "string", "pattern": "^-?[0-9]+$" },
          "ledgerClosingBalanceMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "interestBaseMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "interestPostedMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "counterpartyConfirmedBalanceMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "counterpartyConfirmationDate": { "type": "string", "format": "date" },
          "agreementEvidenceReference": { "type": "string", "maxLength": 500 },
          "counterpartyEvidenceReference": { "type": "string", "maxLength": 500 },
          "source": { "type": "string", "maxLength": 500 },
          "ownerName": { "type": "string", "maxLength": 180 },
          "reviewStatus": { "type": "string", "enum": ["draft", "review", "approved", "rejected"] },
          "resolutionStatus": { "type": "string", "enum": ["open", "explained", "adjustment_posted", "reconciled"] },
          "resolutionNote": { "type": "string", "maxLength": 1000 },
          "resolutionEvidenceReference": { "type": "string", "maxLength": 500 },
          "note": { "type": "string", "maxLength": 1000 },
          "expectedRevision": { "type": "integer", "minimum": 0 }
        }
      },
      "AccountingTaxOpenItemControlInput": {
        "type": "object",
        "required": ["fiscalYear", "sourceType"],
        "properties": {
          "fiscalYear": { "type": "integer", "enum": [2025, 2026] },
          "sourceType": { "type": "string", "enum": ["finance_bill", "finance_invoice", "supplier_credit", "customer_credit", "accrued_payable", "accrued_receivable"] },
          "sourceId": { "type": "string", "maxLength": 200, "description": "Required for finance_bill or finance_invoice; references the existing Finance ledger record." },
          "counterpartyName": { "type": "string", "maxLength": 240, "description": "Required for standalone credits and accruals; derived from Finance for linked items." },
          "reference": { "type": "string", "maxLength": 180 },
          "issueDate": { "type": "string", "format": "date" },
          "dueDate": { "type": "string", "format": "date" },
          "grossMinor": { "type": "string", "pattern": "^[0-9]+$", "description": "Exact source-currency minor units; required for standalone credits and accruals." },
          "creditPaymentMinor": { "type": "string", "pattern": "^[0-9]+$", "description": "Credits or payments recognized by the snapshot as-of date in source-currency minor units." },
          "currency": { "type": "string", "pattern": "^[A-Z]{3}$" },
          "eurRateMicros": { "type": "string", "pattern": "^[0-9]+$", "description": "EUR per source-currency unit in millionths; 920000 means 0.92 EUR." },
          "disputed": { "type": "boolean" },
          "ownerName": { "type": "string", "maxLength": 180 },
          "subsequentPaymentDate": { "type": "string", "format": "date" },
          "evidenceReference": { "type": "string", "maxLength": 500 },
          "source": { "type": "string", "maxLength": 500 },
          "reviewStatus": { "type": "string", "enum": ["draft", "review", "approved", "rejected"] },
          "note": { "type": "string", "maxLength": 1000 },
          "expectedRevision": { "type": "integer", "minimum": 0 }
        }
      },
      "AccountingTaxTreasuryControlInput": {
        "type": "object",
        "required": ["fiscalYear", "financeAccountId", "currency", "ledgerClosingEurMinor", "ledgerAccruedInterestEurMinor", "eurRateMicros", "taxTreatment", "bookProfitLossEurMinor"],
        "properties": {
          "fiscalYear": { "type": "integer", "enum": [2025, 2026] }, "financeAccountId": { "type": "string", "maxLength": 200 }, "currency": { "type": "string", "pattern": "^[A-Z]{3}$" },
          "glAccountNumber": { "type": "string", "maxLength": 80 }, "glAccountName": { "type": "string", "maxLength": 180 },
          "ledgerClosingEurMinor": { "type": "string", "pattern": "^-?[0-9]+$" }, "ledgerAccruedInterestEurMinor": { "type": "string", "pattern": "^-?[0-9]+$" },
          "eurRateMicros": { "type": "string", "pattern": "^[0-9]+$", "description": "EUR per source-currency unit in millionths." },
          "taxTreatment": { "type": "string", "enum": ["ordinary_taxable", "participation_exemption", "adviser_review"], "description": "Dutch corporate-tax treatment of the recognised book result. Ordinary taxable results remain in accounting profit; participation-exempt results produce an equal-and-opposite suggested bridge adjustment." },
          "bookProfitLossEurMinor": { "type": "string", "pattern": "^-?[0-9]+$", "description": "Recognised accounting profit or loss for the period in EUR minor units; this is not inferred from the closing market value." },
          "taxEvidenceReference": { "type": "string", "maxLength": 500, "description": "Evidence supporting the corporate-tax treatment; required when the control is approved." },
          "ownerName": { "type": "string", "maxLength": 180 }, "evidenceReference": { "type": "string", "maxLength": 500 }, "source": { "type": "string", "maxLength": 500 },
          "reviewStatus": { "type": "string", "enum": ["draft", "review", "approved", "rejected"] }, "note": { "type": "string", "maxLength": 1000 }, "expectedRevision": { "type": "integer", "minimum": 0 }
        }
      },
      "AccountingTaxFixedAssetInput": {
        "type": "object",
        "required": ["fiscalYear", "assetName", "category", "acquisitionDate", "inServiceDate", "grossCostMinor", "residualValueMinor", "disposedCostMinor", "usefulLifeMonths", "openingAccumulatedDepreciationMinor", "depreciationPostedMinor", "impairmentMinor", "ledgerClosingNetBookValueMinor"],
        "properties": {
          "fiscalYear": { "type": "integer", "enum": [2025, 2026] }, "assetName": { "type": "string", "maxLength": 240 }, "assetTag": { "type": "string", "maxLength": 100 },
          "category": { "type": "string", "enum": ["software", "computer_equipment", "equipment", "furniture", "vehicle", "leasehold", "other"] },
          "acquisitionDate": { "type": "string", "format": "date" }, "inServiceDate": { "type": "string", "format": "date" },
          "grossCostMinor": { "type": "string", "pattern": "^[0-9]+$" }, "residualValueMinor": { "type": "string", "pattern": "^[0-9]+$" }, "disposedCostMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "usefulLifeMonths": { "type": "integer", "minimum": 1, "maximum": 600 }, "openingAccumulatedDepreciationMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "depreciationPostedMinor": { "type": "string", "pattern": "^[0-9]+$" }, "impairmentMinor": { "type": "string", "pattern": "^[0-9]+$" }, "ledgerClosingNetBookValueMinor": { "type": "string", "pattern": "^-?[0-9]+$" },
          "glAccountNumber": { "type": "string", "maxLength": 80 }, "glAccountName": { "type": "string", "maxLength": 180 }, "ownerName": { "type": "string", "maxLength": 180 },
          "evidenceReference": { "type": "string", "maxLength": 500 }, "source": { "type": "string", "maxLength": 500 }, "reviewStatus": { "type": "string", "enum": ["draft", "review", "approved", "rejected"] },
          "note": { "type": "string", "maxLength": 1000 }, "expectedRevision": { "type": "integer", "minimum": 0 }
        }
      },
      "AccountingTaxAnnualAccountsInput": {
        "type": "object",
        "required": ["legalEntityName"],
        "properties": {
          "fiscalYear": { "type": "integer", "enum": [2025, 2026] },
          "legalEntityName": { "type": "string", "maxLength": 180 },
          "kvkNumber": { "type": "string", "pattern": "^[0-9]{8}$" },
          "financialYearStart": { "type": "string", "format": "date" },
          "financialYearEnd": { "type": "string", "format": "date" },
          "businessClass": { "type": "string", "enum": ["unconfirmed", "micro", "small", "medium", "large"], "description": "Explicitly confirmed KVK size class. ONE does not infer this from one year because the general test uses two of three criteria over two consecutive years." },
          "businessClassTwoYearConfirmed": { "type": "boolean" },
          "businessClassEvidenceReference": { "type": "string", "maxLength": 500 },
          "preparationExtensionMonths": { "type": "integer", "minimum": 0, "maximum": 5 },
          "extensionApprovedDate": { "type": "string", "format": "date" },
          "extensionEvidenceReference": { "type": "string", "maxLength": 500 },
          "allShareholdersAreDirectors": { "type": "boolean" },
          "articlesOverrideAutomaticAdoption": { "type": "boolean" },
          "preparedDate": { "type": "string", "format": "date" },
          "signedDate": { "type": "string", "format": "date" },
          "adoptionDate": { "type": "string", "format": "date" },
          "filingStatus": { "type": "string", "enum": ["not_started", "prepared", "unadopted_filed", "adopted", "filed", "accepted", "rejected"] },
          "filingDate": { "type": "string", "format": "date" },
          "kvkReceiptReference": { "type": "string", "maxLength": 500 },
          "filingChannel": { "type": "string", "enum": ["unconfirmed", "kvk_online_service", "sbr_software", "accountant", "other"] },
          "taxonomyVersion": { "type": "string", "maxLength": 100 },
          "taxonomyValidated": { "type": "boolean" },
          "validationEvidenceReference": { "type": "string", "maxLength": 500 },
          "accountantReviewStatus": { "type": "string", "enum": ["not_required", "pending", "reviewed", "audited"] },
          "accountantName": { "type": "string", "maxLength": 180 },
          "accountantReportReference": { "type": "string", "maxLength": 500 },
          "ownerName": { "type": "string", "maxLength": 180 },
          "evidenceReference": { "type": "string", "maxLength": 500 },
          "source": { "type": "string", "maxLength": 500 },
          "reviewStatus": { "type": "string", "enum": ["draft", "review", "approved", "rejected"] },
          "note": { "type": "string", "maxLength": 1000 },
          "expectedRevision": { "type": "integer", "minimum": 0 }
        }
      },
      "AccountingTaxAuditReviewInput": {
        "type": "object",
        "required": ["fiscalYear", "methodologyKey", "resourceId", "reviewStatus", "summary", "note"],
        "properties": {
          "fiscalYear": { "type": "integer", "enum": [2025, 2026] },
          "methodologyKey": { "type": "string", "enum": ["balance_close", "tax_rollforward", "book_to_tax_bridge", "related_party", "open_item_ageing", "treasury_assets", "annual_accounts", "equity_dividend", "corporate_tax", "dga_controls", "obligations_debt", "audit_methodology"] },
          "resourceId": { "type": "string", "minLength": 1, "maxLength": 180 },
          "reviewStatus": { "type": "string", "enum": ["note", "question", "resolved"] },
          "summary": { "type": "string", "minLength": 1, "maxLength": 300 },
          "note": { "type": "string", "minLength": 1, "maxLength": 2000 },
          "evidenceReference": { "type": "string", "maxLength": 500 },
          "parentEventId": { "type": "string", "maxLength": 180 }
        }
      },
      "AccountingTaxEquityPositionInput": {
        "type": "object",
        "required": ["legalEntityName", "asOfDate", "shareCapitalMinor", "sharePremiumMinor", "statutoryReservesMinor", "articlesReservesMinor", "otherReservesMinor", "retainedEarningsMinor", "currentYearResultMinor", "otherEquityMinor", "ledgerTotalEquityMinor", "articlesReviewed"],
        "properties": {
          "fiscalYear": { "type": "integer", "enum": [2025, 2026] },
          "legalEntityName": { "type": "string", "maxLength": 180 },
          "asOfDate": { "type": "string", "format": "date" },
          "shareCapitalMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "sharePremiumMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "statutoryReservesMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "articlesReservesMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "otherReservesMinor": { "type": "string", "pattern": "^-?[0-9]+$" },
          "retainedEarningsMinor": { "type": "string", "pattern": "^-?[0-9]+$" },
          "currentYearResultMinor": { "type": "string", "pattern": "^-?[0-9]+$" },
          "otherEquityMinor": { "type": "string", "pattern": "^-?[0-9]+$" },
          "ledgerTotalEquityMinor": { "type": "string", "pattern": "^-?[0-9]+$" },
          "articlesReviewed": { "type": "boolean" },
          "articlesReference": { "type": "string", "maxLength": 500 },
          "shareholderRegisterReference": { "type": "string", "maxLength": 500 },
          "ownerName": { "type": "string", "maxLength": 180 },
          "evidenceReference": { "type": "string", "maxLength": 500 },
          "source": { "type": "string", "maxLength": 500 },
          "reviewStatus": { "type": "string", "enum": ["draft", "review", "approved", "rejected"] },
          "note": { "type": "string", "maxLength": 1000 },
          "expectedRevision": { "type": "integer", "minimum": 0 }
        }
      },
      "AccountingTaxDividendDecisionInput": {
        "type": "object",
        "required": ["fiscalYear", "legalEntityName", "distributionType", "beneficiaryName", "shareholderType", "grossDividendMinor"],
        "properties": {
          "fiscalYear": { "type": "integer", "enum": [2025, 2026] },
          "legalEntityName": { "type": "string", "maxLength": 180 },
          "distributionType": { "type": "string", "enum": ["interim", "final", "other"] },
          "status": { "type": "string", "enum": ["draft", "shareholder_approved", "board_approved", "available", "paid", "cancelled", "rejected"] },
          "beneficiaryName": { "type": "string", "maxLength": 180 },
          "shareholderType": { "type": "string", "enum": ["individual", "domestic_entity", "foreign_entity", "other"] },
          "countryCode": { "type": "string", "pattern": "^[A-Z]{2}$" },
          "ownershipBps": { "type": "integer", "minimum": 1, "maximum": 10000 },
          "beneficialOwnerReviewed": { "type": "boolean" },
          "grossDividendMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "resolutionDate": { "type": "string", "format": "date" },
          "shareholderResolutionReference": { "type": "string", "maxLength": 500 },
          "boardApprovalDate": { "type": "string", "format": "date" },
          "boardResolutionReference": { "type": "string", "maxLength": 500 },
          "interimAllowedByArticles": { "type": "boolean" },
          "forecastAsOfDate": { "type": "string", "format": "date" },
          "forecastHorizonMonths": { "type": "integer", "minimum": 1, "maximum": 24 },
          "openingCashMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "forecastInflowsMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "forecastOutflowsMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "otherPlannedDistributionsMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "minimumLiquidityBufferMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "liquidityForecastReference": { "type": "string", "maxLength": 500 },
          "withholdingTreatment": { "type": "string", "enum": ["standard_15", "domestic_participation_exemption", "treaty_or_foreign_relief", "qualification_exemption", "adviser_review"] },
          "withholdingRateBps": { "type": "integer", "minimum": 0, "maximum": 1500 },
          "withholdingEvidenceReference": { "type": "string", "maxLength": 500 },
          "availableDate": { "type": "string", "format": "date" },
          "paymentDate": { "type": "string", "format": "date" },
          "dividendTaxReturnStatus": { "type": "string", "enum": ["not_due", "pending", "filed", "paid", "exempt_no_return", "adviser_review"] },
          "dividendTaxReturnDate": { "type": "string", "format": "date" },
          "dividendTaxPaymentDate": { "type": "string", "format": "date" },
          "dividendTaxReference": { "type": "string", "maxLength": 500 },
          "ownerName": { "type": "string", "maxLength": 180 },
          "evidenceReference": { "type": "string", "maxLength": 500 },
          "source": { "type": "string", "maxLength": 500 },
          "note": { "type": "string", "maxLength": 1000 },
          "expectedRevision": { "type": "integer", "minimum": 0 }
        }
      },
      "AccountingTaxObligationInput": {
        "type": "object",
        "required": ["fiscalYear", "kind", "direction", "status", "periodLabel", "dueDate", "estimateMinor", "provisionMinor", "filedMinor", "assessedMinor", "settledMinor", "confidence"],
        "properties": {
          "fiscalYear": { "type": "integer", "enum": [2025, 2026] },
          "kind": { "type": "string", "enum": ["vpb", "vat", "payroll", "dividend", "annual_accounts", "other"] },
          "direction": { "type": "string", "enum": ["payable", "receivable"] },
          "status": { "type": "string", "enum": ["forecast", "provisioned", "filed", "assessed", "paid"] },
          "periodLabel": { "type": "string", "maxLength": 120 },
          "dueDate": { "type": "string", "format": "date" },
          "estimateMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "provisionMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "filedMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "assessedMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "settledMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "confidence": { "type": "string", "enum": ["low", "medium", "high"] },
          "source": { "type": "string", "maxLength": 500 },
          "note": { "type": "string", "maxLength": 2000 },
          "expectedRevision": { "type": "integer", "minimum": 0 }
        }
      },
      "AccountingTaxDebtInput": {
        "type": "object",
        "required": ["counterparty", "kind", "classification", "status", "principalMinor", "accruedInterestMinor"],
        "properties": {
          "counterparty": { "type": "string", "maxLength": 180 },
          "kind": { "type": "string", "enum": ["loan", "creditor", "accrual", "lease", "shareholder", "other"] },
          "classification": { "type": "string", "enum": ["current", "long_term"] },
          "status": { "type": "string", "enum": ["active", "repaid", "disputed", "archived"] },
          "principalMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "accruedInterestMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "maturityDate": { "type": "string", "format": "date" },
          "nextPaymentDate": { "type": "string", "format": "date" },
          "secured": { "type": "boolean" },
          "securityNote": { "type": "string", "maxLength": 500 },
          "source": { "type": "string", "maxLength": 500 },
          "note": { "type": "string", "maxLength": 2000 },
          "expectedRevision": { "type": "integer", "minimum": 0 }
        }
      },
      "AccountingTaxLoanInput": {
        "type": "object",
        "required": ["lenderEntity", "borrower", "relationship", "status", "principalMinor", "totalDisbursedMinor", "facilityAmountMinor", "annualInterestRateBps"],
        "properties": {
          "lenderEntity": { "type": "string", "maxLength": 180 },
          "borrower": { "type": "string", "maxLength": 180 },
          "relationship": { "type": "string", "enum": ["ubo", "employee", "external_person", "external_company"] },
          "status": { "type": "string", "enum": ["active", "repaid", "disputed", "archived"] },
          "purpose": { "type": "string", "maxLength": 500 },
          "principalMinor": { "type": "string", "pattern": "^[0-9]+$", "description": "Current outstanding principal in exact euro cents." },
          "totalDisbursedMinor": { "type": "string", "pattern": "^[0-9]+$", "description": "Cumulative principal disbursed in exact euro cents." },
          "facilityAmountMinor": { "type": "string", "pattern": "^[0-9]+$", "description": "Current agreed facility limit in exact euro cents." },
          "accruedInterestMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "annualInterestRateBps": { "type": "integer", "minimum": 0, "maximum": 10000, "description": "Annual rate in basis points; 450 means 4.50%." },
          "rateType": { "type": "string", "enum": ["fixed", "variable"] },
          "marketRateReviewed": { "type": "boolean" },
          "rateReviewDate": { "type": "string" },
          "repaymentType": { "type": "string", "enum": ["open_ended", "fixed_principal", "annuity", "interest_only", "bullet", "other"] },
          "paymentFrequency": { "type": "string", "enum": ["monthly", "quarterly", "annual", "on_demand", "maturity", "other"] },
          "scheduledPrincipalPaymentMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "startDate": { "type": "string" },
          "maturityDate": { "type": "string" },
          "nextPaymentDate": { "type": "string" },
          "writtenAgreement": { "type": "boolean" },
          "repaymentPlan": { "type": "boolean" },
          "secured": { "type": "boolean" },
          "securityNote": { "type": "string", "maxLength": 500 },
          "ownHomeDebt": { "type": "boolean" },
          "mortgageRightRecorded": { "type": "boolean" },
          "existedOn2022_12_31": { "type": "boolean" },
          "source": { "type": "string", "maxLength": 500 },
          "note": { "type": "string", "maxLength": 1000 },
          "expectedRevision": { "type": "integer", "minimum": 0 }
        }
      },
      "AccountingTaxLoanMovementInput": {
        "type": "object",
        "required": ["type", "amountMinor", "date", "expectedRevision"],
        "properties": {
          "type": { "type": "string", "enum": ["drawdown", "principal_repayment", "interest_charge", "interest_payment"] },
          "amountMinor": { "type": "string", "pattern": "^[0-9]+$" },
          "date": { "type": "string", "format": "date" },
          "newFacilityAmountMinor": { "type": "string", "pattern": "^[0-9]+$", "description": "Optional increased facility limit for a drawdown; cannot reduce the existing facility." },
          "source": { "type": "string", "maxLength": 500 },
          "note": { "type": "string", "maxLength": 1000 },
          "expectedRevision": { "type": "integer", "minimum": 0 }
        }
      },
      "AccountingTaxLoanDeleteInput": {
        "type": "object",
        "required": ["expectedRevision", "confirmBorrower"],
        "properties": {
          "expectedRevision": { "type": "integer", "minimum": 0 },
          "confirmBorrower": { "type": "string", "minLength": 1, "maxLength": 180, "description": "Exact current borrower name used as destructive confirmation." },
          "reason": { "type": "string", "maxLength": 1000 }
        }
      },
      "DeckDraftInput": {
        "type": "object",
        "required": ["spec"],
        "properties": {
          "expectedRevision": { "type": "integer", "minimum": 0 },
          "spec": { "$ref": "#/components/schemas/DeckSpec" }
        },
        "additionalProperties": false
      },
      "DeckSpec": {
        "type": "object",
        "required": ["slug", "title", "sections"],
        "properties": {
          "schemaVersion": { "type": "string", "const": "1.0" },
          "slug": { "type": "string", "pattern": "^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$" },
          "title": { "type": "string", "minLength": 1, "maxLength": 180 },
          "description": { "type": "string", "maxLength": 600 },
          "documentTitle": { "type": "string", "maxLength": 220 },
          "sidebarPrefix": { "type": "string", "maxLength": 60 },
          "sidebarSubject": { "type": "string", "maxLength": 120 },
          "client": { "type": "object", "required": ["name"], "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 160 } } },
          "confidentiality": { "type": "string", "enum": ["public", "public-unlisted"] },
          "template": { "type": "string", "enum": ["standard", "legacy-deck", "framestore-slides", "one-pricing-report"] },
          "sections": { "type": "array", "minItems": 2, "maxItems": 40, "items": { "$ref": "#/components/schemas/DeckSection" } },
          "sources": { "type": "array", "maxItems": 80, "items": { "$ref": "#/components/schemas/DeckSource" } },
          "pdfPages": { "type": "array", "maxItems": 40, "description": "Optional one-to-one visual PDF pages backed by protected uploaded images. When present, the array length must match sections.", "items": { "$ref": "#/components/schemas/DeckPdfPage" } }
        }
      },
      "DeckSection": {
        "type": "object",
        "required": ["id", "title"],
        "properties": {
          "id": { "type": "string", "maxLength": 64 },
          "navLabel": { "type": "string", "maxLength": 80 },
          "eyebrow": { "type": "string", "maxLength": 100 },
          "title": { "type": "string", "minLength": 1, "maxLength": 180 },
          "summary": { "type": "string", "maxLength": 1200 },
          "theme": { "type": "string", "enum": ["dark", "light", "blue"] },
          "layout": { "type": "string", "pattern": "^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$" },
          "navGroup": { "type": "string", "maxLength": 100 },
          "evidenceStatus": { "type": "string", "enum": ["fact", "hypothesis", "proposal", "research-pending"] },
          "blocks": { "type": "array", "maxItems": 12, "items": { "type": "object", "required": ["type"], "properties": { "type": { "type": "string", "enum": ["bullets", "metrics", "quote", "image", "video", "contact", "callout", "markup"] }, "title": { "type": "string", "maxLength": 140 }, "html": { "type": "string", "maxLength": 120000, "description": "Server-validated presentation markup. Scripts, embedded documents, inline event handlers, and executable URLs are rejected." }, "assetIds": { "type": "array", "maxItems": 40, "uniqueItems": true, "items": { "type": "string", "pattern": "^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$" } } }, "additionalProperties": true } }
        }
      },
      "DeckPdfPage": {
        "type": "object",
        "required": ["assetId"],
        "properties": {
          "assetId": { "type": "string", "pattern": "^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$" },
          "links": { "type": "array", "maxItems": 40, "items": { "$ref": "#/components/schemas/DeckPdfLink" } }
        },
        "additionalProperties": false
      },
      "DeckPdfLink": {
        "type": "object",
        "required": ["url", "x", "y", "width", "height"],
        "properties": {
          "url": { "type": "string", "format": "uri", "maxLength": 2000 },
          "label": { "type": "string", "maxLength": 240 },
          "x": { "type": "number", "minimum": 0, "maximum": 1 },
          "y": { "type": "number", "minimum": 0, "maximum": 1 },
          "width": { "type": "number", "minimum": 0, "maximum": 1 },
          "height": { "type": "number", "minimum": 0, "maximum": 1 }
        },
        "additionalProperties": false
      },
      "DeckSource": {
        "type": "object",
        "required": ["label", "url"],
        "properties": { "id": { "type": "string", "maxLength": 64 }, "label": { "type": "string", "maxLength": 200 }, "url": { "type": "string", "format": "uri", "maxLength": 2000 }, "publisher": { "type": "string", "maxLength": 160 } }
      },
      "DeckAssetInput": {
        "type": "object",
        "required": ["expectedRevision", "fileName", "contentType", "dataBase64"],
        "properties": {
          "assetId": { "type": "string", "maxLength": 64 },
          "expectedRevision": { "type": "integer", "minimum": 1 },
          "fileName": { "type": "string", "minLength": 1, "maxLength": 180 },
          "contentType": { "type": "string", "enum": ["image/jpeg", "image/png", "image/webp", "video/mp4"] },
          "dataBase64": { "type": "string", "format": "byte", "maxLength": 14000000 }
        },
        "additionalProperties": false
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "details": {}
        },
        "required": [
          "error"
        ]
      },
      "CreateItemRequest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Optional explicit item ID. Omit to generate one."
          },
          "name": {
            "type": "string",
            "minLength": 1
          },
          "groupId": {
            "type": "string",
            "description": "Optional board group ID or title."
          },
          "fields": {
            "type": "object",
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "boolean",
                "null"
              ]
            },
            "description": "Field values keyed by existing column ID or column title."
          },
          "note": {
            "type": "string",
            "description": "Optional initial update note."
          }
        },
        "required": [
          "name"
        ]
      },
      "DeleteItemRequest": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "description": "Optional audit reason stored as an item update."
          }
        }
      }
    }
  }
}
