{
  "openapi": "3.1.0",
  "info": {
    "title": "cairn API",
    "version": "v1",
    "description": "cairn 租戶 API。掛在各租戶自己的網域下；bearer token 由 CLI 的 OAuth device flow 核發，權限沿用帳號角色。回應一律 { ok, data } / { ok, error } 外殼。自 command registry 與路由樹生成。"
  },
  "servers": [
    {
      "url": "https://{tenantDomain}/api/v1",
      "variables": {
        "tenantDomain": {
          "default": "your-tenant.example.com",
          "description": "你的租戶網域"
        }
      }
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "cairn login（OAuth device flow）核發的 token"
      }
    }
  },
  "paths": {
    "/accrual-ledger": {
      "get": {
        "operationId": "get_accrual_ledger",
        "tags": [
          "accrual-ledger"
        ],
        "summary": "掛帳台帳",
        "description": "GET /api/v1/accrual-ledger?period=YYYY-MM — 掛帳台帳（accrual ledger）四區塊派生\n（梯次彙總 / 成本掛帳逐筆 / 應付清單 / 應收清單），對齊 /admin/accrual-ledger 頁面。\n\nalways-on 核心財務出口（accounting-module.md §3.2），純讀派生、無 module gate，\n只受 `ledger.read` 閘（毛利欄屬敏感財務）。period 必填 YYYY-MM（Asia/Taipei 出團月）；\ncore buildAccrualLedger 對非法值 throw。tenant-wide（無 owner scope）。",
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "出團月（格式 YYYY-MM，Asia/Taipei 時區）（格式限定）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "period": {
                          "type": "string",
                          "description": "結算期間（YYYY-MM，Asia/Taipei 出團月）。"
                        },
                        "departureSummary": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "departureId": {
                                "type": "string",
                                "description": "梯次 ID。"
                              },
                              "tripTitle": {
                                "type": "string",
                                "description": "團名。"
                              },
                              "departureDate": {
                                "type": "string",
                                "description": "出團日期（YYYY-MM-DD）。"
                              },
                              "pax": {
                                "type": "number",
                                "description": "出團人數（該梯次確認人數）。"
                              },
                              "revenueTwd": {
                                "type": "number",
                                "description": "總收入（梯次成交應收，排除已取消訂單，TWD 整數）。"
                              },
                              "realCostTwd": {
                                "type": "number",
                                "description": "真實成本合計（TWD 整數）= 房費底價成本 + 已核准的逐筆成本。逐筆成本區塊不含房費 （房費由分房資料另計），故逐筆成本加總會小於此值，差額即房費（設計如此）。"
                              },
                              "grossProfitTwd": {
                                "type": "number",
                                "description": "毛利毛估 = revenue − realCost（含房費）。"
                              }
                            },
                            "required": [
                              "departureId",
                              "tripTitle",
                              "departureDate",
                              "pax",
                              "revenueTwd",
                              "realCostTwd",
                              "grossProfitTwd"
                            ]
                          },
                          "description": "梯次彙總（區塊 1）：出團月落於 period 的各梯次收入 / 成本 / 毛利。"
                        },
                        "costLines": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "成本列 ID。"
                              },
                              "tripTitle": {
                                "type": "string",
                                "description": "團名。"
                              },
                              "departureDate": {
                                "type": "string",
                                "description": "所屬梯次出團日期（YYYY-MM-DD）。"
                              },
                              "category": {
                                "type": "string",
                                "description": "成本分類（如 交通 / 餐費 / 保險 / 嚮導）。"
                              },
                              "vendor": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "廠商：已建檔廠商名優先，否則用成本列上填寫的廠商名；null = 未填。"
                              },
                              "amountTwd": {
                                "type": "number",
                                "description": "代墊額（真實成本，TWD 整數）。"
                              },
                              "invoiceAmountTwd": {
                                "type": "number",
                                "description": "憑證額（外帳可申報金額，TWD 整數）。"
                              },
                              "isDeclarable": {
                                "type": "boolean",
                                "description": "有無發票憑證。"
                              },
                              "reviewStatus": {
                                "type": "string",
                                "description": "覆核狀態：掛了支出證明單則用其 status（pending/approved），否則由有無憑證派生。"
                              }
                            },
                            "required": [
                              "id",
                              "tripTitle",
                              "departureDate",
                              "category",
                              "vendor",
                              "amountTwd",
                              "invoiceAmountTwd",
                              "isDeclarable",
                              "reviewStatus"
                            ]
                          },
                          "description": "成本掛帳逐筆（區塊 2）：該期梯次上所有 departure_costs 成本列。"
                        },
                        "payables": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "payableNumber": {
                                "type": "string",
                                "description": "請款單號（人類可讀）。"
                              },
                              "tripTitle": {
                                "type": "string",
                                "description": "團名（未綁定梯次的手動請款顯示「未綁定梯次」）。"
                              },
                              "payeeName": {
                                "type": "string",
                                "description": "受款對象（供應商 / 嚮導 / 派車人等）。"
                              },
                              "amountTwd": {
                                "type": "number",
                                "description": "請款金額（整數 TWD）。"
                              },
                              "status": {
                                "type": "string",
                                "description": "draft | submitted | approved | paid | cancelled | rejected。"
                              }
                            },
                            "required": [
                              "payableNumber",
                              "tripTitle",
                              "payeeName",
                              "amountTwd",
                              "status"
                            ]
                          },
                          "description": "應付清單（區塊 3）：該期歸屬的請款單（payables）。"
                        },
                        "receivables": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "orderNumber": {
                                "type": "string",
                                "description": "訂單編號。"
                              },
                              "tripTitle": {
                                "type": "string",
                                "description": "團名（該訂單在期間內任一梯次的團名）。"
                              },
                              "receivableTwd": {
                                "type": "number",
                                "description": "應收金額（TWD 整數）。"
                              },
                              "receivedTwd": {
                                "type": "number",
                                "description": "實收金額（收款減退款，TWD 整數）。"
                              },
                              "outstandingTwd": {
                                "type": "number",
                                "description": "待收 = receivable − received。"
                              }
                            },
                            "required": [
                              "orderNumber",
                              "tripTitle",
                              "receivableTwd",
                              "receivedTwd",
                              "outstandingTwd"
                            ]
                          },
                          "description": "應收清單（區塊 4）：該期梯次上的 tour 訂單應收 / 實收 / 待收。"
                        }
                      },
                      "required": [
                        "period",
                        "departureSummary",
                        "costLines",
                        "payables",
                        "receivables"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "ledger.read"
      }
    },
    "/accrual-ledger/departure-summary": {
      "get": {
        "operationId": "get_accrual_ledger_departure_summary",
        "tags": [
          "accrual-ledger"
        ],
        "summary": "掛帳台帳的「梯次彙總」",
        "description": "GET /api/v1/accrual-ledger/departure-summary?period=YYYY-MM — 掛帳台帳的「梯次彙總」\n區塊（團名 / 出團日 / 人數 / 總收入 / 真實成本合計 / 毛利毛估），源自\nbuildAccrualLedger(...).departureSummary（重用 listDepartureLedgers per-departure roll-up）。\n\n同 /api/v1/accrual-ledger 受 `ledger.read` 閘、tenant-wide、純讀派生。只回單一區塊以省頻寬。",
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "出團月（格式 YYYY-MM，Asia/Taipei 時區）（格式限定）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "period": {
                          "type": "string",
                          "description": "結算期間（YYYY-MM，Asia/Taipei 出團月），回聲請求參數。"
                        },
                        "departureSummary": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "departureId": {
                                "type": "string",
                                "description": "梯次 ID。"
                              },
                              "tripTitle": {
                                "type": "string",
                                "description": "團名。"
                              },
                              "departureDate": {
                                "type": "string",
                                "description": "出團日期（YYYY-MM-DD）。"
                              },
                              "pax": {
                                "type": "number",
                                "description": "出團人數（該梯次確認人數）。"
                              },
                              "revenueTwd": {
                                "type": "number",
                                "description": "總收入（梯次成交應收，排除已取消訂單，TWD 整數）。"
                              },
                              "realCostTwd": {
                                "type": "number",
                                "description": "真實成本合計（TWD 整數）= 房費底價成本 + 已核准的逐筆成本。逐筆成本區塊不含房費 （房費由分房資料另計），故逐筆成本加總會小於此值，差額即房費（設計如此）。"
                              },
                              "grossProfitTwd": {
                                "type": "number",
                                "description": "毛利毛估 = revenue − realCost（含房費）。"
                              }
                            },
                            "required": [
                              "departureId",
                              "tripTitle",
                              "departureDate",
                              "pax",
                              "revenueTwd",
                              "realCostTwd",
                              "grossProfitTwd"
                            ]
                          },
                          "description": "梯次彙總：出團月落於 period 的各梯次收入 / 真實成本 / 毛估毛利。"
                        }
                      },
                      "required": [
                        "period",
                        "departureSummary"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "ledger.read"
      }
    },
    "/agencies": {
      "get": {
        "operationId": "get_agencies",
        "tags": [
          "agencies"
        ],
        "summary": "同業",
        "description": "GET /api/v1/agencies — 同業（B2B 旅行社 / 個人團主）列表，含累計訂單數 + 負責\n業務名。對應 /admin/agencies 列表的篩選（status / owner / hasTaxId）。同業是\n跨梯次的租戶層實體（無 owner-scope）—— agency.read 即可全列。owner=none 走\n服務端 filter（listAgencies SQL 只支援明確 owner id），與後台一致。\nSee specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "archived"
              ],
              "description": "同業狀態篩選（active 啟用中／archived 已封存；省略為全部）"
            }
          },
          {
            "name": "owner",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "負責業務篩選（傳明確使用者 ID；none＝只列尚未指派負責業務者；all 或省略＝全部）"
            }
          },
          {
            "name": "hasTaxId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no"
              ],
              "description": "是否有統一編號篩選（yes 僅列有統編者／no 僅列無統編者）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "同業 id（前綴 `agc_`）。"
                          },
                          "name": {
                            "type": "string",
                            "description": "同業公司名 / 個人團主名稱。"
                          },
                          "taxId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "統一編號（個人團主可留空）。"
                          },
                          "contactName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "主要聯絡人姓名（未填 → null）。"
                          },
                          "phone": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "聯絡電話（未填 → null）。"
                          },
                          "email": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "聯絡 Email（未填 → null）。"
                          },
                          "address": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "公司地址（未填 → null）。"
                          },
                          "paymentTerm": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "帳期 / 結算方式（自由文字，例：'月結 30 天'）。"
                          },
                          "ownerUserId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "負責業務 user id（NULL = 未指派）。"
                          },
                          "ownerName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "負責業務顯示名；未指派為 null。"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "active",
                              "archived"
                            ],
                            "description": "同業狀態：active 啟用中 / archived 已封存。"
                          },
                          "note": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "內部備註（未填 → null）。"
                          },
                          "orderCount": {
                            "type": "number",
                            "description": "累計訂單數（COUNT orders WHERE agency_id = id）。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "taxId",
                          "contactName",
                          "phone",
                          "email",
                          "address",
                          "paymentTerm",
                          "ownerUserId",
                          "ownerName",
                          "status",
                          "note",
                          "orderCount",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "agency.read"
      },
      "post": {
        "operationId": "post_agencies",
        "tags": [
          "agencies"
        ],
        "description": "GET /api/v1/agencies — 同業（B2B 旅行社 / 個人團主）列表，含累計訂單數 + 負責\n業務名。對應 /admin/agencies 列表的篩選（status / owner / hasTaxId）。同業是\n跨梯次的租戶層實體（無 owner-scope）—— agency.read 即可全列。owner=none 走\n服務端 filter（listAgencies SQL 只支援明確 owner id），與後台一致。\nSee specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立同業的 ID（agc_ 前綴）。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "agency.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "同業公司名稱（B2B 旅行社或個人團主名稱）（max 200 · min 1）"
                  },
                  "taxId": {
                    "type": "string",
                    "description": "統一編號（選填）"
                  },
                  "contactName": {
                    "type": "string",
                    "description": "主要聯絡人姓名（選填）"
                  },
                  "phone": {
                    "type": "string",
                    "description": "聯絡電話（選填）"
                  },
                  "email": {
                    "description": "聯絡 Email（選填；留空字串視為未填）"
                  },
                  "address": {
                    "type": "string",
                    "description": "公司地址（選填）"
                  },
                  "paymentTerm": {
                    "type": "string",
                    "description": "付款條件／帳期約定（選填，如月結 30 天）"
                  },
                  "ownerUserId": {
                    "type": "string",
                    "description": "指派的負責業務使用者 ID（選填）（max 128）"
                  },
                  "status": {
                    "type": "string",
                    "description": "同業狀態（active 啟用中／archived 已封存；預設 active）"
                  },
                  "note": {
                    "type": "string",
                    "description": "內部備註（選填）"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/agencies/{id}": {
      "get": {
        "operationId": "get_agencies_id_",
        "tags": [
          "agencies"
        ],
        "summary": "單一同業完整資料",
        "description": "GET /api/v1/agencies/{id} — 單一同業完整資料（含累計訂單 + 負責業務名）。\n租戶層實體（無 owner-scope）；不存在 → 404。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "同業 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "同業 id（前綴 `agc_`）。"
                        },
                        "name": {
                          "type": "string",
                          "description": "同業公司名 / 個人團主名稱。"
                        },
                        "taxId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "統一編號（個人團主可留空）。"
                        },
                        "contactName": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "主要聯絡人姓名（未填 → null）。"
                        },
                        "phone": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "聯絡電話（未填 → null）。"
                        },
                        "email": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "聯絡 Email（未填 → null）。"
                        },
                        "address": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "公司地址（未填 → null）。"
                        },
                        "paymentTerm": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "帳期 / 結算方式（自由文字，例：'月結 30 天'）。"
                        },
                        "ownerUserId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "負責業務 user id（NULL = 未指派）。"
                        },
                        "ownerName": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "負責業務顯示名；未指派為 null。"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "active",
                            "archived"
                          ],
                          "description": "同業狀態：active 啟用中 / archived 已封存。"
                        },
                        "note": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "內部備註（未填 → null）。"
                        },
                        "orderCount": {
                          "type": "number",
                          "description": "累計訂單數（COUNT orders WHERE agency_id = id）。"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "建立時間。"
                        },
                        "updatedAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "最後更新時間。"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "taxId",
                        "contactName",
                        "phone",
                        "email",
                        "address",
                        "paymentTerm",
                        "ownerUserId",
                        "ownerName",
                        "status",
                        "note",
                        "orderCount",
                        "createdAt",
                        "updatedAt"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "agency.read"
      },
      "patch": {
        "operationId": "patch_agencies_id_",
        "tags": [
          "agencies"
        ],
        "description": "GET /api/v1/agencies/{id} — 單一同業完整資料（含累計訂單 + 負責業務名）。\n租戶層實體（無 owner-scope）；不存在 → 404。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "要更新的同業 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：同業資料已更新。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "agency.manage",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "同業公司名稱（省略則不更動）（max 200 · min 1）"
                  },
                  "taxId": {
                    "type": "string",
                    "description": "統一編號（省略則不更動）"
                  },
                  "contactName": {
                    "type": "string",
                    "description": "主要聯絡人姓名（省略則不更動）"
                  },
                  "phone": {
                    "type": "string",
                    "description": "聯絡電話（省略則不更動）"
                  },
                  "email": {
                    "description": "聯絡 Email（省略則不更動；空字串視為清空）"
                  },
                  "address": {
                    "type": "string",
                    "description": "公司地址（省略則不更動）"
                  },
                  "paymentTerm": {
                    "type": "string",
                    "description": "付款條件／帳期約定（省略則不更動）"
                  },
                  "ownerUserId": {
                    "type": "string",
                    "description": "指派的負責業務使用者 ID（省略則不更動）（max 128）"
                  },
                  "status": {
                    "type": "string",
                    "description": "同業狀態（active 啟用中／archived 已封存；省略則不更動）"
                  },
                  "note": {
                    "type": "string",
                    "description": "內部備註（省略則不更動）"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/agencies/{id}/status": {
      "post": {
        "operationId": "post_agencies_id_status",
        "tags": [
          "agencies"
        ],
        "summary": "上下架同業",
        "description": "POST /api/v1/agencies/{id}/status — 上下架同業。鏡射 setAgencyStatusAction：\n同 `agency.manage` 閘、同 setAgencyStatus core fn，audit action 依目標狀態取\n`agency.archive`（archived）/ `agency.restore`（active），metadata `{ status }`。\nNOT_FOUND → 404。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "同業 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：同業啟用／停用狀態已更新。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "agency.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "description": "目標狀態（active 上架啟用／archived 下架封存）"
                  }
                },
                "required": [
                  "status"
                ]
              }
            }
          }
        }
      }
    },
    "/agencies/assignable-staff": {
      "get": {
        "operationId": "get_agencies_assignable_staff",
        "tags": [
          "agencies"
        ],
        "summary": "負責業務指派候選清單",
        "description": "GET /api/v1/agencies/assignable-staff — 負責業務指派候選清單（staff users，\nrole in admin/sales/op/accountant）。同業表單的「負責業務」下拉來源；薄包\nstaff/admin-repo 的 listStaff。租戶層（無 owner-scope），agency.read 即可。",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "userId": {
                            "type": "string",
                            "description": "員工使用者 id（可作為負責業務指派的 ownerUserId）。"
                          },
                          "name": {
                            "type": "string",
                            "description": "員工顯示名。"
                          },
                          "role": {
                            "type": "string",
                            "description": "角色代碼（admin / sales / op / accountant）。"
                          }
                        },
                        "required": [
                          "userId",
                          "name",
                          "role"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "agency.read"
      }
    },
    "/agencies/export": {
      "get": {
        "operationId": "get_agencies_export",
        "tags": [
          "agencies"
        ],
        "summary": "同業名單匯出",
        "description": "GET /api/v1/agencies/export — 同業名單匯出（agency.read），沿用列表的篩選\n（status / owner / hasTaxId）。回傳當前視圖的扁平 rows（JSON envelope）；CSV\n呈現由 CLI 端 client-side 組（核心只負責資料，不在此鑄 CSV builder）。對應\n後台 /admin/agencies/export 的 query→opts，但走統一 v1 envelope。",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "archived"
              ],
              "description": "同業狀態篩選（active 啟用中／archived 已封存；省略為全部）"
            }
          },
          {
            "name": "owner",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "負責業務篩選（傳明確使用者 ID；none＝只列尚未指派負責業務者；all 或省略＝全部）"
            }
          },
          {
            "name": "hasTaxId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no"
              ],
              "description": "是否有統一編號篩選（yes 僅列有統編者／no 僅列無統編者）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "同業 id（前綴 `agc_`）。"
                              },
                              "name": {
                                "type": "string",
                                "description": "同業公司名 / 個人團主名稱。"
                              },
                              "taxId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "統一編號（個人團主可留空）。"
                              },
                              "contactName": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "主要聯絡人姓名（未填 → null）。"
                              },
                              "phone": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "聯絡電話（未填 → null）。"
                              },
                              "email": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "聯絡 Email（未填 → null）。"
                              },
                              "address": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "公司地址（未填 → null）。"
                              },
                              "paymentTerm": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "帳期 / 結算方式（自由文字，例：'月結 30 天'）。"
                              },
                              "ownerUserId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "負責業務 user id（NULL = 未指派）。"
                              },
                              "ownerName": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "負責業務顯示名；未指派為 null。"
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "active",
                                  "archived"
                                ],
                                "description": "同業狀態：active 啟用中 / archived 已封存。"
                              },
                              "note": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "內部備註（未填 → null）。"
                              },
                              "orderCount": {
                                "type": "number",
                                "description": "累計訂單數（COUNT orders WHERE agency_id = id）。"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "建立時間。"
                              },
                              "updatedAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "最後更新時間。"
                              }
                            },
                            "required": [
                              "id",
                              "name",
                              "taxId",
                              "contactName",
                              "phone",
                              "email",
                              "address",
                              "paymentTerm",
                              "ownerUserId",
                              "ownerName",
                              "status",
                              "note",
                              "orderCount",
                              "createdAt",
                              "updatedAt"
                            ]
                          },
                          "description": "同業匯出資料列（依 owner 篩選後的全表快照，供試算表匯出）。"
                        }
                      },
                      "required": [
                        "rows"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "agency.read"
      }
    },
    "/audit/log": {
      "get": {
        "operationId": "get_audit_log",
        "tags": [
          "audit"
        ],
        "summary": "list/filter the append-only tenant audit trail",
        "description": "GET /api/v1/audit/log — list/filter the append-only tenant audit trail (the\n/admin/audit table over HTTP). admin-only (audit.read) — the trail carries\ncross-functional sensitive metadata, so it is intentionally NOT widened to\nthe lower order.read roles. Tenant-wide: no owner-scope. Filters are free-form\ntrimmed strings (no enum constraint) to match the back-office behaviour.\nRead-only; the audit_log table is append-only (DB trigger blocks UPDATE/DELETE).",
        "parameters": [
          {
            "name": "action",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "動作代碼篩選，例如 order.update（比對稽核事件的動作）"
            }
          },
          {
            "name": "actor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "操作者篩選，比對執行該動作的使用者 ID"
            }
          },
          {
            "name": "entity",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "目標實體篩選，比對被操作對象的類型或 ID"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "起始時間（ISO 8601），僅回傳此時間之後的事件"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "結束時間（ISO 8601），僅回傳此時間之前的事件"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "回傳筆數上限，最多 1000 筆（max 1000）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "稽核事件 ID。"
                          },
                          "actorUserId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "操作者的使用者 ID；系統事件（webhook／排程等非人為列）為 null。"
                          },
                          "actorEmail": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "操作者 Email；系統事件或帳號已刪時為 null。"
                          },
                          "actorName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "操作者顯示名；系統事件或帳號已刪時為 null。"
                          },
                          "action": {
                            "type": "string",
                            "description": "動作代碼，例如 order.create、traveler.decrypt。"
                          },
                          "targetType": {
                            "type": "string",
                            "description": "被操作對象的類型，例如 order、member。"
                          },
                          "targetId": {
                            "type": "string",
                            "description": "被操作對象的 ID。"
                          },
                          "metadata": {
                            "description": "該事件的附帶內容（欄位隨動作而異的自由結構 JSON）。"
                          },
                          "ipAddress": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "發起請求的來源 IP；無法取得時為 null。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "事件發生時間。"
                          }
                        },
                        "required": [
                          "id",
                          "actorUserId",
                          "actorEmail",
                          "actorName",
                          "action",
                          "targetType",
                          "targetId",
                          "metadata",
                          "ipAddress",
                          "createdAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "audit.read"
      }
    },
    "/audit/stats": {
      "get": {
        "operationId": "get_audit_stats",
        "tags": [
          "audit"
        ],
        "summary": "audit KPI counts",
        "description": "GET /api/v1/audit/stats — audit KPI counts (events this month / today, writes\nthis month, distinct actors this month), optionally narrowed to one actor.\nadmin-only (audit.read); tenant-wide (no owner-scope).",
        "parameters": [
          {
            "name": "actor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "操作者使用者 ID，指定時將統計數據限縮至該操作者"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "eventsThisMonth": {
                          "type": "number",
                          "description": "本月（Asia/Taipei）稽核事件總數。"
                        },
                        "eventsToday": {
                          "type": "number",
                          "description": "今日（Asia/Taipei）稽核事件總數。"
                        },
                        "writesThisMonth": {
                          "type": "number",
                          "description": "本月寫入類事件數（排除 *.read 讀取事件）。"
                        },
                        "distinctActorsThisMonth": {
                          "type": "number",
                          "description": "本月有動作紀錄的不重複操作者人數。"
                        }
                      },
                      "required": [
                        "eventsThisMonth",
                        "eventsToday",
                        "writesThisMonth",
                        "distinctActorsThisMonth"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "audit.read"
      }
    },
    "/consent-templates": {
      "get": {
        "operationId": "get_consent_templates",
        "tags": [
          "consent-templates"
        ],
        "summary": "list every consent-document template version",
        "description": "GET /api/v1/consent-templates — list every consent-document template version\n(the /admin/settings consent registry over HTTP). Append-only registry:\nnewest version first within each kind, each row carrying its bound signature\ncount. Tenant-wide (no owner scope). Gated by consent_template.create for\nparity with the back office, which reuses the create permission for reads.\nSee specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "同意書類別代碼，指定時僅列出該類別的範本版本"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "同意書範本 id（前綴 `ct_`）。同一 kind 每個版本各有一個 id。"
                          },
                          "kind": {
                            "type": "string",
                            "description": "同意書類型：pdpa（個資）/ tour_agreement（旅遊契約）/ cancellation_policy / refund_policy。"
                          },
                          "version": {
                            "type": "number",
                            "description": "版本號，同一 kind 從 1 遞增；範本 append-only，編輯即新增下一版。"
                          },
                          "contentMdx": {
                            "type": "string",
                            "description": "範本內容（MDX 原始碼），可含 {{...}} merge 變數。"
                          },
                          "effectiveFrom": {
                            "type": "string",
                            "format": "date-time",
                            "description": "此版本生效起始時間。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "此版本建立時間。"
                          },
                          "signatureCount": {
                            "type": "number",
                            "description": "引用此版本的已簽署份數（COUNT consent_signatures）。"
                          }
                        },
                        "required": [
                          "id",
                          "kind",
                          "version",
                          "contentMdx",
                          "effectiveFrom",
                          "createdAt",
                          "signatureCount"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "consent_template.create"
      },
      "post": {
        "operationId": "post_consent_templates",
        "tags": [
          "consent-templates"
        ],
        "description": "GET /api/v1/consent-templates — list every consent-document template version\n(the /admin/settings consent registry over HTTP). Append-only registry:\nnewest version first within each kind, each row carrying its bound signature\ncount. Tenant-wide (no owner scope). Gated by consent_template.create for\nparity with the back office, which reuses the create permission for reads.\nSee specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立同意書範本的 ID。"
                        },
                        "version": {
                          "type": "number",
                          "description": "範本版本號（每次發布遞增，簽署時綁定當下版本）。"
                        }
                      },
                      "required": [
                        "id",
                        "version"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "consent_template.create",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "description": "同意書類別代碼，決定此範本綁定的文件種類（min 1）"
                  },
                  "contentMdx": {
                    "type": "string",
                    "description": "同意書內文（MDX 格式），即此版本的條款全文"
                  }
                },
                "required": [
                  "kind",
                  "contentMdx"
                ]
              }
            }
          }
        }
      }
    },
    "/consent-templates/{id}": {
      "get": {
        "operationId": "get_consent_templates_id_",
        "tags": [
          "consent-templates"
        ],
        "summary": "a single consent-template version",
        "description": "GET /api/v1/consent-templates/{id} — a single consent-template version\n(content MDX + bound signature count). Tenant-wide; missing → 404. Gated by\nconsent_template.create for parity with the back office, which reuses the\ncreate permission for reads. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "同意書範本版本的 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "同意書範本 id（前綴 `ct_`）。同一 kind 每個版本各有一個 id。"
                        },
                        "kind": {
                          "type": "string",
                          "description": "同意書類型：pdpa（個資）/ tour_agreement（旅遊契約）/ cancellation_policy / refund_policy。"
                        },
                        "version": {
                          "type": "number",
                          "description": "版本號，同一 kind 從 1 遞增；範本 append-only，編輯即新增下一版。"
                        },
                        "contentMdx": {
                          "type": "string",
                          "description": "範本內容（MDX 原始碼），可含 {{...}} merge 變數。"
                        },
                        "effectiveFrom": {
                          "type": "string",
                          "format": "date-time",
                          "description": "此版本生效起始時間。"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "此版本建立時間。"
                        },
                        "signatureCount": {
                          "type": "number",
                          "description": "引用此版本的已簽署份數（COUNT consent_signatures）。"
                        }
                      },
                      "required": [
                        "id",
                        "kind",
                        "version",
                        "contentMdx",
                        "effectiveFrom",
                        "createdAt",
                        "signatureCount"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "consent_template.create"
      }
    },
    "/cost-templates": {
      "get": {
        "operationId": "get_cost_templates",
        "tags": [
          "cost-templates"
        ],
        "summary": "list reusable series-tour cost templates",
        "description": "GET /api/v1/cost-templates — list reusable series-tour cost templates (the\n/admin/cost-templates table over HTTP). Tenant-wide (no owner scope).\n\n`?status=active|archived` filters heads via listCostTemplates. `?active=1`\nreturns the lightweight `{ id, name }[]` binding picklist (listActiveCostTemplates),\nthe same shape the trip-edit cost-template <Combobox> consumes. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "archived"
              ],
              "description": "依狀態篩選：active 啟用、archived 已封存"
            }
          },
          {
            "name": "active",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "啟用時只回傳輕量的 { id, name } 綁定挑選清單（行程設定的成本範本下拉用）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "成本範本 id（ct_ 前綴）。"
                          },
                          "name": {
                            "type": "string",
                            "description": "成本範本名稱。"
                          }
                        },
                        "required": [
                          "id",
                          "name"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "cost_template.read"
      },
      "post": {
        "operationId": "post_cost_templates",
        "tags": [
          "cost-templates"
        ],
        "description": "GET /api/v1/cost-templates — list reusable series-tour cost templates (the\n/admin/cost-templates table over HTTP). Tenant-wide (no owner scope).\n\n`?status=active|archived` filters heads via listCostTemplates. `?active=1`\nreturns the lightweight `{ id, name }[]` binding picklist (listActiveCostTemplates),\nthe same shape the trip-edit cost-template <Combobox> consumes. See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建成本範本 ID（ct_ 前綴）。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "cost_template.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "成本範本名稱（max 120 · min 1）"
                  },
                  "description": {
                    "type": "string",
                    "description": "成本範本說明（max 500）"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "archived"
                    ],
                    "description": "範本狀態：active 啟用、archived 已封存"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/cost-templates/{id}": {
      "get": {
        "operationId": "get_cost_templates_id_",
        "tags": [
          "cost-templates"
        ],
        "summary": "full cost-template detail",
        "description": "GET /api/v1/cost-templates/{id} — full cost-template detail (head + cost\nlines). Tenant-wide read; missing → 404 (avoids leaking existence).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "成本範本 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "lines": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "成本行 ID。"
                              },
                              "templateId": {
                                "type": "string",
                                "description": "所屬成本範本 ID。"
                              },
                              "category": {
                                "type": "string",
                                "description": "成本分類（如 交通 / 餐費 / 保險）。"
                              },
                              "vendorName": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "供應商 / 廠商名（選填）。"
                              },
                              "description": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "摘要說明（選填）。"
                              },
                              "unitPriceTwd": {
                                "type": [
                                  "number",
                                  "null"
                                ],
                                "description": "TWD 行的單價；外幣行 null。"
                              },
                              "currency": {
                                "type": "string",
                                "description": "幣別（'TWD' = 台幣行）。"
                              },
                              "unitPriceForeign": {
                                "type": [
                                  "number",
                                  "null"
                                ],
                                "description": "外幣行的外幣單價；TWD 行 null。"
                              },
                              "internalRateSource": {
                                "anyOf": [
                                  {},
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "外幣行的內帳匯率來源；TWD 行 null。"
                              },
                              "fxAccountId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "internalRateSource='fx_account' 時的外幣帳戶 id。"
                              },
                              "quantityMode": {
                                "description": "數量模式：fixed 固定值 / headcount 依人頭公式（ceil(Σ人頭 / 組距)）。"
                              },
                              "quantityFixed": {
                                "type": [
                                  "number",
                                  "null"
                                ],
                                "description": "fixed 模式的固定數量；headcount 模式為 null。"
                              },
                              "headcountComponents": {
                                "type": [
                                  "array",
                                  "null"
                                ],
                                "items": {},
                                "description": "headcount 模式選定的人頭 component（passenger / leader / assistant / driver）；fixed 為 null。"
                              },
                              "groupDivisor": {
                                "type": [
                                  "number",
                                  "null"
                                ],
                                "description": "headcount 模式的組距（每 N 人一組，ceil 進位）；null = 直接加總。"
                              },
                              "isDeclarable": {
                                "type": "boolean",
                                "description": "是否預設有合法憑證（帶入成本列的 is_declarable 初值）。"
                              },
                              "sortOrder": {
                                "type": "number",
                                "description": "顯示排序。"
                              }
                            },
                            "required": [
                              "id",
                              "templateId",
                              "category",
                              "vendorName",
                              "description",
                              "unitPriceTwd",
                              "currency",
                              "unitPriceForeign",
                              "internalRateSource",
                              "fxAccountId",
                              "quantityMode",
                              "quantityFixed",
                              "headcountComponents",
                              "groupDivisor",
                              "isDeclarable",
                              "sortOrder"
                            ]
                          },
                          "description": "成本行明細（品項 × 單價 × 數量模型）。"
                        },
                        "id": {
                          "type": "string",
                          "description": "成本範本 ID。"
                        },
                        "name": {
                          "type": "string",
                          "description": "範本名稱。"
                        },
                        "description": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "範本說明（選填）。"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "active",
                            "archived"
                          ],
                          "description": "狀態：active 啟用 / archived 已封存。"
                        },
                        "lineCount": {
                          "type": "number",
                          "description": "成本行數（派生）。"
                        },
                        "boundTripCount": {
                          "type": "number",
                          "description": "綁定行程數（派生）。"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "建立時間。"
                        },
                        "updatedAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "最後更新時間。"
                        }
                      },
                      "required": [
                        "lines",
                        "id",
                        "name",
                        "description",
                        "status",
                        "lineCount",
                        "boundTripCount",
                        "createdAt",
                        "updatedAt"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "cost_template.read"
      },
      "patch": {
        "operationId": "patch_cost_templates_id_",
        "tags": [
          "cost-templates"
        ],
        "description": "GET /api/v1/cost-templates/{id} — full cost-template detail (head + cost\nlines). Tenant-wide read; missing → 404 (avoids leaking existence).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "成本範本 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否更新成功。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "cost_template.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "成本範本名稱（max 120 · min 1）"
                  },
                  "description": {
                    "type": "string",
                    "description": "成本範本說明（max 500）"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "archived"
                    ],
                    "description": "範本狀態：active 啟用、archived 已封存"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/cost-templates/{id}/lines": {
      "post": {
        "operationId": "post_cost_templates_id_lines",
        "tags": [
          "cost-templates"
        ],
        "summary": "add a cost line to a template.",
        "description": "POST /api/v1/cost-templates/{id}/lines — add a cost line to a template.\nMirrors `addTemplateLineAction` (permission `cost_template.manage`). The line\npayload reuses the EXACT line validator from the back-office `AddLineSchema`\n(`AddLineSchema.shape.line`, the §2.2 fixed/headcount superRefine); the path\n`{id}` is the authoritative `templateId`. Calls `addTemplateLine(db, id, line,\nactor.userId)` (normalisation + `cost_template.line_create` audit live in the\nrepo tx). `CostTemplateError` (incl. NOT_FOUND) → 409 via mapError. Returns the\nnew line `{ id }`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "成本範本 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建成本明細行 ID。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "cost_template.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "line": {
                    "type": "object",
                    "description": "成本明細列：含 category 科目、vendorName 廠商、unitPriceTwd 單價、quantityMode 計量方式（fixed 固定／headcount 人數）與對應數量／人數組成、isDeclarable 是否可報帳等欄位"
                  }
                },
                "required": [
                  "line"
                ]
              }
            }
          }
        }
      }
    },
    "/cost-templates/lines/{lineId}": {
      "patch": {
        "operationId": "patch_cost_templates_lines_lineId_",
        "tags": [
          "cost-templates"
        ],
        "summary": "update or delete a",
        "description": "PATCH / DELETE /api/v1/cost-templates/lines/{lineId} — update or delete a\nsingle cost-template line by its global line id (`lines` is a static sibling of\nthe `[id]` template segment, so no dynamic-segment collision).\n\nPATCH mirrors `updateTemplateLineAction` (permission `cost_template.manage`;\nline payload reuses the back-office `UpdateLineSchema.shape.line` §2.2 validator),\ncalling `updateTemplateLine(db, lineId, line, actor.userId)`.\nDELETE mirrors `deleteTemplateLineAction`, calling\n`deleteTemplateLine(db, lineId, actor.userId)`.\nBoth audit (`cost_template.line_update` / `line_delete`) + NOT_FOUND →\n`CostTemplateError` live in the repo tx; `CostTemplateError` → 409 via mapError.",
        "parameters": [
          {
            "name": "lineId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "成本範本明細行 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否更新成功。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "cost_template.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "line": {
                    "type": "object",
                    "description": "成本明細列更新內容：含 category 科目、vendorName 廠商、unitPriceTwd 單價、quantityMode 計量方式（fixed 固定／headcount 人數）與對應數量／人數組成、isDeclarable 是否可報帳等欄位"
                  }
                },
                "required": [
                  "line"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_cost_templates_lines_lineId_",
        "tags": [
          "cost-templates"
        ],
        "description": "PATCH / DELETE /api/v1/cost-templates/lines/{lineId} — update or delete a\nsingle cost-template line by its global line id (`lines` is a static sibling of\nthe `[id]` template segment, so no dynamic-segment collision).\n\nPATCH mirrors `updateTemplateLineAction` (permission `cost_template.manage`;\nline payload reuses the back-office `UpdateLineSchema.shape.line` §2.2 validator),\ncalling `updateTemplateLine(db, lineId, line, actor.userId)`.\nDELETE mirrors `deleteTemplateLineAction`, calling\n`deleteTemplateLine(db, lineId, actor.userId)`.\nBoth audit (`cost_template.line_update` / `line_delete`) + NOT_FOUND →\n`CostTemplateError` live in the repo tx; `CostTemplateError` → 409 via mapError.",
        "parameters": [
          {
            "name": "lineId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "成本範本明細行 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否刪除成功。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "cost_template.manage"
      }
    },
    "/departures/{depId}/allocation-mode": {
      "patch": {
        "operationId": "patch_departures_depId_allocation_mode",
        "tags": [
          "departures"
        ],
        "summary": "設定梯次分配模式",
        "description": "PATCH /api/v1/departures/{depId}/allocation-mode — 設定梯次分配模式（fcfs | lottery）。\n鏡像後台 `setAllocationModeAction`：同核心 op `setDepartureAllocationMode`（core 內建\naudit）+ 同權限 lottery.manage + 抽籤模組閘（未啟用 → 403 module_disabled）。\n找不到梯次 → 404。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "更新成功旗標，恆為 true。"
                        },
                        "departureId": {
                          "type": "string",
                          "description": "被更新的梯次 id。"
                        },
                        "mode": {
                          "type": "string",
                          "enum": [
                            "fcfs",
                            "lottery"
                          ],
                          "description": "更新後的佔位模式：fcfs 先到先得／lottery 抽籤。"
                        }
                      },
                      "required": [
                        "ok",
                        "departureId",
                        "mode"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lottery.manage",
        "x-module": "lottery",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "mode": {
                    "type": "string",
                    "enum": [
                      "fcfs",
                      "lottery"
                    ],
                    "description": "分配模式：fcfs（先到先得）或 lottery（抽籤）"
                  }
                },
                "required": [
                  "mode"
                ]
              }
            }
          }
        }
      }
    },
    "/departures/{depId}/costs": {
      "post": {
        "operationId": "post_departures_depId_costs",
        "tags": [
          "departures"
        ],
        "summary": "登錄梯次成本",
        "description": "POST /api/v1/departures/{depId}/costs — 登錄梯次成本（現場作業）。同核心 op +\ncore 內建 audit，鏡像後台 `createDepartureCostAction`；gated departure_cost.create。\nDepartureCostError → 409。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "建立成功旗標，恆為 true。"
                        },
                        "id": {
                          "type": "string",
                          "description": "新建立的梯次成本列 id。"
                        }
                      },
                      "required": [
                        "ok",
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_cost.create",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "category": {
                    "type": "string",
                    "description": "成本科目類別，決定歸入哪個分類帳（min 1）"
                  },
                  "vendorName": {
                    "type": "string",
                    "description": "供應商／受款對象名稱"
                  },
                  "description": {
                    "type": "string",
                    "description": "成本說明備註"
                  },
                  "amountTwd": {
                    "type": "number",
                    "description": "成本金額（台幣，整數）"
                  }
                },
                "required": [
                  "category",
                  "amountTwd"
                ]
              }
            }
          }
        }
      }
    },
    "/departures/{depId}/costs/{costId}": {
      "patch": {
        "operationId": "patch_departures_depId_costs_costId_",
        "tags": [
          "departures"
        ],
        "description": "PATCH/DELETE /api/v1/departures/{depId}/costs/{costId} — 編輯 / 刪除某筆梯次成本。\n同核心 op + core 內建 audit，鏡像後台 `updateDepartureCostAction` /\n`deleteDepartureCostAction`；gated departure_cost.manage。DepartureCostError → 409。",
        "parameters": [
          {
            "name": "costId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "成本列 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "更新成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_cost.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "category": {
                    "type": "string",
                    "description": "成本科目類別，決定歸入哪個分類帳（min 1）"
                  },
                  "vendorName": {
                    "type": "string",
                    "description": "供應商／受款對象名稱"
                  },
                  "description": {
                    "type": "string",
                    "description": "成本說明備註"
                  },
                  "amountTwd": {
                    "type": "number",
                    "description": "成本金額（台幣，整數）"
                  }
                },
                "required": [
                  "category",
                  "amountTwd"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_departures_depId_costs_costId_",
        "tags": [
          "departures"
        ],
        "description": "PATCH/DELETE /api/v1/departures/{depId}/costs/{costId} — 編輯 / 刪除某筆梯次成本。\n同核心 op + core 內建 audit，鏡像後台 `updateDepartureCostAction` /\n`deleteDepartureCostAction`；gated departure_cost.manage。DepartureCostError → 409。",
        "parameters": [
          {
            "name": "costId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "成本列 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "刪除成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_cost.manage"
      }
    },
    "/departures/{depId}/finance-summary": {
      "get": {
        "operationId": "get_departures_depId_finance_summary",
        "tags": [
          "departures"
        ],
        "summary": "該梯次財務摘要",
        "description": "GET /api/v1/departures/{depId}/finance-summary — 該梯次財務摘要（唯讀）：\n梯次表頭 + 應收/已收彙整 + 成本彙整。tenant-wide（無 owner-scope）；\n查無梯次 → 404。三個 core 讀取函式組裝，鏡像 /admin/control/{depId}/finance。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "header": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "description": "梯次 id（dep_ 前綴）。"
                            },
                            "tripTitle": {
                              "type": "string",
                              "description": "所屬行程標題。"
                            },
                            "tripSlug": {
                              "type": "string",
                              "description": "所屬行程網址 slug。"
                            },
                            "departureDate": {
                              "type": "string",
                              "description": "出發日（ISO 'YYYY-MM-DD'）。"
                            },
                            "returnDate": {
                              "type": "string",
                              "description": "回程日（ISO 'YYYY-MM-DD'）。"
                            }
                          },
                          "required": [
                            "id",
                            "tripTitle",
                            "tripSlug",
                            "departureDate",
                            "returnDate"
                          ],
                          "description": "梯次表頭（團號／行程名／出發日等基本資訊）。"
                        },
                        "finance": {
                          "type": "object",
                          "properties": {
                            "receivableTwd": {
                              "type": "number",
                              "description": "梯次應收：tour 訂單 order_charge_lines 聚合（排除已取消單）。"
                            },
                            "collectedTwd": {
                              "type": "number",
                              "description": "實收：tour 訂單 payment_transactions(direction='in')。"
                            },
                            "cashReturnedTwd": {
                              "type": "number",
                              "description": "客戶現金退回（refund/chargeback/reversal）。"
                            },
                            "outstandingTwd": {
                              "type": "number",
                              "description": "待收 = 應收 − (實收 − 退回)，floor 0。"
                            },
                            "costTwd": {
                              "type": "number",
                              "description": "成本：departure_costs 真實額（房費另計，見成本登記簿）。"
                            },
                            "costBilledTwd": {
                              "type": "number",
                              "description": "已轉請款成本。"
                            },
                            "costUnbilledTwd": {
                              "type": "number",
                              "description": "未轉請款成本。"
                            },
                            "anomalyOrderCount": {
                              "type": "number",
                              "description": "異常單數：overpaid / partially_refunded / refund pending 的 tour 訂單。"
                            }
                          },
                          "required": [
                            "receivableTwd",
                            "collectedTwd",
                            "cashReturnedTwd",
                            "outstandingTwd",
                            "costTwd",
                            "costBilledTwd",
                            "costUnbilledTwd",
                            "anomalyOrderCount"
                          ],
                          "description": "應收／已收金額彙整（TWD）。"
                        },
                        "cost": {
                          "type": "object",
                          "properties": {
                            "totalTwd": {
                              "type": "number",
                              "description": "內帳真實成本合計（TWD 整數，各成本列金額加總）。"
                            },
                            "billedTwd": {
                              "type": "number",
                              "description": "已轉請款的成本合計（TWD 整數）。"
                            },
                            "unbilledTwd": {
                              "type": "number",
                              "description": "尚未轉請款的成本合計（TWD 整數）。"
                            },
                            "declarableTwd": {
                              "type": "number",
                              "description": "外帳可申報金額合計（TWD 整數，各列憑證金額加總）。"
                            },
                            "nonDeclarableTwd": {
                              "type": "number",
                              "description": "無憑證的不可申報成本合計（TWD 整數，逐列取 金額−憑證 的正值，不可跨列抵減）。"
                            },
                            "count": {
                              "type": "number",
                              "description": "成本列筆數。"
                            }
                          },
                          "required": [
                            "totalTwd",
                            "billedTwd",
                            "unbilledTwd",
                            "declarableTwd",
                            "nonDeclarableTwd",
                            "count"
                          ],
                          "description": "成本彙整（各類直接成本合計，TWD）。"
                        }
                      },
                      "required": [
                        "header",
                        "finance",
                        "cost"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure.update"
      }
    },
    "/departures/{depId}/lottery-orders": {
      "get": {
        "operationId": "get_departures_depId_lottery_orders",
        "tags": [
          "departures"
        ],
        "summary": "該梯次抽籤訂單清單",
        "description": "GET /api/v1/departures/{depId}/lottery-orders — 該梯次抽籤訂單清單（應募名單 +\n中籤狀態 + 備案梯次）。tenant-wide（無 owner-scope）。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "orderId": {
                            "type": "string",
                            "description": "訂單 id。"
                          },
                          "orderNumber": {
                            "type": "string",
                            "description": "訂單編號。"
                          },
                          "customerName": {
                            "type": "string",
                            "description": "訂購人姓名。"
                          },
                          "partySize": {
                            "type": "number",
                            "description": "佔位人數。"
                          },
                          "lotteryState": {
                            "type": "string",
                            "enum": [
                              "applied",
                              "won",
                              "lost"
                            ],
                            "description": "抽籤狀態：applied 已應募／won 中籤／lost 未中籤。"
                          },
                          "backupChoiceCount": {
                            "type": "number",
                            "description": "客人自選的有序備案筆數（order_backup_choices；0 = 無備案）。"
                          },
                          "collectedTwd": {
                            "type": "number",
                            "description": "已收現金（payment_transactions direction='in'）；抽籤未中安置時的訂金結轉基準。"
                          },
                          "failoverFromOrderId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "落腳譜系：本單若是由某主單 force-place / cascade 落腳而成立的備案單，指向原主單 id。 null = 本單即主單（非備案落腳單）。供線控從備案列回溯主單。"
                          },
                          "awaitingPlacement": {
                            "type": "boolean",
                            "description": "true when lottery_state='lost' and still active (not cancelled). Means backup cascade exhausted — awaiting manual placement or explicit cancel."
                          }
                        },
                        "required": [
                          "orderId",
                          "orderNumber",
                          "customerName",
                          "partySize",
                          "lotteryState",
                          "backupChoiceCount",
                          "collectedTwd",
                          "failoverFromOrderId",
                          "awaitingPlacement"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.read"
      }
    },
    "/departures/{depId}/manifest": {
      "get": {
        "operationId": "get_departures_depId_manifest",
        "tags": [
          "departures"
        ],
        "summary": "該梯次旅客名單",
        "description": "GET /api/v1/departures/{depId}/manifest — 該梯次旅客名單（團控名單頁）。\ntenant-wide（無 owner-scope）。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "orderId": {
                            "type": "string",
                            "description": "所屬訂單 id。"
                          },
                          "orderNumber": {
                            "type": "string",
                            "description": "所屬訂單編號。"
                          },
                          "travelerName": {
                            "type": "string",
                            "description": "旅客姓名。"
                          },
                          "phone": {
                            "type": "string",
                            "description": "聯絡電話。"
                          },
                          "email": {
                            "type": "string",
                            "description": "聯絡 Email。"
                          },
                          "isPrimary": {
                            "type": "boolean",
                            "description": "是否為該訂單的主要聯絡人（訂購人）。"
                          },
                          "gender": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "enum": [
                              "male",
                              "female",
                              "other"
                            ],
                            "description": "性別（明文 enum-like）：'male'|'female'|'other'|null（未填）。"
                          },
                          "birthDate": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "生日 ISO `YYYY-MM-DD`；null = 未填。"
                          },
                          "diet": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "飲食需求（葷素）明文；null = 未填。"
                          },
                          "medicalNotes": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "醫療 / 過敏 / 病史備註明文；null = 未填。"
                          },
                          "specialNeeds": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "「飲食 · 特殊需求」欄的合併顯示字串（diet + medical_notes，以 ` · ` 併接）。 結構化欄落地後改吃 diet / medical_notes（不再湊 roommate_pref —— 分房需求回歸分房面板）。 兩者皆空 → null。"
                          },
                          "emergencyContactName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "緊急聯絡人姓名；null = 未填。"
                          },
                          "emergencyContactPhone": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "緊急聯絡人電話；null = 未填。"
                          },
                          "consentPending": {
                            "type": "boolean",
                            "description": "該訂單是否仍缺最新版 PDPA 同意書（per-order，同訂單所有旅客共享此旗標）。 true = 未簽 / 只簽過舊版；與 dashboard KPI、催簽 badge 同一述詞。"
                          },
                          "orderStatus": {
                            "type": "string",
                            "description": "Single display status (派生自三軸，與 deriveOrderDisplayStatus 同 precedence)。"
                          },
                          "amount": {
                            "type": "number",
                            "description": "該訂單應收金額（TWD；自 order_charge_lines 派生）。"
                          }
                        },
                        "required": [
                          "orderId",
                          "orderNumber",
                          "travelerName",
                          "phone",
                          "email",
                          "isPrimary",
                          "gender",
                          "birthDate",
                          "diet",
                          "medicalNotes",
                          "specialNeeds",
                          "emergencyContactName",
                          "emergencyContactPhone",
                          "consentPending",
                          "orderStatus",
                          "amount"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.read"
      }
    },
    "/departures/{depId}/payables": {
      "post": {
        "operationId": "post_departures_depId_payables",
        "tags": [
          "departures"
        ],
        "summary": "成本轉請款：以選定的未轉成本列建立一張",
        "description": "POST /api/v1/departures/{depId}/payables — 成本轉請款：以選定的未轉成本列建立一張\npayable（+ 回填成本列 payable_id）。同核心 op + core 內建 audit，鏡像後台\n`convertCostsToPayableAction`；gated payable.create。DepartureCostError → 409。\n（web 版另 revalidate /admin/payment-requests，純前端副作用，API 不需要。）",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "轉請款成功旗標，恆為 true。"
                        },
                        "payableId": {
                          "type": "string",
                          "description": "新建立的出款單（payable）id。"
                        },
                        "payableNumber": {
                          "type": "string",
                          "description": "出款單編號。"
                        }
                      },
                      "required": [
                        "ok",
                        "payableId",
                        "payableNumber"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payable.create",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "costIds": {
                    "type": "array",
                    "items": {},
                    "description": "要轉成請款單的成本列 ID 清單，至少一筆（min 1）"
                  },
                  "payeeType": {
                    "type": "string",
                    "enum": [
                      "supplier",
                      "guide",
                      "staff_commission",
                      "other"
                    ],
                    "description": "受款人類型：supplier（供應商）/ guide（領隊）/ staff_commission（員工佣金）/ other（其他）"
                  },
                  "payeeName": {
                    "type": "string",
                    "description": "受款人姓名／戶名（必填）（min 1）"
                  },
                  "payeeBankAccount": {
                    "type": "string",
                    "description": "受款人銀行帳號"
                  },
                  "payeeBankName": {
                    "type": "string",
                    "description": "受款人銀行名稱"
                  },
                  "payeeTaxId": {
                    "type": "string",
                    "description": "受款人統一編號／稅籍編號"
                  },
                  "submitImmediately": {
                    "type": "boolean",
                    "description": "設為 true 時建立後立即送出核簽，否則僅存為草稿"
                  }
                },
                "required": [
                  "costIds",
                  "payeeType",
                  "payeeName"
                ]
              }
            }
          }
        }
      }
    },
    "/departures/{depId}/prep/catering": {
      "post": {
        "operationId": "post_departures_depId_prep_catering",
        "tags": [
          "departures"
        ],
        "summary": "新增餐食紀錄",
        "description": "POST /api/v1/departures/{depId}/prep/catering — 新增餐食紀錄。鏡像後台\n`createCateringAction`：同核心 op + 同一筆 shell 端 writeAuditLog\n（departure_prep.catering_create）。gated departure_prep.manage。DeparturePrepError → 409。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "建立成功旗標，恆為 true。"
                        },
                        "id": {
                          "type": "string",
                          "description": "新建立的餐食紀錄 id。"
                        }
                      },
                      "required": [
                        "ok",
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_prep.manage",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "supplier": {
                    "type": "string",
                    "description": "餐食供應商名稱"
                  },
                  "mealPlan": {
                    "type": "string",
                    "description": "餐食安排說明（如餐數、菜色）"
                  },
                  "headcountNote": {
                    "type": "string",
                    "description": "人數備註（如素食、特殊餐需求）"
                  },
                  "status": {
                    "type": "string",
                    "description": "餐食安排狀態，預設 pending"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/departures/{depId}/prep/catering/{id}": {
      "patch": {
        "operationId": "patch_departures_depId_prep_catering_id_",
        "tags": [
          "departures"
        ],
        "summary": "更新餐食紀錄",
        "description": "PATCH  /api/v1/departures/{depId}/prep/catering/{id} — 更新餐食紀錄。\nDELETE /api/v1/departures/{depId}/prep/catering/{id} — 刪除餐食紀錄。\n鏡像後台 `updateCateringAction` / `deleteCateringAction`：同核心 op + 同一筆\nshell 端 writeAuditLog。gated departure_prep.manage。找不到 → 404；DeparturePrepError → 409。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "餐食紀錄 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "更新成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_prep.manage",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "supplier": {
                    "type": "string",
                    "description": "餐食供應商名稱"
                  },
                  "mealPlan": {
                    "type": "string",
                    "description": "餐食安排說明（如餐數、菜色）"
                  },
                  "headcountNote": {
                    "type": "string",
                    "description": "人數備註（如素食、特殊餐需求）"
                  },
                  "status": {
                    "type": "string",
                    "description": "餐食安排狀態"
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_departures_depId_prep_catering_id_",
        "tags": [
          "departures"
        ],
        "summary": "刪除餐食紀錄",
        "description": "PATCH  /api/v1/departures/{depId}/prep/catering/{id} — 更新餐食紀錄。\nDELETE /api/v1/departures/{depId}/prep/catering/{id} — 刪除餐食紀錄。\n鏡像後台 `updateCateringAction` / `deleteCateringAction`：同核心 op + 同一筆\nshell 端 writeAuditLog。gated departure_prep.manage。找不到 → 404；DeparturePrepError → 409。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "餐食紀錄 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "刪除成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_prep.manage"
      }
    },
    "/departures/{depId}/prep/checklist": {
      "post": {
        "operationId": "post_departures_depId_prep_checklist",
        "tags": [
          "departures"
        ],
        "summary": "設定行前總檢查某項勾選狀態",
        "description": "POST /api/v1/departures/{depId}/prep/checklist — 設定行前總檢查某項勾選狀態。\n鏡像後台 `setChecklistItemAction`：同核心 op + 同一筆 shell 端 writeAuditLog\n（departure_prep.checklist_toggle）。gated departure_prep.manage。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "設定成功旗標，恆為 true。"
                        },
                        "id": {
                          "type": "string",
                          "description": "行前檢查項紀錄 id。"
                        }
                      },
                      "required": [
                        "ok",
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_prep.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "itemKey": {
                    "type": "string",
                    "description": "行前檢查項目的代碼（min 1）"
                  },
                  "checked": {
                    "type": "boolean",
                    "description": "該檢查項目是否已完成勾選"
                  }
                },
                "required": [
                  "itemKey",
                  "checked"
                ]
              }
            }
          }
        }
      }
    },
    "/departures/{depId}/prep/deadlines": {
      "post": {
        "operationId": "post_departures_depId_prep_deadlines",
        "tags": [
          "departures"
        ],
        "summary": "設定梯次期限警戒",
        "description": "POST /api/v1/departures/{depId}/prep/deadlines — 設定梯次期限警戒（入山申請 / 下載 /\n登山險 / 旅責險送保截止）。鏡像後台 `setDepartureDeadlinesAction`：同核心 op\n`setDepartureDeadlines` + 同一筆 shell 端 writeAuditLog（departure_prep.deadlines_set）+\n同權限 departure_prep.manage + 登山模組閘（deadline 是登山專屬子集）。\n\n四個欄位皆為全量取代語意：傳空字串或省略 = 清除該期限；非空但非 ISO 日期 → 422。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "permitApply": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "入山申請截止日（ISO 日期；null = 未設 / 已清除）。"
                        },
                        "permitDownload": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "入山證下載截止日（ISO 日期；null = 未設 / 已清除）。"
                        },
                        "climbingInsurance": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "登山險送保截止日（ISO 日期；null = 未設 / 已清除）。"
                        },
                        "liabilityInsurance": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "旅責險送保截止日（ISO 日期；null = 未設 / 已清除）。"
                        },
                        "ok": {
                          "type": "boolean",
                          "description": "設定成功旗標，恆為 true。"
                        },
                        "departureId": {
                          "type": "string",
                          "description": "被設定期限的梯次 id。"
                        }
                      },
                      "required": [
                        "permitApply",
                        "permitDownload",
                        "climbingInsurance",
                        "liabilityInsurance",
                        "ok",
                        "departureId"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_prep.manage",
        "x-module": "climbing",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "permitApply": {
                    "type": "string",
                    "description": "入山申請截止日（ISO 日期）；傳空字串或省略則清除此期限"
                  },
                  "permitDownload": {
                    "type": "string",
                    "description": "入山證下載截止日（ISO 日期）；傳空字串或省略則清除此期限"
                  },
                  "climbingInsurance": {
                    "type": "string",
                    "description": "登山險送保截止日（ISO 日期）；傳空字串或省略則清除此期限"
                  },
                  "liabilityInsurance": {
                    "type": "string",
                    "description": "旅責險送保截止日（ISO 日期）；傳空字串或省略則清除此期限"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/departures/{depId}/prep/documents": {
      "post": {
        "operationId": "post_departures_depId_prep_documents",
        "tags": [
          "departures"
        ],
        "summary": "upsert 一種證件追蹤狀態",
        "description": "POST /api/v1/departures/{depId}/prep/documents — upsert 一種證件追蹤狀態。\n鏡像後台 `upsertDocumentAction`：同核心 op + 同一筆 shell 端 writeAuditLog\n（departure_prep.document_upsert）。gated departure_prep.manage。DeparturePrepError → 409。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "upsert 成功旗標，恆為 true。"
                        },
                        "id": {
                          "type": "string",
                          "description": "證件追蹤紀錄 id。"
                        }
                      },
                      "required": [
                        "ok",
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_prep.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "docType": {
                    "type": "string",
                    "description": "證件／文件種類代碼（如入山申請、保險名冊）（min 1）"
                  },
                  "applyStatus": {
                    "type": "string",
                    "enum": [
                      "todo",
                      "applying",
                      "approved"
                    ],
                    "description": "申辦狀態：todo（待辦）/ applying（申請中）/ approved（已核准）"
                  },
                  "fileReady": {
                    "type": "boolean",
                    "description": "文件檔案是否已備妥"
                  },
                  "uploadedToCloud": {
                    "type": "boolean",
                    "description": "文件是否已上傳雲端"
                  },
                  "fileUri": {
                    "type": "string",
                    "description": "文件檔案連結；給 null 清空"
                  },
                  "note": {
                    "type": "string",
                    "description": "備註；給 null 清空"
                  }
                },
                "required": [
                  "docType"
                ]
              }
            }
          }
        }
      }
    },
    "/departures/{depId}/prep/equipment-needs": {
      "post": {
        "operationId": "post_departures_depId_prep_equipment_needs",
        "tags": [
          "departures"
        ],
        "summary": "upsert 某裝備品項的需求數",
        "description": "POST /api/v1/departures/{depId}/prep/equipment-needs — upsert 某裝備品項的需求數。\n鏡像後台 `upsertEquipmentNeedAction`：同核心 op + 同一筆 shell 端 writeAuditLog\n（departure_prep.equipment_need_upsert）。gated departure_prep.manage。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "upsert 成功旗標，恆為 true。"
                        },
                        "id": {
                          "type": "string",
                          "description": "裝備需求紀錄 id。"
                        }
                      },
                      "required": [
                        "ok",
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_prep.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "equipmentItemId": {
                    "type": "string",
                    "description": "裝備品項 ID（min 1）"
                  },
                  "quantity": {
                    "type": "number",
                    "description": "該品項的需求數量"
                  },
                  "note": {
                    "type": "string",
                    "description": "需求備註；給 null 清空"
                  }
                },
                "required": [
                  "equipmentItemId",
                  "quantity"
                ]
              }
            }
          }
        }
      }
    },
    "/departures/{depId}/prep/equipment-needs/{id}": {
      "delete": {
        "operationId": "delete_departures_depId_prep_equipment_needs_id_",
        "tags": [
          "departures"
        ],
        "summary": "刪除裝備需求列",
        "description": "DELETE /api/v1/departures/{depId}/prep/equipment-needs/{id} — 刪除裝備需求列。\n鏡像後台 `deleteEquipmentNeedAction`：同核心 op + 同一筆 shell 端 writeAuditLog\n（departure_prep.equipment_need_delete）。gated departure_prep.manage。找不到 → 404。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "裝備需求列 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "刪除成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_prep.manage"
      }
    },
    "/departures/{depId}/prep/guides": {
      "post": {
        "operationId": "post_departures_depId_prep_guides",
        "tags": [
          "departures"
        ],
        "summary": "指派 / 重派領隊到梯次",
        "description": "POST /api/v1/departures/{depId}/prep/guides — 指派 / 重派領隊到梯次（複用 roster\nrepo）。鏡像後台 `assignGuideAction`：同核心 op + 同一筆 shell 端 writeAuditLog\n（departure_prep.guide_assign）。雙閘 chokepoint：departure_prep.manage（route）+\nguide_roster.manage（handler 內二次強制，防自訂角色繞過 roster 寫入閘）。\n檔期衝突（fail-closed）→ 409。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "指派成功旗標，恆為 true。"
                        },
                        "id": {
                          "type": "string",
                          "description": "領隊指派紀錄 id。"
                        }
                      },
                      "required": [
                        "ok",
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_prep.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "guideId": {
                    "type": "string",
                    "description": "領隊 ID（min 1）"
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "leader",
                      "assistant"
                    ],
                    "description": "指派角色：leader（領隊）或 assistant（隨隊／助理）"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "tentative",
                      "confirmed"
                    ],
                    "description": "指派狀態：tentative（暫定）或 confirmed（已確認）"
                  }
                },
                "required": [
                  "guideId",
                  "role"
                ]
              }
            }
          }
        }
      }
    },
    "/departures/{depId}/prep/insurance": {
      "post": {
        "operationId": "post_departures_depId_prep_insurance",
        "tags": [
          "departures"
        ],
        "summary": "新增投保紀錄",
        "description": "POST /api/v1/departures/{depId}/prep/insurance — 新增投保紀錄。鏡像後台\n`createInsuranceAction`：同核心 op + 同一筆 shell 端 writeAuditLog\n（departure_prep.insurance_create）。gated departure_prep.manage。DeparturePrepError → 409。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "建立成功旗標，恆為 true。"
                        },
                        "id": {
                          "type": "string",
                          "description": "新建立的投保紀錄 id。"
                        }
                      },
                      "required": [
                        "ok",
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_prep.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "description": "保險種類（如登山險、旅責險）（min 1）"
                  },
                  "insurer": {
                    "type": "string",
                    "description": "保險公司名稱"
                  },
                  "policyNo": {
                    "type": "string",
                    "description": "保單號碼"
                  },
                  "status": {
                    "type": "string",
                    "description": "投保狀態，預設 pending"
                  },
                  "note": {
                    "type": "string",
                    "description": "備註；給 null 清空"
                  }
                },
                "required": [
                  "kind"
                ]
              }
            }
          }
        }
      }
    },
    "/departures/{depId}/prep/insurance/{id}": {
      "patch": {
        "operationId": "patch_departures_depId_prep_insurance_id_",
        "tags": [
          "departures"
        ],
        "summary": "更新投保紀錄",
        "description": "PATCH  /api/v1/departures/{depId}/prep/insurance/{id} — 更新投保紀錄。\nDELETE /api/v1/departures/{depId}/prep/insurance/{id} — 刪除投保紀錄。\n鏡像後台 `updateInsuranceAction` / `deleteInsuranceAction`：同核心 op + 同一筆\nshell 端 writeAuditLog。gated departure_prep.manage。找不到 → 404；DeparturePrepError → 409。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "投保紀錄 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "更新成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_prep.manage",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "insurer": {
                    "type": "string",
                    "description": "保險公司名稱"
                  },
                  "policyNo": {
                    "type": "string",
                    "description": "保單號碼"
                  },
                  "status": {
                    "type": "string",
                    "description": "投保狀態"
                  },
                  "note": {
                    "type": "string",
                    "description": "備註；給 null 清空"
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_departures_depId_prep_insurance_id_",
        "tags": [
          "departures"
        ],
        "summary": "刪除投保紀錄",
        "description": "PATCH  /api/v1/departures/{depId}/prep/insurance/{id} — 更新投保紀錄。\nDELETE /api/v1/departures/{depId}/prep/insurance/{id} — 刪除投保紀錄。\n鏡像後台 `updateInsuranceAction` / `deleteInsuranceAction`：同核心 op + 同一筆\nshell 端 writeAuditLog。gated departure_prep.manage。找不到 → 404；DeparturePrepError → 409。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "投保紀錄 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "刪除成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_prep.manage"
      }
    },
    "/departures/{depId}/prep/rentals": {
      "post": {
        "operationId": "post_departures_depId_prep_rentals",
        "tags": [
          "departures"
        ],
        "summary": "從裝備需求開租借單",
        "description": "POST /api/v1/departures/{depId}/prep/rentals — 從裝備需求開租借單（race-safe +\n金流接入，append order_charge_lines 並重算金流）。鏡像後台 `createRentalFromPrepAction`：\n同核心 op + 同一筆 shell 端 writeAuditLog（departure_prep.rental_create）。\n雙閘 chokepoint：departure_prep.manage（route）+ equipment.manage（handler 內二次強制）\n+ 登山模組閘（裝備租借是登山專屬子系統）。EquipmentStockError / EquipmentNotFoundError → 409。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "開單成功旗標，恆為 true。"
                        },
                        "rentalId": {
                          "type": "string",
                          "description": "新開立的裝備租借單 id。"
                        }
                      },
                      "required": [
                        "ok",
                        "rentalId"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_prep.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "orderId": {
                    "type": "string",
                    "description": "要掛這筆租借費用的訂單 ID（min 1）"
                  },
                  "renterName": {
                    "type": "string",
                    "description": "租借人姓名；給 null 清空"
                  },
                  "lines": {
                    "type": "array",
                    "items": {},
                    "description": "租借品項明細（品項 + 數量），數量需大於 0 才計入"
                  }
                },
                "required": [
                  "orderId",
                  "lines"
                ]
              }
            }
          }
        }
      }
    },
    "/departures/{depId}/prep/transport": {
      "post": {
        "operationId": "post_departures_depId_prep_transport",
        "tags": [
          "departures"
        ],
        "summary": "新增派車紀錄",
        "description": "POST /api/v1/departures/{depId}/prep/transport — 新增派車紀錄。鏡像後台\n`createTransportAction`：同核心 op + 同一筆 shell 端 writeAuditLog\n（departure_prep.transport_create）。gated departure_prep.manage。DeparturePrepError → 409。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "建立成功旗標，恆為 true。"
                        },
                        "id": {
                          "type": "string",
                          "description": "新建立的派車紀錄 id。"
                        }
                      },
                      "required": [
                        "ok",
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_prep.manage",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "description": {
                    "type": "string",
                    "description": "派車說明（如路線、接送地點）"
                  },
                  "driverName": {
                    "type": "string",
                    "description": "司機姓名"
                  },
                  "vehicleInfo": {
                    "type": "string",
                    "description": "車輛資訊（如車型、車牌）"
                  },
                  "fareNote": {
                    "type": "string",
                    "description": "車資備註"
                  },
                  "status": {
                    "type": "string",
                    "description": "派車狀態，預設 pending"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/departures/{depId}/prep/transport/{id}": {
      "patch": {
        "operationId": "patch_departures_depId_prep_transport_id_",
        "tags": [
          "departures"
        ],
        "summary": "更新派車紀錄",
        "description": "PATCH  /api/v1/departures/{depId}/prep/transport/{id} — 更新派車紀錄。\nDELETE /api/v1/departures/{depId}/prep/transport/{id} — 刪除派車紀錄。\n鏡像後台 `updateTransportAction` / `deleteTransportAction`：同核心 op + 同一筆\nshell 端 writeAuditLog。gated departure_prep.manage。找不到 → 404；DeparturePrepError → 409。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "派車紀錄 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "更新成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_prep.manage",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "description": {
                    "type": "string",
                    "description": "派車說明（如路線、接送地點）"
                  },
                  "driverName": {
                    "type": "string",
                    "description": "司機姓名"
                  },
                  "vehicleInfo": {
                    "type": "string",
                    "description": "車輛資訊（如車型、車牌）"
                  },
                  "fareNote": {
                    "type": "string",
                    "description": "車資備註"
                  },
                  "status": {
                    "type": "string",
                    "description": "派車狀態"
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_departures_depId_prep_transport_id_",
        "tags": [
          "departures"
        ],
        "summary": "刪除派車紀錄",
        "description": "PATCH  /api/v1/departures/{depId}/prep/transport/{id} — 更新派車紀錄。\nDELETE /api/v1/departures/{depId}/prep/transport/{id} — 刪除派車紀錄。\n鏡像後台 `updateTransportAction` / `deleteTransportAction`：同核心 op + 同一筆\nshell 端 writeAuditLog。gated departure_prep.manage。找不到 → 404；DeparturePrepError → 409。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "派車紀錄 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "刪除成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_prep.manage"
      }
    },
    "/departures/{depId}/rooming-export": {
      "get": {
        "operationId": "get_departures_depId_rooming_export",
        "tags": [
          "departures"
        ],
        "summary": "分房表匯出資料列",
        "description": "GET /api/v1/departures/{depId}/rooming-export — 分房表匯出資料列（給線控/旅宿/\n嚮導/入山文件）。聯絡電話已遮罩、不含證號/護照/成本。tenant-wide（無 owner-scope）。\n回傳結構化 rows；CSV 由呼叫端（CLI）依需求格式化。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "fullName": {
                            "type": "string",
                            "description": "旅客姓名。"
                          },
                          "gender": {
                            "type": "string",
                            "description": "性別（中文標籤：男／女／其他）。"
                          },
                          "roomLabel": {
                            "type": "string",
                            "description": "房號／房間標籤（未排房為「未分房」）。"
                          },
                          "bedInfo": {
                            "type": "string",
                            "description": "床位資訊（房型中文標籤 + 床位）。"
                          },
                          "roommates": {
                            "type": "string",
                            "description": "同房其他旅客姓名（依房號分組派生）。"
                          },
                          "specialRequest": {
                            "type": "string",
                            "description": "特殊需求（房友偏好等自由文字）。"
                          },
                          "contactSummary": {
                            "type": "string",
                            "description": "聯絡摘要（電話已遮罩，只露末 3 碼）。"
                          }
                        },
                        "required": [
                          "fullName",
                          "gender",
                          "roomLabel",
                          "bedInfo",
                          "roommates",
                          "specialRequest",
                          "contactSummary"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure.update"
      }
    },
    "/departures/{depId}/rooms": {
      "get": {
        "operationId": "get_departures_depId_rooms",
        "tags": [
          "departures"
        ],
        "summary": "該梯次分房檢視",
        "description": "GET  /api/v1/departures/{depId}/rooms — 該梯次分房檢視（房間 + 旅客指派）。\nPOST /api/v1/departures/{depId}/rooms — 建立一間梯次房間。同核心 op + core 內建\n  audit，鏡像後台 `createDepartureRoomAction`；gated departure.update。床數必須 ≥ 1。\ntenant-wide（無 owner-scope）；查無梯次 → 404。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "departure": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "description": "梯次 id（dep_ 前綴）。"
                            },
                            "departureDate": {
                              "type": "string",
                              "description": "出發日（ISO 'YYYY-MM-DD'）。"
                            },
                            "returnDate": {
                              "type": "string",
                              "description": "回程日（ISO 'YYYY-MM-DD'）。"
                            },
                            "tripTitle": {
                              "type": "string",
                              "description": "所屬行程標題。"
                            },
                            "tripSlug": {
                              "type": "string",
                              "description": "所屬行程網址 slug。"
                            },
                            "capacity": {
                              "type": "number",
                              "description": "名額上限（人數）。"
                            },
                            "bookedCount": {
                              "type": "number",
                              "description": "已成團佔用名額（人數）。"
                            }
                          },
                          "required": [
                            "id",
                            "departureDate",
                            "returnDate",
                            "tripTitle",
                            "tripSlug",
                            "capacity",
                            "bookedCount"
                          ],
                          "description": "梯次表頭（id／起訖日／行程名／容量等）。"
                        },
                        "rooms": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "房間 id。"
                              },
                              "roomLabel": {
                                "type": "string",
                                "description": "房號／房間標籤。"
                              },
                              "roomType": {
                                "type": "string",
                                "description": "房型（如 single 單人／double 雙人／dorm 通舖）。"
                              },
                              "bedCount": {
                                "type": "number",
                                "description": "床位數。"
                              },
                              "bedConfig": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "床位配置說明（可空）。"
                              },
                              "accommodationName": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "住宿名稱（梯次配套派生房才有；可空）。"
                              },
                              "accommodationDate": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "住宿日期（YYYY-MM-DD；可空）。"
                              },
                              "baseCostTwd": {
                                "type": "number",
                                "description": "房間底價成本（TWD）。"
                              },
                              "upgradeFeeTwd": {
                                "type": "number",
                                "description": "房型升等補款（TWD）。"
                              },
                              "notes": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "備註（可空）。"
                              },
                              "departureLodgingId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "null = 手動建立的房；non-null = 梯次配套自動派生房的來源 ID。"
                              },
                              "assignedTravelers": {
                                "type": "array",
                                "items": {
                                  "type": "object"
                                },
                                "description": "已入住此房的旅客。"
                              }
                            },
                            "required": [
                              "id",
                              "roomLabel",
                              "roomType",
                              "bedCount",
                              "bedConfig",
                              "accommodationName",
                              "accommodationDate",
                              "baseCostTwd",
                              "upgradeFeeTwd",
                              "notes",
                              "departureLodgingId",
                              "assignedTravelers"
                            ]
                          },
                          "description": "此梯次的所有房間（含入住旅客）。"
                        },
                        "unassignedTravelers": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "旅客 id。"
                              },
                              "fullName": {
                                "type": "string",
                                "description": "旅客姓名。"
                              },
                              "orderId": {
                                "type": "string",
                                "description": "所屬訂單 id。"
                              },
                              "orderNumber": {
                                "type": "string",
                                "description": "所屬訂單編號。"
                              },
                              "isPrimary": {
                                "type": "boolean",
                                "description": "是否為該訂單的主要聯絡人（訂購人）。"
                              },
                              "gender": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "性別：'male'|'female'|'other'|null。"
                              },
                              "birthDate": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "出生日期（YYYY-MM-DD；可空）。"
                              },
                              "roomPreference": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "下單登記的房型偏好（auto-pair 起點提示）。"
                              },
                              "roommatePref": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "指定房友 id / 特殊需求自由文字。"
                              }
                            },
                            "required": [
                              "id",
                              "fullName",
                              "orderId",
                              "orderNumber",
                              "isPrimary",
                              "gender",
                              "roomPreference",
                              "roommatePref"
                            ]
                          },
                          "description": "尚未分房的旅客清單。"
                        },
                        "stats": {
                          "type": "object",
                          "properties": {
                            "totalTravelers": {
                              "type": "number",
                              "description": "此梯次旅客總人數。"
                            },
                            "assignedCount": {
                              "type": "number",
                              "description": "已分配房間的旅客數。"
                            },
                            "roomCount": {
                              "type": "number",
                              "description": "房間數。"
                            },
                            "totalUpgradeFee": {
                              "type": "number",
                              "description": "升等補款合計（TWD 整數）。"
                            }
                          },
                          "required": [
                            "totalTravelers",
                            "assignedCount",
                            "roomCount",
                            "totalUpgradeFee"
                          ],
                          "description": "分房統計彙總（總人數／已分房數／房間數／升等補款合計）。"
                        }
                      },
                      "required": [
                        "departure",
                        "rooms",
                        "unassignedTravelers",
                        "stats"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure.update"
      },
      "post": {
        "operationId": "post_departures_depId_rooms",
        "tags": [
          "departures"
        ],
        "summary": "建立一間梯次房間",
        "description": "GET  /api/v1/departures/{depId}/rooms — 該梯次分房檢視（房間 + 旅客指派）。\nPOST /api/v1/departures/{depId}/rooms — 建立一間梯次房間。同核心 op + core 內建\n  audit，鏡像後台 `createDepartureRoomAction`；gated departure.update。床數必須 ≥ 1。\ntenant-wide（無 owner-scope）；查無梯次 → 404。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "建立成功旗標，恆為 true。"
                        },
                        "id": {
                          "type": "string",
                          "description": "新建立的房間 id。"
                        }
                      },
                      "required": [
                        "ok",
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure.update",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "roomLabel": {
                    "type": "string",
                    "description": "房間代號／標籤（如 101、A 房）（min 1）"
                  },
                  "roomType": {
                    "type": "string",
                    "description": "房型（如 雙人房、四人房）（min 1）"
                  },
                  "bedCount": {
                    "type": "number",
                    "description": "床位數，必須大於 0"
                  },
                  "bedConfig": {
                    "type": "string",
                    "description": "床型配置說明（如 2 大床、1 大 2 小）"
                  },
                  "accommodationName": {
                    "type": "string",
                    "description": "住宿地點／旅宿名稱"
                  },
                  "accommodationDate": {
                    "type": "string",
                    "description": "入住日期（ISO 日期字串）"
                  },
                  "baseCostTwd": {
                    "type": "number",
                    "description": "房間基本成本（台幣），預設 0"
                  },
                  "upgradeFeeTwd": {
                    "type": "number",
                    "description": "房型升等補款金額（台幣），預設 0"
                  },
                  "notes": {
                    "type": "string",
                    "description": "房間備註"
                  }
                },
                "required": [
                  "roomLabel",
                  "roomType",
                  "bedCount"
                ]
              }
            }
          }
        }
      }
    },
    "/departures/{depId}/rooms/{roomId}": {
      "patch": {
        "operationId": "patch_departures_depId_rooms_roomId_",
        "tags": [
          "departures"
        ],
        "summary": "編輯房間",
        "description": "PATCH  /api/v1/departures/{depId}/rooms/{roomId} — 編輯房間。\nDELETE /api/v1/departures/{depId}/rooms/{roomId} — 刪除房間。\n同核心 op + core 內建 audit，鏡像後台 `updateRoomAction` / `deleteRoomAction`；\ngated departure.update。PATCH：未給的欄位不動（partial）；nullable 欄位給 null 清空。\n查無房間 → 404；有旅客 / 派生房不可刪 → 409。",
        "parameters": [
          {
            "name": "roomId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "房間 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "更新成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure.update",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "roomLabel": {
                    "type": "string",
                    "description": "房間代號／標籤；未給則不變"
                  },
                  "roomType": {
                    "type": "string",
                    "description": "房型；未給則不變"
                  },
                  "bedCount": {
                    "type": "number",
                    "description": "床位數；未給則不變"
                  },
                  "bedConfig": {
                    "type": "string",
                    "description": "床型配置說明；給 null 清空、未給則不變"
                  },
                  "accommodationName": {
                    "type": "string",
                    "description": "住宿地點名稱；給 null 清空、未給則不變"
                  },
                  "accommodationDate": {
                    "type": "string",
                    "description": "入住日期（ISO 字串）；給 null 清空、未給則不變"
                  },
                  "baseCostTwd": {
                    "type": "number",
                    "description": "房間基本成本（台幣）；未給則不變"
                  },
                  "upgradeFeeTwd": {
                    "type": "number",
                    "description": "房型升等補款金額（台幣）；未給則不變"
                  },
                  "notes": {
                    "type": "string",
                    "description": "房間備註；給 null 清空、未給則不變"
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_departures_depId_rooms_roomId_",
        "tags": [
          "departures"
        ],
        "summary": "刪除房間",
        "description": "PATCH  /api/v1/departures/{depId}/rooms/{roomId} — 編輯房間。\nDELETE /api/v1/departures/{depId}/rooms/{roomId} — 刪除房間。\n同核心 op + core 內建 audit，鏡像後台 `updateRoomAction` / `deleteRoomAction`；\ngated departure.update。PATCH：未給的欄位不動（partial）；nullable 欄位給 null 清空。\n查無房間 → 404；有旅客 / 派生房不可刪 → 409。",
        "parameters": [
          {
            "name": "roomId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "房間 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "刪除成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure.update"
      }
    },
    "/departures/{depId}/rooms/auto-pair-apply": {
      "post": {
        "operationId": "post_departures_depId_rooms_auto_pair_apply",
        "tags": [
          "departures"
        ],
        "summary": "線控確認 auto-pair 建議分組：",
        "description": "POST /api/v1/departures/{depId}/rooms/auto-pair-apply — 線控確認 auto-pair 建議分組：\n在單一交易內建房 + 整組指派旅客。鏡像後台 `applyAutoPairGroupAction`：同核心 op\n`applyAutoPairGroup`（core 內建 audit、原子性、同梯歸屬驗證）+ 同權限 departure.update。\n錯誤對應：空名單 → 422、旅客不存在 → 404、跨梯 → 409。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "套用成功旗標，恆為 true。"
                        },
                        "roomId": {
                          "type": "string",
                          "description": "建議分組寫入後所在的房間 id。"
                        },
                        "travelerIds": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "被排入該房的旅客 id 清單。"
                        }
                      },
                      "required": [
                        "ok",
                        "roomId",
                        "travelerIds"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure.update",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "travelerIds": {
                    "type": "array",
                    "items": {},
                    "description": "要編入同一房的旅客 ID 清單，至少一人（min 1）"
                  },
                  "roomType": {
                    "type": "string",
                    "description": "建立房間的房型，預設 shared（合住）（min 1）"
                  }
                },
                "required": [
                  "travelerIds"
                ]
              }
            }
          }
        }
      }
    },
    "/departures/{depId}/rooms/auto-pair-preview": {
      "get": {
        "operationId": "get_departures_depId_rooms_auto_pair_preview",
        "tags": [
          "departures"
        ],
        "summary": "對某梯次「尚未排房」的旅客",
        "description": "GET /api/v1/departures/{depId}/rooms/auto-pair-preview — 對某梯次「尚未排房」的旅客\n跑 auto-pair 建議（純讀取，不寫入）。鏡像後台 `previewAutoPairAction`：同核心引擎\n`previewDepartureAutoPair`，同權限 `departure.update`。線控確認某組後再 POST\nauto-pair-apply 寫入。查無梯次 → 404。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "suggestion": {
                          "type": "object",
                          "properties": {
                            "groups": {
                              "type": "array",
                              "items": {
                                "type": "object"
                              },
                              "description": "建議的分房組合（每組一間房，含旅客與需確認註記）。"
                            },
                            "unmatched": {
                              "type": "array",
                              "items": {
                                "type": "object"
                              },
                              "description": "無法安全自動配對、待人工處理的旅客。"
                            }
                          },
                          "required": [
                            "groups",
                            "unmatched"
                          ],
                          "description": "auto-pair 引擎產出的分房建議（未寫入，供線控確認）。"
                        },
                        "names": {
                          "type": "object",
                          "description": "travelerId → 顯示名（建議分組渲染用）。"
                        }
                      },
                      "required": [
                        "suggestion",
                        "names"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure.update"
      }
    },
    "/departures/{depId}/template-costs": {
      "get": {
        "operationId": "get_departures_depId_template_costs",
        "tags": [
          "departures"
        ],
        "summary": "該梯次套用的成本範本列",
        "description": "GET /api/v1/departures/{depId}/template-costs — 該梯次套用的成本範本列（含手動\noverride 狀態）。tenant-wide（無 owner-scope）。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "梯次成本列 ID。"
                          },
                          "category": {
                            "type": "string",
                            "description": "成本分類（如 交通 / 餐費 / 保險）。"
                          },
                          "vendorName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "供應商 / 廠商名（可空）。"
                          },
                          "description": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "摘要說明（可空）。"
                          },
                          "amountTwd": {
                            "type": "number",
                            "description": "內帳成本金額（TWD；數量 × 單價派生）。"
                          },
                          "invoiceAmountTwd": {
                            "type": "number",
                            "description": "報帳／發票金額（TWD；is_declarable=true 時同步 amount，否則 0）。"
                          },
                          "isDeclarable": {
                            "type": "boolean",
                            "description": "是否有合法憑證可報帳（開發票）。"
                          },
                          "quantityMode": {
                            "anyOf": [
                              {},
                              {
                                "type": "null"
                              }
                            ],
                            "description": "數量模式：fixed 固定值 / headcount 依人頭公式（ceil(Σ人頭 / 組距)）。"
                          },
                          "headcountComponents": {
                            "type": [
                              "array",
                              "null"
                            ],
                            "items": {},
                            "description": "headcount 模式選定的人頭 component（passenger / leader / assistant / driver）；fixed 為 null。"
                          },
                          "groupDivisor": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "headcount 模式的組距（每 N 人一組，ceil 進位）；null = 直接加總。"
                          },
                          "quantity": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "實際套用的數量（依 quantityMode 派生）。"
                          },
                          "unitPriceTwd": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "內帳單價（TWD；外幣列可為 null）。"
                          },
                          "currency": {
                            "type": "string",
                            "description": "幣別（'TWD' = 台幣列）。"
                          },
                          "unitPriceForeign": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "外幣單價；TWD 列 null。"
                          },
                          "foreignAmount": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "外幣金額快照 = unit_price_foreign × quantity；TWD 列 null。"
                          },
                          "internalRate": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "內帳匯率快照（numeric 字串）；TWD 列 null。"
                          },
                          "externalRate": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "外帳匯率快照（numeric 字串）；TWD 列 null。"
                          },
                          "isManualOverride": {
                            "type": "boolean",
                            "description": "是否為線控手動改寫（true 時重算會跳過此列，不覆蓋手改值）。"
                          },
                          "payableId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "已轉請款 → 鎖定（不可手改 / 重算）。"
                          }
                        },
                        "required": [
                          "id",
                          "category",
                          "vendorName",
                          "description",
                          "amountTwd",
                          "invoiceAmountTwd",
                          "isDeclarable",
                          "quantityMode",
                          "headcountComponents",
                          "groupDivisor",
                          "quantity",
                          "unitPriceTwd",
                          "currency",
                          "unitPriceForeign",
                          "foreignAmount",
                          "internalRate",
                          "externalRate",
                          "isManualOverride",
                          "payableId"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure.update"
      }
    },
    "/departures/{depId}/template-costs/{id}/clear-override": {
      "post": {
        "operationId": "post_departures_depId_template_costs_id_clear_override",
        "tags": [
          "departures"
        ],
        "summary": "重設為範本算法",
        "description": "POST /api/v1/departures/{depId}/template-costs/{id}/clear-override — 重設為範本算法\n（清手改鎖 + 立即重算）。同核心 op + core 內建 audit，鏡像後台\n`clearTemplateCostOverrideAction`；gated departure_cost.manage。CostTemplateError → 409。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "範本成本列 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "清除手改鎖並重算成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_cost.manage"
      }
    },
    "/departures/{depId}/template-costs/{id}/override": {
      "post": {
        "operationId": "post_departures_depId_template_costs_id_override",
        "tags": [
          "departures"
        ],
        "summary": "線控手改某範本成本列",
        "description": "POST /api/v1/departures/{depId}/template-costs/{id}/override — 線控手改某範本成本列\n金額（設 is_manual_override=true 停止自動重算）。同核心 op + core 內建 audit，鏡像\n後台 `overrideTemplateCostAction`；gated departure_cost.manage。CostTemplateError → 409。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "範本成本列 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "手改金額成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_cost.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "amountTwd": {
                    "type": "number",
                    "description": "手動指定的成本金額（台幣），設定後停止自動重算"
                  }
                },
                "required": [
                  "amountTwd"
                ]
              }
            }
          }
        }
      }
    },
    "/departures/{depId}/template-costs/apply": {
      "post": {
        "operationId": "post_departures_depId_template_costs_apply",
        "tags": [
          "departures"
        ],
        "summary": "套用行程綁定範本到本梯次",
        "description": "POST /api/v1/departures/{depId}/template-costs/apply — 套用行程綁定範本到本梯次\n（補套缺的範本成本行，冪等）。同核心 op + core 內建 audit，鏡像後台\n`applyTemplateAction`；gated departure_cost.create。CostTemplateError → 409。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "套用成功旗標，恆為 true。"
                        },
                        "inserted": {
                          "type": "number",
                          "description": "本次新補插入的範本成本行數（冪等，已存在的不重複插）。"
                        }
                      },
                      "required": [
                        "ok",
                        "inserted"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_cost.create"
      }
    },
    "/departures/{depId}/validation-summary": {
      "get": {
        "operationId": "get_departures_depId_validation_summary",
        "tags": [
          "departures"
        ],
        "summary": "該梯次各訂單旅客資料完整度",
        "description": "GET /api/v1/departures/{depId}/validation-summary — 該梯次各訂單旅客資料完整度\n驗證摘要（證件 / 必填欄缺漏）。tenant-wide（無 owner-scope）。",
        "parameters": [
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "orderId": {
                            "type": "string",
                            "description": "訂單 id。"
                          },
                          "orderNumber": {
                            "type": "string",
                            "description": "訂單編號。"
                          },
                          "errorCount": {
                            "type": "number",
                            "description": "該訂單的 error（必補缺漏）項目數。"
                          },
                          "warningCount": {
                            "type": "number",
                            "description": "該訂單的 warning（建議補齊）項目數。"
                          },
                          "incompleteTravelerCount": {
                            "type": "number",
                            "description": "至少有一項 error 或 warning 的旅客數（資料待補人數）。"
                          },
                          "errorTravelerCount": {
                            "type": "number",
                            "description": "含 error 的旅客數（出團前置紅標用）。"
                          }
                        },
                        "required": [
                          "orderId",
                          "orderNumber",
                          "errorCount",
                          "warningCount",
                          "incompleteTravelerCount",
                          "errorTravelerCount"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.read"
      }
    },
    "/departures/control": {
      "get": {
        "operationId": "get_departures_control",
        "tags": [
          "departures"
        ],
        "summary": "團控主列表：以出發日為主軸、彙整 order/付款/同意書",
        "description": "GET /api/v1/departures/control — 團控主列表：以出發日為主軸、彙整 order/付款/同意書\n統計的近期梯次清單（/admin/control 主表）。tenant-wide（無 owner-scope）。\nrange 對應視窗：future_60(60 天) / this_month / next_month。",
        "parameters": [
          {
            "name": "range",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "future_60",
                "this_month",
                "next_month"
              ],
              "description": "時間視窗：future_60（未來 60 天）/ this_month（本月）/ next_month（下個月），預設不限"
            }
          },
          {
            "name": "trip",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "行程 ID，只看該行程的梯次"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "梯次狀態篩選（如 open / closed）"
            }
          },
          {
            "name": "attention",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "設為 true 時只回傳付款或同意書有異常、需要關注的梯次"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "梯次 id。"
                          },
                          "tripId": {
                            "type": "string",
                            "description": "所屬行程 id。"
                          },
                          "tripTitle": {
                            "type": "string",
                            "description": "行程名稱。"
                          },
                          "tripSlug": {
                            "type": "string",
                            "description": "行程公開頁網址代稱（slug）。"
                          },
                          "groupCode": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "團號（可空）。"
                          },
                          "departureDate": {
                            "type": "string",
                            "description": "出發日（YYYY-MM-DD）。"
                          },
                          "returnDate": {
                            "type": "string",
                            "description": "回程日（YYYY-MM-DD）。"
                          },
                          "capacity": {
                            "type": "number",
                            "description": "團位容量（總名額）。"
                          },
                          "bookedCount": {
                            "type": "number",
                            "description": "已佔位人數。"
                          },
                          "status": {
                            "type": "string",
                            "description": "梯次狀態（如 open 開放／closed 關閉）。"
                          },
                          "allocationMode": {
                            "type": "string",
                            "enum": [
                              "fcfs",
                              "lottery"
                            ],
                            "description": "佔位模式：fcfs 先到先得／lottery 抽籤。"
                          },
                          "leaderNames": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "已排領隊姓名（confirmed + tentative 皆列；空 = 未指派）。"
                          },
                          "assistantNames": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "已排協作 / 助教姓名（空 = 未指派協作）。"
                          },
                          "priceTwd": {
                            "type": "number",
                            "description": "定價（TWD）。"
                          },
                          "agencyPriceTwd": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "同業／旅行社報價（TWD；未設為 null）。"
                          },
                          "promoActive": {
                            "type": "boolean",
                            "description": "是否有進行中的促銷價。"
                          },
                          "promoPriceTwd": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "促銷價（TWD；無促銷為 null）。"
                          },
                          "promoAgencyPriceTwd": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "同業促銷價（TWD；無促銷為 null）。"
                          },
                          "daysUntilDeparture": {
                            "type": "number",
                            "description": "距出發天數（負值表示已出發）。"
                          },
                          "travelerCount": {
                            "type": "number",
                            "description": "旅客總人數（未取消訂單的 party_size 加總）。"
                          },
                          "paidCount": {
                            "type": "number",
                            "description": "已付款人數（party_size 加總）。"
                          },
                          "pendingCount": {
                            "type": "number",
                            "description": "未結清人數（未付／部分付／已付訂金；不含取消）。"
                          },
                          "cancelledCount": {
                            "type": "number",
                            "description": "已取消人數（僅供參考，不計入總數）。"
                          },
                          "ordersWithoutConsent": {
                            "type": "number",
                            "description": "尚未簽署同意書（PDPA）的訂單數。"
                          },
                          "codedRevenueTwd": {
                            "type": "number",
                            "description": "有折扣訂單的應收營收合計（TWD；排除取消／退款）。"
                          },
                          "discountTotalTwd": {
                            "type": "number",
                            "description": "折扣金額合計（TWD）。"
                          },
                          "profitShareTotalTwd": {
                            "type": "number",
                            "description": "利潤分潤金額合計（TWD）。"
                          }
                        },
                        "required": [
                          "id",
                          "tripId",
                          "tripTitle",
                          "tripSlug",
                          "groupCode",
                          "departureDate",
                          "returnDate",
                          "capacity",
                          "bookedCount",
                          "status",
                          "allocationMode",
                          "leaderNames",
                          "assistantNames",
                          "priceTwd",
                          "agencyPriceTwd",
                          "promoActive",
                          "promoPriceTwd",
                          "promoAgencyPriceTwd",
                          "daysUntilDeparture",
                          "travelerCount",
                          "paidCount",
                          "pendingCount",
                          "cancelledCount",
                          "ordersWithoutConsent",
                          "codedRevenueTwd",
                          "discountTotalTwd",
                          "profitShareTotalTwd"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.read"
      }
    },
    "/departures/room-stats": {
      "get": {
        "operationId": "get_departures_room_stats",
        "tags": [
          "departures"
        ],
        "summary": "多梯次的分房進度統計",
        "description": "GET /api/v1/departures/room-stats?ids=a,b,c — 多梯次的分房進度統計（房數 / 已排 /\n總旅客數）。tenant-wide（無 owner-scope）。core 回傳 Map，序列化為\n{ [departureId]: { roomCount, assignedCount, totalTravelers } }。",
        "parameters": [
          {
            "name": "ids",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "要查詢的梯次 ID 清單，以逗號分隔（例：a,b,c）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {}
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.read"
      }
    },
    "/discount-codes": {
      "get": {
        "operationId": "get_discount_codes",
        "tags": [
          "discount-codes"
        ],
        "summary": "list all discount codes",
        "description": "GET /api/v1/discount-codes — list all discount codes (the /admin/discount-codes\ntable over HTTP). Tenant-wide read (no owner scope); same `discount.read` gate\nas the back office. See specs/tenant-cli.md.\n\nPOST /api/v1/discount-codes — create a discount code (mirrors\ncreateDiscountCodeAction). Same `discount.manage` gate, same `createDiscountCode`\ncore fn + args (the core fn writes the `discount.create` audit row inside its\nown tx, so the route does not replicate writeAuditLog). Duplicate code → 409.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "折扣碼 id（disc_ 前綴）。"
                          },
                          "code": {
                            "type": "string",
                            "description": "折扣碼字串（客戶結帳輸入用，租戶內唯一）。"
                          },
                          "label": {
                            "type": "string",
                            "description": "折扣碼顯示名稱（後台辨識用）。"
                          },
                          "discountType": {
                            "description": "折扣型別：fixed 定額折抵 / percentage 比例折抵。"
                          },
                          "discountValue": {
                            "type": "number",
                            "description": "折扣值：fixed 為 TWD 整數，percentage 為百分比數字。"
                          },
                          "profitShareType": {
                            "anyOf": [
                              {},
                              {
                                "type": "null"
                              }
                            ],
                            "description": "分潤型別：fixed 定額 / percentage 比例；null = 無分潤。"
                          },
                          "profitShareValue": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "分潤值：fixed 為 TWD 整數，percentage 為百分比；null = 無分潤。"
                          },
                          "profitSharePayee": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "分潤受款對象（如合作夥伴名稱）；null = 無。"
                          },
                          "isActive": {
                            "type": "boolean",
                            "description": "是否啟用（停用後不可再兌換）。"
                          },
                          "validFrom": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time",
                            "description": "生效起始時間；null = 無下限。"
                          },
                          "validUntil": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time",
                            "description": "生效截止時間；null = 無上限。"
                          },
                          "maxRedemptions": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "總兌換次數上限；null = 不限。"
                          },
                          "redemptionCount": {
                            "type": "number",
                            "description": "已兌換次數（不含已取消訂單）。"
                          },
                          "minOrderTwd": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "最低訂單金額門檻（TWD 整數）；null = 無門檻。"
                          },
                          "appliesToAll": {
                            "type": "boolean",
                            "description": "是否適用所有行程（true = 全站，false = 僅限 tripIds 名單）。"
                          },
                          "maxRedemptionsPerCustomer": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "每位客戶兌換次數上限；null = 不限。"
                          },
                          "allowedPriceChannels": {
                            "type": [
                              "array",
                              "null"
                            ],
                            "items": {
                              "type": "string"
                            },
                            "description": "限用的價格通路清單（如 direct / agency）；null = 不限。"
                          },
                          "allowedCustomerTypes": {
                            "type": [
                              "array",
                              "null"
                            ],
                            "items": {
                              "type": "string"
                            },
                            "description": "限用的客戶類型清單；null = 不限。"
                          },
                          "stackable": {
                            "type": "boolean",
                            "description": "是否可與其他折扣疊加使用。"
                          },
                          "notes": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "內部備註；null = 無。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          }
                        },
                        "required": [
                          "id",
                          "code",
                          "label",
                          "discountType",
                          "discountValue",
                          "profitShareType",
                          "profitShareValue",
                          "profitSharePayee",
                          "isActive",
                          "validFrom",
                          "validUntil",
                          "maxRedemptions",
                          "redemptionCount",
                          "minOrderTwd",
                          "appliesToAll",
                          "maxRedemptionsPerCustomer",
                          "allowedPriceChannels",
                          "allowedCustomerTypes",
                          "stackable",
                          "notes",
                          "createdAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "discount.read"
      },
      "post": {
        "operationId": "post_discount_codes",
        "tags": [
          "discount-codes"
        ],
        "summary": "create a discount code",
        "description": "GET /api/v1/discount-codes — list all discount codes (the /admin/discount-codes\ntable over HTTP). Tenant-wide read (no owner scope); same `discount.read` gate\nas the back office. See specs/tenant-cli.md.\n\nPOST /api/v1/discount-codes — create a discount code (mirrors\ncreateDiscountCodeAction). Same `discount.manage` gate, same `createDiscountCode`\ncore fn + args (the core fn writes the `discount.create` audit row inside its\nown tx, so the route does not replicate writeAuditLog). Duplicate code → 409.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立折扣碼的 id（disc_ 前綴）。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "discount.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "折扣碼字串（前台結帳輸入，不分大小寫須唯一）（max 64 · min 1）"
                  },
                  "label": {
                    "type": "string",
                    "description": "折扣碼顯示名稱（後台與報表辨識用）（max 200 · min 1）"
                  },
                  "discountType": {
                    "type": "string",
                    "enum": [
                      "fixed",
                      "percentage"
                    ],
                    "description": "折抵方式：fixed 固定金額（TWD）或 percentage 百分比"
                  },
                  "discountValue": {
                    "type": "number",
                    "description": "折抵數值；fixed 為折抵金額（TWD），percentage 為百分比（1–100）"
                  },
                  "profitShareType": {
                    "type": "string",
                    "enum": [
                      "fixed",
                      "percentage"
                    ],
                    "description": "分潤方式：fixed 固定金額或 percentage 百分比；null 為不分潤"
                  },
                  "profitShareValue": {
                    "type": "number",
                    "description": "分潤數值；搭配 profitShareType，percentage 須 1–100，null 為不分潤"
                  },
                  "profitSharePayee": {
                    "type": "string",
                    "description": "分潤對象名稱（如合作推廣者），供出款對帳辨識（max 200）"
                  },
                  "isActive": {
                    "type": "boolean",
                    "description": "是否啟用；停用後前台無法套用"
                  },
                  "validFrom": {
                    "type": "string",
                    "description": "生效起日（YYYY-MM-DD）；留空為不限起日"
                  },
                  "validUntil": {
                    "type": "string",
                    "description": "生效迄日（YYYY-MM-DD）；留空為不限迄日"
                  },
                  "maxRedemptions": {
                    "type": "number",
                    "description": "全碼可使用總次數上限；null 為不限"
                  },
                  "minOrderTwd": {
                    "type": "number",
                    "description": "最低訂單金額門檻（TWD），未達門檻不可套用；null 為不限"
                  },
                  "appliesToAll": {
                    "type": "boolean",
                    "description": "是否適用全部行程；true 時忽略 tripIds"
                  },
                  "tripIds": {
                    "type": "array",
                    "items": {},
                    "description": "指定可套用的行程 id 清單（appliesToAll=false 時生效）"
                  },
                  "maxRedemptionsPerCustomer": {
                    "type": "number",
                    "description": "每位客戶可使用次數上限；null 為不限"
                  },
                  "allowedPriceChannels": {
                    "type": "array",
                    "items": {},
                    "description": "可套用的價格渠道（direct 直客 / agency 同業 / promo 優惠）；空陣列為不限"
                  },
                  "allowedCustomerTypes": {
                    "type": "array",
                    "items": {},
                    "description": "可套用的客戶類型（direct 直客 / agency_contact 同業聯絡人）；空陣列為不限"
                  },
                  "stackable": {
                    "type": "boolean",
                    "description": "是否可與其他折扣碼疊加使用"
                  },
                  "notes": {
                    "type": "string",
                    "description": "內部備註（不對外顯示）（max 2000）"
                  }
                },
                "required": [
                  "code",
                  "label",
                  "discountType",
                  "discountValue"
                ]
              }
            }
          }
        }
      }
    },
    "/discount-codes/{id}": {
      "get": {
        "operationId": "get_discount_codes_id_",
        "tags": [
          "discount-codes"
        ],
        "summary": "full discount code detail",
        "description": "GET /api/v1/discount-codes/{id} — full discount code detail (header + applicable\ntrip ids + redemptions[] + redemption/profit-share totals). Missing → 404.\nTenant-wide read gated by `discount.read`.\n\nPATCH /api/v1/discount-codes/{id} — update a discount code (mirrors\nupdateDiscountCodeAction). Same `discount.manage` gate, same `updateDiscountCode`\ncore fn + args (core writes the `discount.update` audit row in its own tx, so the\nroute does not replicate writeAuditLog). NOT_FOUND → 404, CODE_DUPLICATE → 409.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "折扣碼 id（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "折扣碼 id（disc_ 前綴）。"
                        },
                        "code": {
                          "type": "string",
                          "description": "折扣碼字串（客戶結帳輸入用，租戶內唯一）。"
                        },
                        "label": {
                          "type": "string",
                          "description": "折扣碼顯示名稱（後台辨識用）。"
                        },
                        "discountType": {
                          "description": "折扣型別：fixed 定額折抵 / percentage 比例折抵。"
                        },
                        "discountValue": {
                          "type": "number",
                          "description": "折扣值：fixed 為 TWD 整數，percentage 為百分比數字。"
                        },
                        "profitShareType": {
                          "anyOf": [
                            {},
                            {
                              "type": "null"
                            }
                          ],
                          "description": "分潤型別：fixed 定額 / percentage 比例；null = 無分潤。"
                        },
                        "profitShareValue": {
                          "type": [
                            "number",
                            "null"
                          ],
                          "description": "分潤值：fixed 為 TWD 整數，percentage 為百分比；null = 無分潤。"
                        },
                        "profitSharePayee": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "分潤受款對象（如合作夥伴名稱）；null = 無。"
                        },
                        "isActive": {
                          "type": "boolean",
                          "description": "是否啟用（停用後不可再兌換）。"
                        },
                        "validFrom": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "生效起始時間；null = 無下限。"
                        },
                        "validUntil": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "生效截止時間；null = 無上限。"
                        },
                        "maxRedemptions": {
                          "type": [
                            "number",
                            "null"
                          ],
                          "description": "總兌換次數上限；null = 不限。"
                        },
                        "redemptionCount": {
                          "type": "number",
                          "description": "已兌換次數（不含已取消訂單）。"
                        },
                        "minOrderTwd": {
                          "type": [
                            "number",
                            "null"
                          ],
                          "description": "最低訂單金額門檻（TWD 整數）；null = 無門檻。"
                        },
                        "appliesToAll": {
                          "type": "boolean",
                          "description": "是否適用所有行程（true = 全站，false = 僅限 tripIds 名單）。"
                        },
                        "maxRedemptionsPerCustomer": {
                          "type": [
                            "number",
                            "null"
                          ],
                          "description": "每位客戶兌換次數上限；null = 不限。"
                        },
                        "allowedPriceChannels": {
                          "type": [
                            "array",
                            "null"
                          ],
                          "items": {
                            "type": "string"
                          },
                          "description": "限用的價格通路清單（如 direct / agency）；null = 不限。"
                        },
                        "allowedCustomerTypes": {
                          "type": [
                            "array",
                            "null"
                          ],
                          "items": {
                            "type": "string"
                          },
                          "description": "限用的客戶類型清單；null = 不限。"
                        },
                        "stackable": {
                          "type": "boolean",
                          "description": "是否可與其他折扣疊加使用。"
                        },
                        "notes": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "內部備註；null = 無。"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "建立時間。"
                        },
                        "tripIds": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "限定適用的行程 id 清單（appliesToAll=false 時生效）。"
                        },
                        "redemptions": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "orderId": {
                                "type": "string",
                                "description": "兌換該折扣碼的訂單 id（ord_ 前綴）。"
                              },
                              "orderNumber": {
                                "type": "string",
                                "description": "訂單編號（人類可讀流水號）。"
                              },
                              "codeSnapshot": {
                                "type": "string",
                                "description": "兌換當下的折扣碼字串快照。"
                              },
                              "originalTotalTwd": {
                                "type": "number",
                                "description": "套用折扣前的原始應收總額（TWD 整數）。"
                              },
                              "discountTwd": {
                                "type": "number",
                                "description": "本次折抵金額（TWD 整數）。"
                              },
                              "profitShareTwd": {
                                "type": "number",
                                "description": "本次分潤金額（TWD 整數）。"
                              },
                              "orderStatus": {
                                "type": "string",
                                "description": "訂單當前狀態。"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "兌換（下單）時間。"
                              }
                            },
                            "required": [
                              "orderId",
                              "orderNumber",
                              "codeSnapshot",
                              "originalTotalTwd",
                              "discountTwd",
                              "profitShareTwd",
                              "orderStatus",
                              "createdAt"
                            ]
                          },
                          "description": "逐筆兌換紀錄。"
                        },
                        "totalDiscountTwd": {
                          "type": "number",
                          "description": "累計折抵金額合計（TWD 整數）。"
                        },
                        "totalProfitShareTwd": {
                          "type": "number",
                          "description": "累計分潤金額合計（TWD 整數）。"
                        },
                        "totalPaidTwd": {
                          "type": "number",
                          "description": "兌換訂單累計已收金額合計（TWD 整數）。"
                        }
                      },
                      "required": [
                        "id",
                        "code",
                        "label",
                        "discountType",
                        "discountValue",
                        "profitShareType",
                        "profitShareValue",
                        "profitSharePayee",
                        "isActive",
                        "validFrom",
                        "validUntil",
                        "maxRedemptions",
                        "redemptionCount",
                        "minOrderTwd",
                        "appliesToAll",
                        "maxRedemptionsPerCustomer",
                        "allowedPriceChannels",
                        "allowedCustomerTypes",
                        "stackable",
                        "notes",
                        "createdAt",
                        "tripIds",
                        "redemptions",
                        "totalDiscountTwd",
                        "totalProfitShareTwd",
                        "totalPaidTwd"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "discount.read"
      },
      "patch": {
        "operationId": "patch_discount_codes_id_",
        "tags": [
          "discount-codes"
        ],
        "summary": "update a discount code",
        "description": "GET /api/v1/discount-codes/{id} — full discount code detail (header + applicable\ntrip ids + redemptions[] + redemption/profit-share totals). Missing → 404.\nTenant-wide read gated by `discount.read`.\n\nPATCH /api/v1/discount-codes/{id} — update a discount code (mirrors\nupdateDiscountCodeAction). Same `discount.manage` gate, same `updateDiscountCode`\ncore fn + args (core writes the `discount.update` audit row in its own tx, so the\nroute does not replicate writeAuditLog). NOT_FOUND → 404, CODE_DUPLICATE → 409.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "折扣碼 id（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "discount.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "折扣碼字串（前台結帳輸入，不分大小寫須唯一）（max 64 · min 1）"
                  },
                  "label": {
                    "type": "string",
                    "description": "折扣碼顯示名稱（後台與報表辨識用）（max 200 · min 1）"
                  },
                  "discountType": {
                    "type": "string",
                    "enum": [
                      "fixed",
                      "percentage"
                    ],
                    "description": "折抵方式：fixed 固定金額（TWD）或 percentage 百分比"
                  },
                  "discountValue": {
                    "type": "number",
                    "description": "折抵數值；fixed 為折抵金額（TWD），percentage 為百分比（1–100）"
                  },
                  "profitShareType": {
                    "type": "string",
                    "enum": [
                      "fixed",
                      "percentage"
                    ],
                    "description": "分潤方式：fixed 固定金額或 percentage 百分比；null 為不分潤"
                  },
                  "profitShareValue": {
                    "type": "number",
                    "description": "分潤數值；搭配 profitShareType，percentage 須 1–100，null 為不分潤"
                  },
                  "profitSharePayee": {
                    "type": "string",
                    "description": "分潤對象名稱（如合作推廣者），供出款對帳辨識（max 200）"
                  },
                  "isActive": {
                    "type": "boolean",
                    "description": "是否啟用；停用後前台無法套用"
                  },
                  "validFrom": {
                    "type": "string",
                    "description": "生效起日（YYYY-MM-DD）；留空為不限起日"
                  },
                  "validUntil": {
                    "type": "string",
                    "description": "生效迄日（YYYY-MM-DD）；留空為不限迄日"
                  },
                  "maxRedemptions": {
                    "type": "number",
                    "description": "全碼可使用總次數上限；null 為不限"
                  },
                  "minOrderTwd": {
                    "type": "number",
                    "description": "最低訂單金額門檻（TWD），未達門檻不可套用；null 為不限"
                  },
                  "appliesToAll": {
                    "type": "boolean",
                    "description": "是否適用全部行程；true 時忽略 tripIds"
                  },
                  "tripIds": {
                    "type": "array",
                    "items": {},
                    "description": "指定可套用的行程 id 清單（appliesToAll=false 時生效）"
                  },
                  "maxRedemptionsPerCustomer": {
                    "type": "number",
                    "description": "每位客戶可使用次數上限；null 為不限"
                  },
                  "allowedPriceChannels": {
                    "type": "array",
                    "items": {},
                    "description": "可套用的價格渠道（direct 直客 / agency 同業 / promo 優惠）；空陣列為不限"
                  },
                  "allowedCustomerTypes": {
                    "type": "array",
                    "items": {},
                    "description": "可套用的客戶類型（direct 直客 / agency_contact 同業聯絡人）；空陣列為不限"
                  },
                  "stackable": {
                    "type": "boolean",
                    "description": "是否可與其他折扣碼疊加使用"
                  },
                  "notes": {
                    "type": "string",
                    "description": "內部備註（不對外顯示）（max 2000）"
                  }
                },
                "required": [
                  "code",
                  "label",
                  "discountType",
                  "discountValue"
                ]
              }
            }
          }
        }
      }
    },
    "/discount-codes/{id}/redemptions": {
      "get": {
        "operationId": "get_discount_codes_id_redemptions",
        "tags": [
          "discount-codes"
        ],
        "summary": "redemption/profit-share report for",
        "description": "GET /api/v1/discount-codes/{id}/redemptions — redemption/profit-share report for\none code. Reuses getDiscountCodeDetail and projects the report-relevant slice\n(the redemptions[] rows + redemption/discount/profit-share/paid totals).\nMissing code → 404. Tenant-wide read gated by `discount.read`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "折扣碼 id（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "折扣碼 id（disc_ 前綴）。"
                        },
                        "code": {
                          "type": "string",
                          "description": "折扣碼字串。"
                        },
                        "label": {
                          "type": "string",
                          "description": "折扣碼顯示名稱。"
                        },
                        "redemptionCount": {
                          "type": "number",
                          "description": "已兌換次數（不含已取消訂單）。"
                        },
                        "totalDiscountTwd": {
                          "type": "number",
                          "description": "累計折抵金額合計（TWD 整數）。"
                        },
                        "totalProfitShareTwd": {
                          "type": "number",
                          "description": "累計分潤金額合計（TWD 整數）。"
                        },
                        "totalPaidTwd": {
                          "type": "number",
                          "description": "兌換訂單累計已收金額合計（TWD 整數）。"
                        },
                        "redemptions": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "orderId": {
                                "type": "string",
                                "description": "兌換該折扣碼的訂單 id（ord_ 前綴）。"
                              },
                              "orderNumber": {
                                "type": "string",
                                "description": "訂單編號（人類可讀流水號）。"
                              },
                              "codeSnapshot": {
                                "type": "string",
                                "description": "兌換當下的折扣碼字串快照。"
                              },
                              "originalTotalTwd": {
                                "type": "number",
                                "description": "套用折扣前的原始應收總額（TWD 整數）。"
                              },
                              "discountTwd": {
                                "type": "number",
                                "description": "本次折抵金額（TWD 整數）。"
                              },
                              "profitShareTwd": {
                                "type": "number",
                                "description": "本次分潤金額（TWD 整數）。"
                              },
                              "orderStatus": {
                                "type": "string",
                                "description": "訂單當前狀態。"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "兌換（下單）時間。"
                              }
                            },
                            "required": [
                              "orderId",
                              "orderNumber",
                              "codeSnapshot",
                              "originalTotalTwd",
                              "discountTwd",
                              "profitShareTwd",
                              "orderStatus",
                              "createdAt"
                            ]
                          },
                          "description": "逐筆兌換紀錄。"
                        }
                      },
                      "required": [
                        "id",
                        "code",
                        "label",
                        "redemptionCount",
                        "totalDiscountTwd",
                        "totalProfitShareTwd",
                        "totalPaidTwd",
                        "redemptions"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "discount.read"
      }
    },
    "/discount-codes/{id}/set-active": {
      "post": {
        "operationId": "post_discount_codes_id_set_active",
        "tags": [
          "discount-codes"
        ],
        "summary": "activate / deactivate a discount",
        "description": "POST /api/v1/discount-codes/{id}/set-active — activate / deactivate a discount\ncode (mirrors setDiscountCodeActiveAction). Same `discount.manage` gate, same\n`setDiscountCodeActive` core fn + args (core writes the `discount.set_active`\naudit row in its own tx, so the route does not replicate writeAuditLog).\nMissing → 404.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "折扣碼 id（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "discount.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "isActive": {
                    "type": "boolean",
                    "description": "目標啟用狀態：true 啟用、false 停用"
                  }
                },
                "required": [
                  "isActive"
                ]
              }
            }
          }
        }
      }
    },
    "/discount-codes/preview": {
      "get": {
        "operationId": "get_discount_codes_preview",
        "tags": [
          "discount-codes"
        ],
        "summary": "read-only checkout preview of a code's",
        "description": "GET /api/v1/discount-codes/preview — read-only checkout preview of a code's\ndiscount/profit-share for a given product context. Mirrors the same gating +\ncalculation as the live checkout apply, but SELECT-only (does NOT consume a\nredemption). Returns the core result envelope ({ ok:true, … } | { ok:false,\nreason }) verbatim so the CLI can branch on the machine reason. Tenant-wide\nread gated by `discount.read`.",
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "欲試算的折扣碼字串（min 1）"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "tour",
                "lodging"
              ],
              "description": "產品種類：tour 行程或 lodging 住宿"
            }
          },
          {
            "name": "tripId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "行程 id（kind=tour 時必填）"
            }
          },
          {
            "name": "total",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number",
              "description": "試算用原始金額（TWD，未折扣前）"
            }
          },
          {
            "name": "priceChannel",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "價格渠道（direct / agency / promo），用於折扣碼資格判定"
            }
          },
          {
            "name": "customerType",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "客戶類型（direct / agency_contact），用於折扣碼資格判定"
            }
          },
          {
            "name": "userId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "客戶 user id，用於每客戶使用次數限制判定"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {}
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "discount.read"
      }
    },
    "/equipment/items": {
      "get": {
        "operationId": "get_equipment_items",
        "tags": [
          "equipment"
        ],
        "summary": "list the equipment master",
        "description": "GET /api/v1/equipment/items — list the equipment master (rentable inventory),\nthe /admin/equipment items table over HTTP. Tenant-wide (no owner scope).\n`activeOnly` filters to currently-rentable items.\n\nPOST /api/v1/equipment/items — create a master item. Mirrors back-office\n`createEquipmentItemAction`: equipment.manage gate + climbing-module gate +\nsame core `createEquipmentItem` + same shell-side writeAuditLog\n(equipment.item.create). See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "activeOnly",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "只列出啟用中（可租借）的品項"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "裝備主檔品項 id（equipmentItem_ 前綴）。"
                          },
                          "name": {
                            "type": "string",
                            "description": "品名。"
                          },
                          "category": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "分類（如帳篷／睡袋／爐具；未分類為 null）。"
                          },
                          "spec": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "規格描述（尺寸／型號等；可空）。"
                          },
                          "rentPriceTwd": {
                            "type": "number",
                            "description": "每日租金單價（TWD）。"
                          },
                          "depositTwd": {
                            "type": "number",
                            "description": "每件押金（TWD）。"
                          },
                          "totalCount": {
                            "type": "number",
                            "description": "庫存總件數。"
                          },
                          "outCount": {
                            "type": "number",
                            "description": "目前在外（已借出未歸還）件數。"
                          },
                          "maintenanceCount": {
                            "type": "number",
                            "description": "維修中件數（不可借出）。"
                          },
                          "availableCount": {
                            "type": "number",
                            "description": "可租 = total − out − maintenance（派生，便利 UI）。"
                          },
                          "isActive": {
                            "type": "boolean",
                            "description": "是否啟用（可租借）。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建檔時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "category",
                          "spec",
                          "rentPriceTwd",
                          "depositTwd",
                          "totalCount",
                          "outCount",
                          "maintenanceCount",
                          "availableCount",
                          "isActive",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "equipment.read"
      },
      "post": {
        "operationId": "post_equipment_items",
        "tags": [
          "equipment"
        ],
        "summary": "create a master item",
        "description": "GET /api/v1/equipment/items — list the equipment master (rentable inventory),\nthe /admin/equipment items table over HTTP. Tenant-wide (no owner scope).\n`activeOnly` filters to currently-rentable items.\n\nPOST /api/v1/equipment/items — create a master item. Mirrors back-office\n`createEquipmentItemAction`: equipment.manage gate + climbing-module gate +\nsame core `createEquipmentItem` + same shell-side writeAuditLog\n(equipment.item.create). See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立的裝備品項 id。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "equipment.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "裝備品項名稱（max 200 · min 1）"
                  },
                  "category": {
                    "type": "string",
                    "description": "裝備分類（如帳篷、睡袋；選填）（max 50）"
                  },
                  "spec": {
                    "type": "string",
                    "description": "規格說明（如尺寸、型號；選填）（max 500）"
                  },
                  "rentPriceTwd": {
                    "type": "number",
                    "description": "每日租金（台幣）（min 0）"
                  },
                  "depositTwd": {
                    "type": "number",
                    "description": "每件押金（台幣）（min 0）"
                  },
                  "totalCount": {
                    "type": "number",
                    "description": "總庫存數量（min 0）"
                  },
                  "maintenanceCount": {
                    "type": "number",
                    "description": "維修中而不可租借的數量（min 0）"
                  },
                  "isActive": {
                    "type": "boolean",
                    "description": "是否啟用（可供租借）"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/equipment/items/{id}": {
      "get": {
        "operationId": "get_equipment_items_id_",
        "tags": [
          "equipment"
        ],
        "summary": "single equipment master item detail.",
        "description": "GET /api/v1/equipment/items/{id} — single equipment master item detail.\nTenant-wide; missing → 404.\n\nPATCH /api/v1/equipment/items/{id} — update a master item. Mirrors back-office\n`updateEquipmentItemAction`: equipment.manage gate + climbing-module gate +\nsame core `updateEquipmentItem` + same shell-side writeAuditLog\n(equipment.item.update). A CHECK violation (total/maintenance breaking the\nout+maint ≤ total invariant) → 409, mirroring the action's friendly message.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "裝備品項 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "裝備主檔品項 id（equipmentItem_ 前綴）。"
                        },
                        "name": {
                          "type": "string",
                          "description": "品名。"
                        },
                        "category": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "分類（如帳篷／睡袋／爐具；未分類為 null）。"
                        },
                        "spec": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "規格描述（尺寸／型號等；可空）。"
                        },
                        "rentPriceTwd": {
                          "type": "number",
                          "description": "每日租金單價（TWD）。"
                        },
                        "depositTwd": {
                          "type": "number",
                          "description": "每件押金（TWD）。"
                        },
                        "totalCount": {
                          "type": "number",
                          "description": "庫存總件數。"
                        },
                        "outCount": {
                          "type": "number",
                          "description": "目前在外（已借出未歸還）件數。"
                        },
                        "maintenanceCount": {
                          "type": "number",
                          "description": "維修中件數（不可借出）。"
                        },
                        "availableCount": {
                          "type": "number",
                          "description": "可租 = total − out − maintenance（派生，便利 UI）。"
                        },
                        "isActive": {
                          "type": "boolean",
                          "description": "是否啟用（可租借）。"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "建檔時間。"
                        },
                        "updatedAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "最後更新時間。"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "category",
                        "spec",
                        "rentPriceTwd",
                        "depositTwd",
                        "totalCount",
                        "outCount",
                        "maintenanceCount",
                        "availableCount",
                        "isActive",
                        "createdAt",
                        "updatedAt"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "equipment.read"
      },
      "patch": {
        "operationId": "patch_equipment_items_id_",
        "tags": [
          "equipment"
        ],
        "summary": "update a master item",
        "description": "GET /api/v1/equipment/items/{id} — single equipment master item detail.\nTenant-wide; missing → 404.\n\nPATCH /api/v1/equipment/items/{id} — update a master item. Mirrors back-office\n`updateEquipmentItemAction`: equipment.manage gate + climbing-module gate +\nsame core `updateEquipmentItem` + same shell-side writeAuditLog\n(equipment.item.update). A CHECK violation (total/maintenance breaking the\nout+maint ≤ total invariant) → 409, mirroring the action's friendly message.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "要更新的裝備品項 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "更新成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "equipment.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "裝備品項名稱（max 200 · min 1）"
                  },
                  "category": {
                    "type": "string",
                    "description": "裝備分類（如帳篷、睡袋；選填）（max 50）"
                  },
                  "spec": {
                    "type": "string",
                    "description": "規格說明（如尺寸、型號；選填）（max 500）"
                  },
                  "rentPriceTwd": {
                    "type": "number",
                    "description": "每日租金（台幣）（min 0）"
                  },
                  "depositTwd": {
                    "type": "number",
                    "description": "每件押金（台幣）（min 0）"
                  },
                  "totalCount": {
                    "type": "number",
                    "description": "總庫存數量（min 0）"
                  },
                  "maintenanceCount": {
                    "type": "number",
                    "description": "維修中而不可租借的數量（min 0）"
                  },
                  "isActive": {
                    "type": "boolean",
                    "description": "是否啟用（可供租借）"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/equipment/rentals": {
      "get": {
        "operationId": "get_equipment_rentals",
        "tags": [
          "equipment"
        ],
        "summary": "list rental tickets",
        "description": "GET /api/v1/equipment/rentals — list rental tickets (with lines), the\n/admin/equipment rentals table over HTTP. Tenant-wide (no owner scope).\nFilterable by return/recon state, order, departure.\n\nPOST /api/v1/equipment/rentals — open a rental ticket. Mirrors back-office\n`createRentalAction`: equipment.manage gate + climbing-module gate + same core\n`createRental` + same shell-side writeAuditLog (equipment.rental.create).\nNOTE: opening a rental mutates the bound order's money model (rent + deposit\ncharge lines / schedule / intent). EquipmentStockError → 409, missing item /\norder → 404. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "returnState",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "rented",
                "returned",
                "overdue"
              ],
              "description": "依歸還狀態篩選：rented 在租中、returned 已歸還、overdue 逾期"
            }
          },
          {
            "name": "reconState",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "reconciled",
                "deposit_pending"
              ],
              "description": "依驗收結算狀態篩選：pending 待驗收、reconciled 已結算、deposit_pending 待退押金"
            }
          },
          {
            "name": "orderId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "只列出綁定此訂單 ID 的租借單"
            }
          },
          {
            "name": "departureId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "只列出綁定此梯次 ID 的租借單"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "租借單 id（equipmentRental_ 前綴）。"
                          },
                          "orderId": {
                            "type": "string",
                            "description": "掛載的訂單 id。"
                          },
                          "orderNumber": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "訂單編號（JOIN；可空）。"
                          },
                          "departureId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "綁定的梯次 id（可不綁梯次時 null）。"
                          },
                          "departureLabel": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "梯次可讀標籤：團號 ‧ 行程名 ‧ 出發日（無綁梯次時 null）。"
                          },
                          "renterName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "租借人姓名（可空）。"
                          },
                          "rentStartDate": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "租期起日（YYYY-MM-DD；可空）。"
                          },
                          "rentEndDate": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "租期迄日（YYYY-MM-DD；可空）。"
                          },
                          "returnedAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time",
                            "description": "歸還驗收時間（尚未歸還為 null）。"
                          },
                          "returnState": {
                            "description": "歸還狀態：rented 租借中／returned 已歸還／overdue 逾期。"
                          },
                          "inspectedAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time",
                            "description": "驗收時間（尚未驗收為 null）。"
                          },
                          "damageCostTwd": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "破損／遺失賠償金額（TWD；無為 null）。"
                          },
                          "reconState": {
                            "description": "對款狀態：pending 待對款／reconciled 已結清／deposit_pending 押金待退或待扣。"
                          },
                          "notes": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "備註（可空）。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建單時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          },
                          "lines": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "description": "租借明細 id（equipmentRentalLine_ 前綴）。"
                                },
                                "equipmentItemId": {
                                  "type": "string",
                                  "description": "借出的裝備主檔品項 id。"
                                },
                                "itemName": {
                                  "type": [
                                    "string",
                                    "null"
                                  ],
                                  "description": "主檔品名快照（JOIN，便利顯示；改主檔不回寫單）。"
                                },
                                "quantity": {
                                  "type": "number",
                                  "description": "借出數量。"
                                },
                                "rentPriceTwdSnapshot": {
                                  "type": "number",
                                  "description": "成交單位總價快照（每日單價 × 計價日數；TWD）。"
                                },
                                "depositTwdSnapshot": {
                                  "type": "number",
                                  "description": "成交每件押金快照（TWD，不乘天數）。"
                                },
                                "returnedQuantity": {
                                  "type": [
                                    "number",
                                    "null"
                                  ],
                                  "description": "已歸還數量（尚未歸還為 null）。"
                                }
                              },
                              "required": [
                                "id",
                                "equipmentItemId",
                                "itemName",
                                "quantity",
                                "rentPriceTwdSnapshot",
                                "depositTwdSnapshot",
                                "returnedQuantity"
                              ]
                            },
                            "description": "租借明細（借出的品項清單）。"
                          },
                          "rentTotalTwd": {
                            "type": "number",
                            "description": "成交租金合計（Σ rent snapshot × qty）。"
                          },
                          "depositTotalTwd": {
                            "type": "number",
                            "description": "成交押金合計（Σ deposit snapshot × qty）。"
                          }
                        },
                        "required": [
                          "id",
                          "orderId",
                          "orderNumber",
                          "departureId",
                          "departureLabel",
                          "renterName",
                          "rentStartDate",
                          "rentEndDate",
                          "returnedAt",
                          "returnState",
                          "inspectedAt",
                          "damageCostTwd",
                          "reconState",
                          "notes",
                          "createdAt",
                          "updatedAt",
                          "lines",
                          "rentTotalTwd",
                          "depositTotalTwd"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "equipment.read"
      },
      "post": {
        "operationId": "post_equipment_rentals",
        "tags": [
          "equipment"
        ],
        "summary": "open a rental ticket",
        "description": "GET /api/v1/equipment/rentals — list rental tickets (with lines), the\n/admin/equipment rentals table over HTTP. Tenant-wide (no owner scope).\nFilterable by return/recon state, order, departure.\n\nPOST /api/v1/equipment/rentals — open a rental ticket. Mirrors back-office\n`createRentalAction`: equipment.manage gate + climbing-module gate + same core\n`createRental` + same shell-side writeAuditLog (equipment.rental.create).\nNOTE: opening a rental mutates the bound order's money model (rent + deposit\ncharge lines / schedule / intent). EquipmentStockError → 409, missing item /\norder → 404. See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rentalId": {
                          "type": "string",
                          "description": "新開立的租借單 id。"
                        }
                      },
                      "required": [
                        "rentalId"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "equipment.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "orderId": {
                    "type": "string",
                    "description": "租借單綁定的訂單 ID（租金與押金會掛入該訂單金流）（min 1）"
                  },
                  "departureId": {
                    "type": "string",
                    "description": "關聯的梯次 ID（選填）"
                  },
                  "renterName": {
                    "type": "string",
                    "description": "租借人姓名（選填）（max 100）"
                  },
                  "rentStartDate": {
                    "type": "string",
                    "description": "租借起始日，格式 YYYY-MM-DD（選填）（格式限定）"
                  },
                  "rentEndDate": {
                    "type": "string",
                    "description": "租借結束日，格式 YYYY-MM-DD（選填）（格式限定）"
                  },
                  "notes": {
                    "type": "string",
                    "description": "租借單備註（選填）（max 1000）"
                  },
                  "lines": {
                    "type": "array",
                    "items": {},
                    "description": "租借明細清單（至少一筆品項）（min 1）"
                  }
                },
                "required": [
                  "orderId",
                  "lines"
                ]
              }
            }
          }
        }
      }
    },
    "/equipment/rentals/{id}": {
      "get": {
        "operationId": "get_equipment_rentals_id_",
        "tags": [
          "equipment"
        ],
        "summary": "single rental ticket detail",
        "description": "GET /api/v1/equipment/rentals/{id} — single rental ticket detail (header +\nlines + derived rent total). Tenant-wide; missing → 404.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "租借單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "租借單 id（equipmentRental_ 前綴）。"
                        },
                        "orderId": {
                          "type": "string",
                          "description": "掛載的訂單 id。"
                        },
                        "orderNumber": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "訂單編號（JOIN；可空）。"
                        },
                        "departureId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "綁定的梯次 id（可不綁梯次時 null）。"
                        },
                        "departureLabel": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "梯次可讀標籤：團號 ‧ 行程名 ‧ 出發日（無綁梯次時 null）。"
                        },
                        "renterName": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "租借人姓名（可空）。"
                        },
                        "rentStartDate": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "租期起日（YYYY-MM-DD；可空）。"
                        },
                        "rentEndDate": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "租期迄日（YYYY-MM-DD；可空）。"
                        },
                        "returnedAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "歸還驗收時間（尚未歸還為 null）。"
                        },
                        "returnState": {
                          "description": "歸還狀態：rented 租借中／returned 已歸還／overdue 逾期。"
                        },
                        "inspectedAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "驗收時間（尚未驗收為 null）。"
                        },
                        "damageCostTwd": {
                          "type": [
                            "number",
                            "null"
                          ],
                          "description": "破損／遺失賠償金額（TWD；無為 null）。"
                        },
                        "reconState": {
                          "description": "對款狀態：pending 待對款／reconciled 已結清／deposit_pending 押金待退或待扣。"
                        },
                        "notes": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "備註（可空）。"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "建單時間。"
                        },
                        "updatedAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "最後更新時間。"
                        },
                        "lines": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "租借明細 id（equipmentRentalLine_ 前綴）。"
                              },
                              "equipmentItemId": {
                                "type": "string",
                                "description": "借出的裝備主檔品項 id。"
                              },
                              "itemName": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "主檔品名快照（JOIN，便利顯示；改主檔不回寫單）。"
                              },
                              "quantity": {
                                "type": "number",
                                "description": "借出數量。"
                              },
                              "rentPriceTwdSnapshot": {
                                "type": "number",
                                "description": "成交單位總價快照（每日單價 × 計價日數；TWD）。"
                              },
                              "depositTwdSnapshot": {
                                "type": "number",
                                "description": "成交每件押金快照（TWD，不乘天數）。"
                              },
                              "returnedQuantity": {
                                "type": [
                                  "number",
                                  "null"
                                ],
                                "description": "已歸還數量（尚未歸還為 null）。"
                              }
                            },
                            "required": [
                              "id",
                              "equipmentItemId",
                              "itemName",
                              "quantity",
                              "rentPriceTwdSnapshot",
                              "depositTwdSnapshot",
                              "returnedQuantity"
                            ]
                          },
                          "description": "租借明細（借出的品項清單）。"
                        },
                        "rentTotalTwd": {
                          "type": "number",
                          "description": "成交租金合計（Σ rent snapshot × qty）。"
                        },
                        "depositTotalTwd": {
                          "type": "number",
                          "description": "成交押金合計（Σ deposit snapshot × qty）。"
                        }
                      },
                      "required": [
                        "id",
                        "orderId",
                        "orderNumber",
                        "departureId",
                        "departureLabel",
                        "renterName",
                        "rentStartDate",
                        "rentEndDate",
                        "returnedAt",
                        "returnState",
                        "inspectedAt",
                        "damageCostTwd",
                        "reconState",
                        "notes",
                        "createdAt",
                        "updatedAt",
                        "lines",
                        "rentTotalTwd",
                        "depositTotalTwd"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "equipment.read"
      }
    },
    "/equipment/rentals/{id}/mark-overdue": {
      "post": {
        "operationId": "post_equipment_rentals_id_mark_overdue",
        "tags": [
          "equipment"
        ],
        "summary": "flag a single rented ticket",
        "description": "POST /api/v1/equipment/rentals/{id}/mark-overdue — flag a single rented ticket\nas overdue. Mirrors back-office `markRentalOverdueAction`: equipment.manage\ngate + climbing-module gate + same core `markRentalOverdue` + same shell-side\nwriteAuditLog (equipment.rental.mark_overdue). See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "要標記為逾期的租借單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "標記逾期成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "equipment.manage"
      }
    },
    "/equipment/rentals/{id}/return": {
      "post": {
        "operationId": "post_equipment_rentals_id_return",
        "tags": [
          "equipment"
        ],
        "summary": "receive a rental back",
        "description": "POST /api/v1/equipment/rentals/{id}/return — receive a rental back (full\nreturn + optional damage cost). Mirrors back-office `returnRentalAction`:\nequipment.manage gate + climbing-module gate + same core `returnRental` + same\nshell-side writeAuditLog (equipment.rental.return). Missing rental → 404;\nover-return (returnedQty > out) → 409. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "要驗收歸還的租借單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "驗收歸還成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "equipment.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "returnedLines": {
                    "type": "array",
                    "items": {},
                    "description": "各明細的歸還數量清單（min 1）"
                  },
                  "damageCostTwd": {
                    "type": "number",
                    "description": "損壞賠償金額（台幣，選填）（min 0）"
                  }
                },
                "required": [
                  "returnedLines"
                ]
              }
            }
          }
        }
      }
    },
    "/equipment/rentals/order-options": {
      "get": {
        "operationId": "get_equipment_rentals_order_options",
        "tags": [
          "equipment"
        ],
        "summary": "the minimal order picker",
        "description": "GET /api/v1/equipment/rentals/order-options — the minimal order picker\n(id/number/customer) backing the \"new rental\" dialog's order dropdown.\nMost-recent-first, capped. Tenant-wide.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "回傳訂單筆數上限（最多 200，預設取最近多筆）（max 200）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "orderId": {
                            "type": "string",
                            "description": "訂單 id。"
                          },
                          "orderNumber": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "訂單編號（可空）。"
                          },
                          "customerName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "訂購人姓名（可空）。"
                          }
                        },
                        "required": [
                          "orderId",
                          "orderNumber",
                          "customerName"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "equipment.read"
      }
    },
    "/exchange-rates": {
      "get": {
        "operationId": "get_exchange_rates",
        "tags": [
          "exchange-rates"
        ],
        "summary": "list the Bank-of-Taiwan published FX rate board",
        "description": "GET /api/v1/exchange-rates — list the Bank-of-Taiwan published FX rate board\n(bot auto-fetched + tenant manual overrides) over HTTP, mirroring the\n/admin/exchange-rates table. Tenant-wide (no owner scope). Optional filters:\nsingle currency, month-from / month-to ('YYYY-MM', inclusive). See\nspecs/tenant-cli.md.",
        "parameters": [
          {
            "name": "currency",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "幣別篩選（ISO 4217 三碼，如 JPY / USD）；省略則回傳所有幣別"
            }
          },
          {
            "name": "monthFrom",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "起始月份（YYYY-MM，含當月）；省略則不設下界（格式限定）"
            }
          },
          {
            "name": "monthTo",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "結束月份（YYYY-MM，含當月）；省略則不設上界（格式限定）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "匯率牌價列 ID。"
                          },
                          "rateDate": {
                            "type": "string",
                            "description": "掛牌日期（'YYYY-MM-DD'，Asia/Taipei）。"
                          },
                          "currency": {
                            "type": "string",
                            "description": "ISO 4217（'JPY' / 'IDR' / 'USD'…）。"
                          },
                          "cashBuy": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "各報價 canonical「1 外幣 = ? 台幣」（numeric → 字串原值保精度；NULL = 該幣別無此報價）。"
                          },
                          "cashSell": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "現金賣出匯率「1 外幣 = ? 台幣」（字串保精度；null = 無此報價）。"
                          },
                          "spotBuy": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "即期買入匯率「1 外幣 = ? 台幣」（字串保精度；null = 無此報價）。"
                          },
                          "spotSell": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "即期賣出匯率「1 外幣 = ? 台幣」（字串保精度；null = 無此報價）。"
                          },
                          "source": {
                            "description": "牌價來源：bot 台銀自動抓取 / manual 租戶手動覆蓋。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          }
                        },
                        "required": [
                          "id",
                          "rateDate",
                          "currency",
                          "cashBuy",
                          "cashSell",
                          "spotBuy",
                          "spotSell",
                          "source",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "account_transfer.read",
        "x-module": "accounting"
      }
    },
    "/exchange-rates/manual": {
      "put": {
        "operationId": "put_exchange_rates_manual",
        "tags": [
          "exchange-rates"
        ],
        "summary": "manual FX rate override",
        "description": "PUT /api/v1/exchange-rates/manual — manual FX rate override. Upserts one\n`source='manual'` row (unique per rate_date+currency+source; manual re-writes\noverwrite). Mirrors the back-office `upsertManualRateAction`: same\n`account_transfer.manage` gate + advanced-accounting module gate\n(fail-closed), same core fn `upsertExchangeRate(db, { …, source:'manual' })`.\nReceives JSON (not FormData). Validation errors / module gate are wrapped as\nActionError → 409 conflict, faithfully matching the action's catch. See\nspecs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否覆蓋寫入成功。"
                        },
                        "id": {
                          "type": "string",
                          "description": "寫入 / 更新的 manual 匯率牌價列 ID。"
                        }
                      },
                      "required": [
                        "ok",
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "account_transfer.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "rateDate": {
                    "type": "string",
                    "description": "匯率掛牌日期（YYYY-MM-DD），與幣別共同決定覆蓋哪一筆牌價（格式限定）"
                  },
                  "currency": {
                    "type": "string",
                    "description": "幣別（ISO 4217 三碼大寫，如 JPY / USD）（格式限定）"
                  },
                  "cashBuy": {
                    "type": "string",
                    "description": "現金買入匯率（正數最多 6 位小數，以字串表達）；四種報價至少填一個，留空傳 null（格式限定）"
                  },
                  "cashSell": {
                    "type": "string",
                    "description": "現金賣出匯率（正數最多 6 位小數，以字串表達）；四種報價至少填一個，留空傳 null（格式限定）"
                  },
                  "spotBuy": {
                    "type": "string",
                    "description": "即期買入匯率（正數最多 6 位小數，以字串表達）；四種報價至少填一個，留空傳 null（格式限定）"
                  },
                  "spotSell": {
                    "type": "string",
                    "description": "即期賣出匯率（正數最多 6 位小數，以字串表達）；四種報價至少填一個，留空傳 null（格式限定）"
                  }
                },
                "required": [
                  "rateDate",
                  "currency"
                ]
              }
            }
          }
        }
      }
    },
    "/exchange-rates/resolve": {
      "get": {
        "operationId": "get_exchange_rates_resolve",
        "tags": [
          "exchange-rates"
        ],
        "summary": "resolve the canonical \"1 foreign unit =",
        "description": "GET /api/v1/exchange-rates/resolve — resolve the canonical \"1 foreign unit =\n? TWD\" for a currency/date/quote, applying manual-over-bot precedence +\ncarry-forward (core resolveExchangeRate). Tenant-wide. Mirrors core's\nfail-safe contract: no rate found → 200 with `{ rate: null }` (not 404), so\ncallers branch on null rather than an HTTP error. `quote` is validated\nagainst the fixed台銀 4-quote union (defaults spot_sell). See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "currency",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "要換算的外幣幣別（ISO 4217 三碼，如 JPY / USD）（min 1）"
            }
          },
          {
            "name": "date",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "換算基準日期（YYYY-MM-DD），套用手動優先 + 往前承接的解析規則（格式限定）"
            }
          },
          {
            "name": "quote",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "cash_buy",
                "cash_sell",
                "spot_buy",
                "spot_sell"
              ],
              "description": "報價類型：cash_buy 現金買入、cash_sell 現金賣出、spot_buy 即期買入、spot_sell 即期賣出；省略預設 spot_sell"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "currency": {
                          "type": "string",
                          "description": "換算的外幣幣別（ISO 4217 三碼）。"
                        },
                        "date": {
                          "type": "string",
                          "description": "換算基準日期（YYYY-MM-DD）。"
                        },
                        "quote": {
                          "type": "string",
                          "enum": [
                            "cash_buy",
                            "cash_sell",
                            "spot_buy",
                            "spot_sell"
                          ],
                          "description": "使用的報價類型（cash_buy / cash_sell / spot_buy / spot_sell）。"
                        },
                        "rate": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "解析出的匯率「1 外幣 = ? 台幣」（字串保精度）；查無適用牌價為 null。"
                        }
                      },
                      "required": [
                        "currency",
                        "date",
                        "quote",
                        "rate"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "account_transfer.read"
      }
    },
    "/group-codes/airlines": {
      "get": {
        "operationId": "get_group_codes_airlines",
        "tags": [
          "group-codes"
        ],
        "summary": "航空碼對照表",
        "description": "GET /api/v1/group-codes/airlines — 航空碼對照表（含每碼 departures 引用數）。\n`?activeOnly=true` 只列啟用中的碼。Mirrors /admin/group-codes 的航空碼表。",
        "parameters": [
          {
            "name": "activeOnly",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false",
                "1",
                "0"
              ],
              "description": "傳 true 或 1 時只列出啟用中的航空碼"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "code": {
                            "type": "string",
                            "description": "航空公司代碼（團號組成，通常大寫縮寫，如 EG）。"
                          },
                          "name": {
                            "type": "string",
                            "description": "航空公司名稱。"
                          },
                          "isActive": {
                            "type": "boolean",
                            "description": "是否啟用（停用後不可再指派給新梯次）。"
                          },
                          "displayOrder": {
                            "type": "number",
                            "description": "顯示排序（由小到大）。"
                          },
                          "usedCount": {
                            "type": "number",
                            "description": "被多少梯次引用。"
                          }
                        },
                        "required": [
                          "code",
                          "name",
                          "isActive",
                          "displayOrder",
                          "usedCount"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "group_code.manage"
      },
      "post": {
        "operationId": "post_group_codes_airlines",
        "tags": [
          "group-codes"
        ],
        "description": "GET /api/v1/group-codes/airlines — 航空碼對照表（含每碼 departures 引用數）。\n`?activeOnly=true` 只列啟用中的碼。Mirrors /admin/group-codes 的航空碼表。",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        },
                        "code": {
                          "type": "string",
                          "description": "新增或更新的航空公司代碼。"
                        }
                      },
                      "required": [
                        "ok",
                        "code"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "group_code.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "對照表碼，2–3 碼大寫英數（自動轉大寫）"
                  },
                  "name": {
                    "type": "string",
                    "description": "碼的顯示名稱（如地區或航空公司全名）（max 100 · min 1）"
                  },
                  "isActive": {
                    "type": "boolean",
                    "description": "是否啟用（停用後不再供新團號選用）"
                  },
                  "displayOrder": {
                    "type": "number",
                    "description": "排序權重，數字越小越前面（max 9999 · min 0）"
                  }
                },
                "required": [
                  "code",
                  "name"
                ]
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patch_group_codes_airlines",
        "tags": [
          "group-codes"
        ],
        "description": "GET /api/v1/group-codes/airlines — 航空碼對照表（含每碼 departures 引用數）。\n`?activeOnly=true` 只列啟用中的碼。Mirrors /admin/group-codes 的航空碼表。",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        },
                        "code": {
                          "type": "string",
                          "description": "新增或更新的航空公司代碼。"
                        }
                      },
                      "required": [
                        "ok",
                        "code"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "group_code.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "要更新的對照表碼（不可變更碼本身）"
                  },
                  "name": {
                    "type": "string",
                    "description": "碼的顯示名稱（如地區或航空公司全名）（max 100 · min 1）"
                  },
                  "isActive": {
                    "type": "boolean",
                    "description": "是否啟用（停用後不再供新團號選用）"
                  },
                  "displayOrder": {
                    "type": "number",
                    "description": "排序權重，數字越小越前面（max 9999 · min 0）"
                  }
                },
                "required": [
                  "code",
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/group-codes/departures": {
      "get": {
        "operationId": "get_group_codes_departures",
        "tags": [
          "group-codes"
        ],
        "summary": "前綴團號反查多梯次",
        "description": "GET /api/v1/group-codes/departures?prefix=<prefix> — 前綴團號反查多梯次\n（例 '26EGTK' 列該地區該航空所有團，上限 100）。Mirrors\nsearchDeparturesByGroupCodePrefix。",
        "parameters": [
          {
            "name": "prefix",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "團號前綴，反查同地區同航空的所有梯次（如 26EGTK）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "梯次 id（dep_ 前綴）。"
                          },
                          "tripId": {
                            "type": "string",
                            "description": "所屬行程 id（trip_ 前綴）。"
                          },
                          "tripTitle": {
                            "type": "string",
                            "description": "所屬行程標題。"
                          },
                          "tripSlug": {
                            "type": "string",
                            "description": "所屬行程網址 slug。"
                          },
                          "departureDate": {
                            "type": "string",
                            "description": "出發日（ISO 'YYYY-MM-DD'）。"
                          },
                          "groupCode": {
                            "type": "string",
                            "description": "完整團號。"
                          },
                          "regionCode": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "地區代碼；null = 未設。"
                          },
                          "airlineCode": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "航空公司代碼；null = 國內團或未設。"
                          }
                        },
                        "required": [
                          "id",
                          "tripId",
                          "tripTitle",
                          "tripSlug",
                          "departureDate",
                          "groupCode",
                          "regionCode",
                          "airlineCode"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "group_code.manage"
      }
    },
    "/group-codes/departures/{id}": {
      "get": {
        "operationId": "get_group_codes_departures_id_",
        "tags": [
          "group-codes"
        ],
        "summary": "精確團號反查單一梯次",
        "description": "GET /api/v1/group-codes/departures/{id} — 精確團號反查單一梯次（走唯一索引，\n大小寫不敏感）。`id` = 完整團號（group code）。查無 → 404。Mirrors\nfindDepartureByGroupCode。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "完整團號，反查單一梯次（大小寫不敏感）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "梯次 id（dep_ 前綴）。"
                        },
                        "tripId": {
                          "type": "string",
                          "description": "所屬行程 id（trip_ 前綴）。"
                        },
                        "tripTitle": {
                          "type": "string",
                          "description": "所屬行程標題。"
                        },
                        "tripSlug": {
                          "type": "string",
                          "description": "所屬行程網址 slug。"
                        },
                        "departureDate": {
                          "type": "string",
                          "description": "出發日（ISO 'YYYY-MM-DD'）。"
                        },
                        "groupCode": {
                          "type": "string",
                          "description": "完整團號。"
                        },
                        "regionCode": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "地區代碼；null = 未設。"
                        },
                        "airlineCode": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "航空公司代碼；null = 國內團或未設。"
                        }
                      },
                      "required": [
                        "id",
                        "tripId",
                        "tripTitle",
                        "tripSlug",
                        "departureDate",
                        "groupCode",
                        "regionCode",
                        "airlineCode"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "group_code.manage"
      }
    },
    "/group-codes/regions": {
      "get": {
        "operationId": "get_group_codes_regions",
        "tags": [
          "group-codes"
        ],
        "summary": "地區碼對照表",
        "description": "GET /api/v1/group-codes/regions — 地區碼對照表（含每碼 departures 引用數）。\n`?activeOnly=true` 只列啟用中的碼。Mirrors /admin/group-codes 的地區碼表。",
        "parameters": [
          {
            "name": "activeOnly",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false",
                "1",
                "0"
              ],
              "description": "傳 true 或 1 時只列出啟用中的地區碼"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "code": {
                            "type": "string",
                            "description": "地區代碼（團號組成，通常大寫縮寫，如 YS）。"
                          },
                          "name": {
                            "type": "string",
                            "description": "地區名稱（如「玉山」）。"
                          },
                          "isActive": {
                            "type": "boolean",
                            "description": "是否啟用（停用後不可再指派給新梯次）。"
                          },
                          "displayOrder": {
                            "type": "number",
                            "description": "顯示排序（由小到大）。"
                          },
                          "usedCount": {
                            "type": "number",
                            "description": "被多少梯次引用 —— UI 鎖頭 / 「使用中 N」。"
                          }
                        },
                        "required": [
                          "code",
                          "name",
                          "isActive",
                          "displayOrder",
                          "usedCount"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "group_code.manage"
      },
      "post": {
        "operationId": "post_group_codes_regions",
        "tags": [
          "group-codes"
        ],
        "description": "GET /api/v1/group-codes/regions — 地區碼對照表（含每碼 departures 引用數）。\n`?activeOnly=true` 只列啟用中的碼。Mirrors /admin/group-codes 的地區碼表。",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        },
                        "code": {
                          "type": "string",
                          "description": "新增或更新的地區代碼。"
                        }
                      },
                      "required": [
                        "ok",
                        "code"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "group_code.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "對照表碼，2–3 碼大寫英數（自動轉大寫）"
                  },
                  "name": {
                    "type": "string",
                    "description": "碼的顯示名稱（如地區或航空公司全名）（max 100 · min 1）"
                  },
                  "isActive": {
                    "type": "boolean",
                    "description": "是否啟用（停用後不再供新團號選用）"
                  },
                  "displayOrder": {
                    "type": "number",
                    "description": "排序權重，數字越小越前面（max 9999 · min 0）"
                  }
                },
                "required": [
                  "code",
                  "name"
                ]
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patch_group_codes_regions",
        "tags": [
          "group-codes"
        ],
        "description": "GET /api/v1/group-codes/regions — 地區碼對照表（含每碼 departures 引用數）。\n`?activeOnly=true` 只列啟用中的碼。Mirrors /admin/group-codes 的地區碼表。",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        },
                        "code": {
                          "type": "string",
                          "description": "新增或更新的地區代碼。"
                        }
                      },
                      "required": [
                        "ok",
                        "code"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "group_code.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "要更新的對照表碼（不可變更碼本身）"
                  },
                  "name": {
                    "type": "string",
                    "description": "碼的顯示名稱（如地區或航空公司全名）（max 100 · min 1）"
                  },
                  "isActive": {
                    "type": "boolean",
                    "description": "是否啟用（停用後不再供新團號選用）"
                  },
                  "displayOrder": {
                    "type": "number",
                    "description": "排序權重，數字越小越前面（max 9999 · min 0）"
                  }
                },
                "required": [
                  "code",
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/guide-roster/assignments": {
      "post": {
        "operationId": "post_guide_roster_assignments",
        "tags": [
          "guide-roster"
        ],
        "summary": "指派 / 重派 guide 到梯次",
        "description": "POST /api/v1/guide-roster/assignments — 指派 / 重派 guide 到梯次（upsert）。\nMirrors the back-office `assignGuideAction`: same `guide_roster.manage` gate,\nsame `assignGuide` core op, same conflict fail-close, same audit log. See\nspecs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立（或重派後）的指派紀錄 id。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "guide_roster.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "departureId": {
                    "type": "string",
                    "description": "指派的目標梯次 ID（max 64 · min 1）"
                  },
                  "guideId": {
                    "type": "string",
                    "description": "被指派的領隊／嚮導 ID（max 64 · min 1）"
                  },
                  "role": {
                    "type": "string",
                    "description": "指派角色（leader 領隊／assistant 隨隊助理）"
                  },
                  "status": {
                    "type": "string",
                    "description": "指派狀態（tentative 預塞暫定／confirmed 正式確認）"
                  }
                },
                "required": [
                  "departureId",
                  "guideId",
                  "role",
                  "status"
                ]
              }
            }
          }
        }
      }
    },
    "/guide-roster/assignments/{id}": {
      "delete": {
        "operationId": "delete_guide_roster_assignments_id_",
        "tags": [
          "guide-roster"
        ],
        "summary": "移除某筆指派",
        "description": "DELETE /api/v1/guide-roster/assignments/{id} — 移除某筆指派。Mirrors the\nback-office `removeAssignmentAction`: same `guide_roster.manage` gate, same\n`removeAssignment` core op, same NOT_FOUND → 404, same audit log. See\nspecs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "要移除的指派紀錄 ID（max 64 · min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "移除成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "guide_roster.manage"
      }
    },
    "/guide-roster/assignments/{id}/confirm": {
      "post": {
        "operationId": "post_guide_roster_assignments_id_confirm",
        "tags": [
          "guide-roster"
        ],
        "summary": "正式確認某筆指派",
        "description": "POST /api/v1/guide-roster/assignments/{id}/confirm — 正式確認某筆指派\n（tentative→confirmed）。Mirrors the back-office `confirmAssignmentAction`:\nsame `guide_roster.manage` gate, same `confirmAssignment` core op, same\nNOT_FOUND → 404 / CONFLICT → 409, same audit log. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "要正式確認的指派紀錄 ID（max 64 · min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "確認成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "guide_roster.manage"
      }
    },
    "/guide-roster/change-leader": {
      "post": {
        "operationId": "post_guide_roster_change_leader",
        "tags": [
          "guide-roster"
        ],
        "summary": "換領隊",
        "description": "POST /api/v1/guide-roster/change-leader — 換領隊（移除舊領隊 leader 指派 →\n升任新領隊為 confirmed leader，一個 tx 內）。Mirrors the back-office\n`changeLeaderAction`: same `guide_roster.manage` gate, same `changeLeader`\ncore op + args, same conflict fail-close, same audit log. See\nspecs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新任領隊的指派紀錄 id。"
                        },
                        "removedGuideIds": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "被移除的舊領隊嚮導 id 清單（DB 權威）。"
                        }
                      },
                      "required": [
                        "id",
                        "removedGuideIds"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "guide_roster.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "departureId": {
                    "type": "string",
                    "description": "要換領隊的目標梯次 ID（max 64 · min 1）"
                  },
                  "fromGuideId": {
                    "type": "string",
                    "description": "原領隊嚮導 ID（選填；省略表示該梯次原本無領隊）（max 64 · min 1）"
                  },
                  "toGuideId": {
                    "type": "string",
                    "description": "新任領隊嚮導 ID（max 64 · min 1）"
                  },
                  "reason": {
                    "type": "string",
                    "description": "換領隊的原因（必填，記入稽核）（max 500 · min 1）"
                  }
                },
                "required": [
                  "departureId",
                  "toGuideId",
                  "reason"
                ]
              }
            }
          }
        }
      }
    },
    "/guide-roster/conflict-check": {
      "get": {
        "operationId": "get_guide_roster_conflict_check",
        "tags": [
          "guide-roster"
        ],
        "summary": "pre-check whether assigning a guide",
        "description": "GET /api/v1/guide-roster/conflict-check — pre-check whether assigning a guide\nto a departure would collide with an existing confirmed assignment on an\noverlapping date range (the same condition `confirm` enforces). Returns the\nconflicting departure, or null when clear. Tenant-wide (no owner scope).",
        "parameters": [
          {
            "name": "departureId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "欲指派的目標梯次 ID（min 1）"
            }
          },
          {
            "name": "guideId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "欲檢查檔期衝突的領隊／嚮導 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "anyOf": [
                        {},
                        {
                          "type": "null"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "guide_roster.read"
      }
    },
    "/guide-roster/conflicts": {
      "get": {
        "operationId": "get_guide_roster_conflicts",
        "tags": [
          "guide-roster"
        ],
        "summary": "schedule conflicts for the selected",
        "description": "GET /api/v1/guide-roster/conflicts — schedule conflicts for the selected\nmonth: same guide with confirmed assignments on date-overlapping departures.\nMirrors the /admin/guide-roster conflict alert. Tenant-wide (no owner scope).\n`month=YYYY-MM` required.",
        "parameters": [
          {
            "name": "month",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "查詢月份（YYYY-MM 格式）（格式限定）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "guideId": {
                            "type": "string",
                            "description": "發生衝突的嚮導 id。"
                          },
                          "guideName": {
                            "type": "string",
                            "description": "發生衝突的嚮導姓名。"
                          },
                          "a": {
                            "type": "object",
                            "properties": {
                              "departureId": {
                                "type": "string",
                                "description": "梯次 id。"
                              },
                              "tripTitle": {
                                "type": "string",
                                "description": "行程名稱。"
                              },
                              "departureDate": {
                                "type": "string",
                                "description": "出發日（YYYY-MM-DD）。"
                              },
                              "returnDate": {
                                "type": "string",
                                "description": "回程日（YYYY-MM-DD）。"
                              }
                            },
                            "required": [
                              "departureId",
                              "tripTitle",
                              "departureDate",
                              "returnDate"
                            ],
                            "description": "衝突梯次之一（含梯次 id／行程名／起訖日）。"
                          },
                          "b": {
                            "type": "object",
                            "properties": {
                              "departureId": {
                                "type": "string",
                                "description": "梯次 id。"
                              },
                              "tripTitle": {
                                "type": "string",
                                "description": "行程名稱。"
                              },
                              "departureDate": {
                                "type": "string",
                                "description": "出發日（YYYY-MM-DD）。"
                              },
                              "returnDate": {
                                "type": "string",
                                "description": "回程日（YYYY-MM-DD）。"
                              }
                            },
                            "required": [
                              "departureId",
                              "tripTitle",
                              "departureDate",
                              "returnDate"
                            ],
                            "description": "與 a 日期重疊的另一梯次（含梯次 id／行程名／起訖日）。"
                          }
                        },
                        "required": [
                          "guideId",
                          "guideName",
                          "a",
                          "b"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "guide_roster.read"
      }
    },
    "/guide-roster/departures": {
      "get": {
        "operationId": "get_guide_roster_departures",
        "tags": [
          "guide-roster"
        ],
        "summary": "the selected month's departures",
        "description": "GET /api/v1/guide-roster/departures — the selected month's departures (JOIN\ntrips for title) with their attached guide assignments (leader-first),\nmirroring the /admin/guide-roster matrix. Tenant-wide (no owner scope).\n`month=YYYY-MM` required; `includeCancelled` includes cancelled departures.",
        "parameters": [
          {
            "name": "month",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "查詢月份（YYYY-MM 格式）（格式限定）"
            }
          },
          {
            "name": "includeCancelled",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "是否一併納入已取消的梯次（預設不納入）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "梯次 id。"
                          },
                          "tripId": {
                            "type": "string",
                            "description": "所屬行程 id。"
                          },
                          "tripTitle": {
                            "type": "string",
                            "description": "行程名稱。"
                          },
                          "departureDate": {
                            "type": "string",
                            "description": "出發日（YYYY-MM-DD）。"
                          },
                          "returnDate": {
                            "type": "string",
                            "description": "回程日（YYYY-MM-DD）。"
                          },
                          "days": {
                            "type": "number",
                            "description": "帶團天數（含頭尾）。"
                          },
                          "capacity": {
                            "type": "number",
                            "description": "團位容量（總名額）。"
                          },
                          "bookedCount": {
                            "type": "number",
                            "description": "已成團報名人數。"
                          },
                          "status": {
                            "type": "string",
                            "description": "梯次狀態（如 open 開放／full 已滿／cancelled 已取消）。"
                          },
                          "assignments": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "description": "指派紀錄 id。"
                                },
                                "guideId": {
                                  "type": "string",
                                  "description": "被指派的嚮導 id。"
                                },
                                "guideName": {
                                  "type": "string",
                                  "description": "被指派的嚮導姓名。"
                                },
                                "role": {
                                  "type": "string",
                                  "enum": [
                                    "leader",
                                    "assistant"
                                  ],
                                  "description": "指派角色：leader 領隊／assistant 隨隊助理。"
                                },
                                "status": {
                                  "type": "string",
                                  "enum": [
                                    "tentative",
                                    "confirmed"
                                  ],
                                  "description": "指派狀態：tentative 預塞暫定／confirmed 正式確認。"
                                }
                              },
                              "required": [
                                "id",
                                "guideId",
                                "guideName",
                                "role",
                                "status"
                              ]
                            },
                            "description": "該梯次所有指派（領隊在前）。"
                          }
                        },
                        "required": [
                          "id",
                          "tripId",
                          "tripTitle",
                          "departureDate",
                          "returnDate",
                          "days",
                          "capacity",
                          "bookedCount",
                          "status",
                          "assignments"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "guide_roster.read"
      }
    },
    "/guide-roster/guides": {
      "get": {
        "operationId": "get_guide_roster_guides",
        "tags": [
          "guide-roster"
        ],
        "summary": "roster",
        "description": "GET /api/v1/guide-roster/guides — roster (領隊/嚮導 名冊) with the selected\nmonth's confirmed load (帶團天數/梯次數) + availability, mirroring the\n/admin/guide-roster guide list. Tenant-wide (no owner scope). `month=YYYY-MM`\nrequired; `includeInactive` lists suspended guides too.",
        "parameters": [
          {
            "name": "month",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "查詢月份（YYYY-MM 格式）（格式限定）"
            }
          },
          {
            "name": "includeInactive",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "是否一併列出已停用的嚮導（預設不列出）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "嚮導 id。"
                          },
                          "name": {
                            "type": "string",
                            "description": "嚮導姓名。"
                          },
                          "rosterRole": {
                            "type": "string",
                            "enum": [
                              "leader",
                              "assistant",
                              "both"
                            ],
                            "description": "名冊職能：leader 領隊／assistant 隨隊助理／both 皆可。"
                          },
                          "specialties": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "可帶路線 / 專長；未設為空陣列。"
                          },
                          "status": {
                            "type": "string",
                            "description": "嚮導狀態：active 啟用／inactive 停用。"
                          },
                          "maxDaysPerMonth": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "單月可帶上限（天）；NULL = 不限。"
                          },
                          "monthDays": {
                            "type": "number",
                            "description": "本月 confirmed 指派的帶團天數彙總。"
                          },
                          "monthTrips": {
                            "type": "number",
                            "description": "本月 confirmed 帶團梯次數。"
                          },
                          "hasTentative": {
                            "type": "boolean",
                            "description": "本月是否含 tentative（預塞）指派。"
                          },
                          "availability": {
                            "description": "派生載量狀態。"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "rosterRole",
                          "specialties",
                          "status",
                          "maxDaysPerMonth",
                          "monthDays",
                          "monthTrips",
                          "hasTentative",
                          "availability"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "guide_roster.read"
      }
    },
    "/guides": {
      "get": {
        "operationId": "get_guides",
        "tags": [
          "guides"
        ],
        "summary": "list/search guides",
        "description": "GET /api/v1/guides — list/search guides (the /admin/guides table over HTTP),\nor look up a single guide by slug when `?slug=` is given. Tenant-wide (no\nowner scope). Gated on guide.read, identical to the back office.\n\nPOST /api/v1/guides — create a guide (建檔). Same core op + audit as the back\noffice `createGuideAction`; gated on guide.manage. JSON body (not FormData):\n`specialties` is a comma-separated string (mirroring the form) parsed into an\narray; empty strings collapse to undefined → core treats as null/unset. See\nspecs/tenant-cli.md.",
        "parameters": [
          {
            "name": "slug",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依嚮導公開頁網址代稱（slug）精確查單筆（選填）（min 1）"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "active",
                "inactive"
              ],
              "description": "嚮導狀態篩選（all 全部／active 啟用／inactive 停用）"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "關鍵字搜尋（比對嚮導姓名等欄位）"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "頁碼（從 1 起算）"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "每頁筆數（上限 200）（max 200）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {}
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "guide.read"
      },
      "post": {
        "operationId": "post_guides",
        "tags": [
          "guides"
        ],
        "summary": "create a guide",
        "description": "GET /api/v1/guides — list/search guides (the /admin/guides table over HTTP),\nor look up a single guide by slug when `?slug=` is given. Tenant-wide (no\nowner scope). Gated on guide.read, identical to the back office.\n\nPOST /api/v1/guides — create a guide (建檔). Same core op + audit as the back\noffice `createGuideAction`; gated on guide.manage. JSON body (not FormData):\n`specialties` is a comma-separated string (mirroring the form) parsed into an\narray; empty strings collapse to undefined → core treats as null/unset. See\nspecs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立的嚮導 id。"
                        },
                        "slug": {
                          "type": "string",
                          "description": "嚮導公開頁網址代稱（未帶則系統自動產生）。"
                        }
                      },
                      "required": [
                        "id",
                        "slug"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "guide.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "嚮導／領隊姓名（max 100 · min 1）"
                  },
                  "slug": {
                    "type": "string",
                    "description": "公開頁網址代稱（選填，小寫英數與連字號；省略則自動產生）（格式限定）"
                  },
                  "bio": {
                    "type": "string",
                    "description": "嚮導簡介／經歷（選填）（max 20000）"
                  },
                  "avatarUrl": {
                    "type": "string",
                    "description": "大頭照圖片網址（選填，http/https）（max 500）"
                  },
                  "specialties": {
                    "type": "string",
                    "description": "專長領域（選填，以逗號分隔多項）"
                  },
                  "yearsExperience": {
                    "type": "number",
                    "description": "帶團年資（年數，0～80；選填）（max 80 · min 0）"
                  },
                  "contactPhone": {
                    "type": "string",
                    "description": "聯絡電話（選填）（max 40）"
                  },
                  "contactEmail": {
                    "type": "string",
                    "format": "email",
                    "description": "聯絡 Email（選填）（max 120）"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "inactive"
                    ],
                    "description": "嚮導狀態（active 啟用／inactive 停用；預設 active）"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/guides/{id}": {
      "get": {
        "operationId": "get_guides_id_",
        "tags": [
          "guides"
        ],
        "summary": "single guide detail",
        "description": "GET /api/v1/guides/{id} — single guide detail. Tenant-wide (no owner scope);\nmissing → 404. Gated on guide.read, identical to the back office.\n\nPATCH /api/v1/guides/{id} — update a guide (建檔編輯). Same core op + audit as\nthe back office `updateGuideAction`; gated on guide.manage. JSON body, all\nfields optional (partial): omitted fields are left unchanged; explicit `null`\nclears (mirroring the form's empty-string→undefined→core \"leave\"/null shape).\n`specialties` is a comma-separated string parsed into an array.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "嚮導 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "嚮導 id（guide_ 前綴）。"
                        },
                        "name": {
                          "type": "string",
                          "description": "嚮導／領隊姓名。"
                        },
                        "slug": {
                          "type": "string",
                          "description": "公開頁網址代稱（slug；小寫英數與連字號）。"
                        },
                        "bio": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "簡介／經歷（可空）。"
                        },
                        "avatarUrl": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "大頭照圖片網址（可空）。"
                        },
                        "specialties": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "專長領域清單。"
                        },
                        "yearsExperience": {
                          "type": [
                            "number",
                            "null"
                          ],
                          "description": "帶團年資（年數；可空）。"
                        },
                        "contactPhone": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "聯絡電話（可空）。"
                        },
                        "contactEmail": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "聯絡 Email（可空）。"
                        },
                        "status": {
                          "description": "嚮導狀態：active 啟用／inactive 停用。"
                        },
                        "engagementType": {
                          "type": "string",
                          "enum": [
                            "external",
                            "full_time",
                            "partner"
                          ],
                          "description": "僱用型態：full_time 正式／partner 協作／external 外聘。"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "建檔時間。"
                        },
                        "updatedAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "最後更新時間。"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "slug",
                        "bio",
                        "avatarUrl",
                        "specialties",
                        "yearsExperience",
                        "contactPhone",
                        "contactEmail",
                        "status",
                        "engagementType",
                        "createdAt",
                        "updatedAt"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "guide.read"
      },
      "patch": {
        "operationId": "patch_guides_id_",
        "tags": [
          "guides"
        ],
        "summary": "update a guide",
        "description": "GET /api/v1/guides/{id} — single guide detail. Tenant-wide (no owner scope);\nmissing → 404. Gated on guide.read, identical to the back office.\n\nPATCH /api/v1/guides/{id} — update a guide (建檔編輯). Same core op + audit as\nthe back office `updateGuideAction`; gated on guide.manage. JSON body, all\nfields optional (partial): omitted fields are left unchanged; explicit `null`\nclears (mirroring the form's empty-string→undefined→core \"leave\"/null shape).\n`specialties` is a comma-separated string parsed into an array.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "要更新的嚮導 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "更新成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "guide.manage",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "嚮導／領隊姓名（省略則不更動）（max 100 · min 1）"
                  },
                  "slug": {
                    "type": "string",
                    "description": "公開頁網址代稱（小寫英數與連字號；省略則不更動）（格式限定）"
                  },
                  "bio": {
                    "type": "string",
                    "description": "嚮導簡介／經歷（省略則不更動）（max 20000）"
                  },
                  "avatarUrl": {
                    "type": "string",
                    "description": "大頭照圖片網址（http/https；省略則不更動）（max 500）"
                  },
                  "specialties": {
                    "type": "string",
                    "description": "專長領域（以逗號分隔多項；省略則不更動）"
                  },
                  "yearsExperience": {
                    "type": "number",
                    "description": "帶團年資（年數，0～80；省略則不更動）（max 80 · min 0）"
                  },
                  "contactPhone": {
                    "type": "string",
                    "description": "聯絡電話（省略則不更動）（max 40）"
                  },
                  "contactEmail": {
                    "type": "string",
                    "format": "email",
                    "description": "聯絡 Email（省略則不更動）（max 120）"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "inactive"
                    ],
                    "description": "嚮導狀態（active 啟用／inactive 停用；省略則不更動）"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/guides/{id}/archive": {
      "post": {
        "operationId": "post_guides_id_archive",
        "tags": [
          "guides"
        ],
        "summary": "archive a guide",
        "description": "POST /api/v1/guides/{id}/archive — archive a guide (status→inactive). Same\ncore op + audit as the back office `archiveGuideAction`; gated on\nguide.manage. Idempotent (re-archiving an inactive guide is a no-op).\nReactivation is via `PATCH /api/v1/guides/{id}` with `status: active`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "要封存（狀態改為停用）的嚮導 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "封存成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "guide.manage"
      }
    },
    "/guides/{id}/invite-account": {
      "post": {
        "operationId": "post_guides_id_invite_account",
        "tags": [
          "guides"
        ],
        "summary": "開通某既有 guide 的嚮導 portal 登入帳號",
        "description": "POST /api/v1/guides/{id}/invite-account — 開通某既有 guide 的嚮導 portal 登入帳號。\n鏡像後台 `inviteGuideAccountAction`：同核心 op `inviteGuideAccount`（建帳號）+ 一次性\n暫時密碼 + best-effort guide.invite 稽核。gated guide.manage。\n\n⚠ 回應內含一次性明文暫時密碼 `tempPassword`（與後台對話框同等信任：HTTPS + bearer）；\n僅此一次回傳，CLI 顯示後請立即轉交並要求嚮導首次登入改密。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "要開通登入帳號的嚮導 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "tempPassword": {
                          "type": "string",
                          "description": "一次性明文暫時密碼（僅此次回傳，請立即轉交嚮導並要求首次登入改密）。"
                        },
                        "email": {
                          "type": "string",
                          "description": "已開通登入帳號的 Email。"
                        }
                      },
                      "required": [
                        "tempPassword",
                        "email"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "guide.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "嚮導 portal 登入帳號的 Email（max 120）"
                  },
                  "name": {
                    "type": "string",
                    "description": "嚮導帳號的顯示姓名（max 100 · min 1）"
                  }
                },
                "required": [
                  "email",
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/holidays": {
      "get": {
        "operationId": "get_holidays",
        "tags": [
          "holidays"
        ],
        "summary": "per-tenant national-holiday / makeup-workday table",
        "description": "GET /api/v1/holidays — per-tenant national-holiday / makeup-workday table\n(the /admin/holidays list over HTTP). Year-filtered (optional). Tenant-wide,\nno owner scope. Replicates the page's climbing-module fail-closed gate: the\nholiday table only feeds climbing-tour deadline business-day countdown, so a\ntenant without the climbing module gets 403 (identical to the back office\nhiding the page). See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "year",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "篩選的西元年份（1000..9999）；省略則回傳所有年份（max 9999 · min 1000）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "date": {
                                "type": "string",
                                "description": "日期（ISO 'YYYY-MM-DD'）。"
                              },
                              "name": {
                                "type": "string",
                                "description": "名稱（如「國慶日」「補班」）。"
                              },
                              "isWorkday": {
                                "type": "boolean",
                                "description": "是否為補班日（true = 該日照常上班，false = 放假）。"
                              }
                            },
                            "required": [
                              "date",
                              "name",
                              "isWorkday"
                            ]
                          },
                          "description": "假日列（依日期排序）。"
                        }
                      },
                      "required": [
                        "rows"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "public_holiday.read"
      }
    },
    "/holidays/{date}": {
      "put": {
        "operationId": "put_holidays_date_",
        "tags": [
          "holidays"
        ],
        "summary": "upsert / delete a single per-tenant",
        "description": "PUT / DELETE /api/v1/holidays/{date} — upsert / delete a single per-tenant\nnational-holiday or makeup-workday row (date is the natural key). Same core\nops + climbing-module fail-closed gate + audit as the back-office\n`upsertPublicHolidayAction` / `deletePublicHolidayAction`; gated\n`public_holiday.manage`. The holiday table only feeds climbing-tour deadline\nbusiness-day countdown, so a tenant without the climbing module gets 403\n(identical to the back office hiding the page). See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "date",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "假日 / 補班日的日期（YYYY-MM-DD，路徑參數），作為該筆紀錄的自然鍵（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "public_holiday.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "假日 / 補班日名稱（如「春節」「補行上班」）（max 100 · min 1）"
                  },
                  "isWorkday": {
                    "type": "boolean",
                    "description": "是否為補班日：true 表示原假日改上班、false 表示國定假日；影響行前作業工作日倒數"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_holidays_date_",
        "tags": [
          "holidays"
        ],
        "description": "PUT / DELETE /api/v1/holidays/{date} — upsert / delete a single per-tenant\nnational-holiday or makeup-workday row (date is the natural key). Same core\nops + climbing-module fail-closed gate + audit as the back-office\n`upsertPublicHolidayAction` / `deletePublicHolidayAction`; gated\n`public_holiday.manage`. The holiday table only feeds climbing-tour deadline\nbusiness-day countdown, so a tenant without the climbing module gets 403\n(identical to the back office hiding the page). See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "date",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "要刪除的假日 / 補班日日期（YYYY-MM-DD，路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "public_holiday.manage"
      }
    },
    "/holidays/stats": {
      "get": {
        "operationId": "get_holidays_stats",
        "tags": [
          "holidays"
        ],
        "summary": "holiday / makeup-workday counts for a",
        "description": "GET /api/v1/holidays/stats?year=YYYY — holiday / makeup-workday counts for a\nyear (the /admin/holidays StatCards over HTTP). `year` is required (the core\nfn takes a concrete year). Tenant-wide; replicates the page's climbing-module\nfail-closed gate. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "year",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number",
              "description": "要統計的西元年份（1000..9999，必填）（max 9999 · min 1000）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "holidayCount": {
                          "type": "number",
                          "description": "該年度放假日數。"
                        },
                        "makeupCount": {
                          "type": "number",
                          "description": "該年度補班日數。"
                        }
                      },
                      "required": [
                        "holidayCount",
                        "makeupCount"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "public_holiday.read"
      }
    },
    "/images": {
      "get": {
        "operationId": "get_images",
        "tags": [
          "images"
        ],
        "summary": "list/search the trip image gallery",
        "description": "GET /api/v1/images — list/search the trip image gallery (the /admin/images\ngrid over HTTP). Tenant-wide (no owner scope); filter by trip or free-text\nover trip title/slug + caption/url. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "tripId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "行程 ID 篩選，僅回傳掛在該行程的圖片"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "關鍵字，模糊比對行程標題、slug、圖說或網址"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "分頁頁碼，從 1 起算，預設第 1 頁"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "每頁筆數，上限 200，預設由後端決定（max 200）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "圖片資源 id（timg_ 前綴）。"
                              },
                              "tripId": {
                                "type": "string",
                                "description": "所屬行程 id（trip_ 前綴）。"
                              },
                              "tripTitle": {
                                "type": "string",
                                "description": "所屬行程標題。"
                              },
                              "tripSlug": {
                                "type": "string",
                                "description": "所屬行程網址 slug。"
                              },
                              "url": {
                                "type": "string",
                                "description": "圖片公開 URL。"
                              },
                              "caption": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "圖說文字；null = 無。"
                              },
                              "displayOrder": {
                                "type": "number",
                                "description": "在行程相簿中的排序（由小到大）。"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "上傳建立時間。"
                              }
                            },
                            "required": [
                              "id",
                              "tripId",
                              "tripTitle",
                              "tripSlug",
                              "url",
                              "caption",
                              "displayOrder",
                              "createdAt"
                            ]
                          },
                          "description": "當頁圖片列。"
                        },
                        "total": {
                          "type": "number",
                          "description": "符合條件的總筆數（跨頁）。"
                        },
                        "page": {
                          "type": "number",
                          "description": "目前頁碼（1 起算）。"
                        },
                        "pageSize": {
                          "type": "number",
                          "description": "每頁筆數。"
                        }
                      },
                      "required": [
                        "rows",
                        "total",
                        "page",
                        "pageSize"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "image.read"
      },
      "post": {
        "operationId": "post_images",
        "tags": [
          "images"
        ],
        "description": "GET /api/v1/images — list/search the trip image gallery (the /admin/images\ngrid over HTTP). Tenant-wide (no owner scope); filter by trip or free-text\nover trip title/slug + caption/url. See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立圖片的 id（timg_ 前綴）。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "image.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tripId": {
                    "type": "string",
                    "description": "要掛上此圖片的行程 ID（min 1）"
                  },
                  "url": {
                    "type": "string",
                    "description": "圖片網址（http 或 https），以引用方式掛載，非檔案上傳（max 2000）"
                  },
                  "caption": {
                    "type": "string",
                    "description": "圖片說明文字，選填（max 500）"
                  },
                  "displayOrder": {
                    "type": "number",
                    "description": "排序權重，數字越小越前面，預設 0（max 9999 · min 0）"
                  }
                },
                "required": [
                  "tripId",
                  "url"
                ]
              }
            }
          }
        }
      }
    },
    "/images/{id}": {
      "delete": {
        "operationId": "delete_images_id_",
        "tags": [
          "images"
        ],
        "summary": "remove a trip image",
        "description": "DELETE /api/v1/images/{id} — remove a trip image. Mirrors the back office\n`deleteImageAction`: same `image.manage` gate, same `deleteImage(db, id)`\ncall, same `image.delete` audit. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "欲刪除的行程圖片 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "image.manage"
      }
    },
    "/images/trips": {
      "get": {
        "operationId": "get_images_trips",
        "tags": [
          "images"
        ],
        "summary": "the trip picker for attaching images: draft +",
        "description": "GET /api/v1/images/trips — the trip picker for attaching images: draft +\npublished trips as `{ id, title }`, sorted by title. Gated under image.read\n(same as the gallery list), tenant-wide.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "行程 id（trip_ 前綴）。"
                          },
                          "title": {
                            "type": "string",
                            "description": "行程標題。"
                          }
                        },
                        "required": [
                          "id",
                          "title"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "image.read"
      }
    },
    "/internal-external-ledger/cancelled-departures": {
      "get": {
        "operationId": "get_internal_external_ledger_cancelled_departures",
        "tags": [
          "internal-external-ledger"
        ],
        "summary": "取消梯次待結轉列表",
        "description": "GET /api/v1/internal-external-ledger/cancelled-departures — 取消梯次待結轉列表\n(殘餘成本 / 房費 / 已核准·待覆核成本筆數 + 是否已結轉為特殊損益). The API-transport\nsibling of the 內外帳頁「取消梯次待結轉」card. Tenant-wide sensitive finance —\ngated `ledger.read` + accounting module (operating-expenses §3.4).",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "departureId": {
                            "type": "string",
                            "description": "取消梯次 ID。"
                          },
                          "tripTitle": {
                            "type": "string",
                            "description": "團名。"
                          },
                          "tripSlug": {
                            "type": "string",
                            "description": "行程 slug（URL 識別）。"
                          },
                          "departureDate": {
                            "type": "string",
                            "description": "原出團日期（YYYY-MM-DD）。"
                          },
                          "returnDate": {
                            "type": "string",
                            "description": "原回程日期（YYYY-MM-DD）。"
                          },
                          "groupCode": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "團號（group-code），未產生為 null。"
                          },
                          "residualCostTwd": {
                            "type": "number",
                            "description": "殘餘成本（TWD 整數）：已核准的逐筆成本合計 + 房費底價成本合計。"
                          },
                          "approvedCostCount": {
                            "type": "number",
                            "description": "已核准成本筆數。"
                          },
                          "pendingCostCount": {
                            "type": "number",
                            "description": "待覆核成本筆數（UI 提示「還有待覆核成本」）。"
                          },
                          "roomCostTwd": {
                            "type": "number",
                            "description": "房費殘餘成本（房費底價成本合計，整數 TWD）。"
                          },
                          "conversion": {
                            "anyOf": [
                              {},
                              {
                                "type": "null"
                              }
                            ],
                            "description": "結轉狀態：已結轉為特殊損益時的費用列資訊（expenseId / 金額 / 歸屬月 / 摘要）；未結轉為 null。"
                          }
                        },
                        "required": [
                          "departureId",
                          "tripTitle",
                          "tripSlug",
                          "departureDate",
                          "returnDate",
                          "groupCode",
                          "residualCostTwd",
                          "approvedCostCount",
                          "pendingCostCount",
                          "roomCostTwd",
                          "conversion"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "ledger.read",
        "x-module": "accounting"
      }
    },
    "/internal-external-ledger/cancelled-departures/convert": {
      "post": {
        "operationId": "post_internal_external_ledger_cancelled_departures_convert",
        "tags": [
          "internal-external-ledger"
        ],
        "summary": "結轉取消",
        "description": "POST /api/v1/internal-external-ledger/cancelled-departures/convert — 結轉取消\n梯次殘餘成本為公司特殊損益 (operating-expenses §3.4). Mirrors\n`convertCancelledDepartureAction`: same core fn, same permission\n(`operating_expense.manage`), same accounting-module gate, audit in core.\nCancelledConversionError → stable code (not_found 404 / invalid_* 422 / else 409).",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立的殘餘成本營業費用列 ID（opx_ 前綴）。"
                        },
                        "residualCostTwd": {
                          "type": "number",
                          "description": "結轉的殘餘成本金額（TWD 整數）。"
                        }
                      },
                      "required": [
                        "id",
                        "residualCostTwd"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "operating_expense.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "departureId": {
                    "type": "string",
                    "description": "梯次 ID（min 1）"
                  },
                  "categoryId": {
                    "type": "string",
                    "description": "特殊損益費用科目 ID（kind=special）（min 1）"
                  },
                  "period": {
                    "type": "string",
                    "description": "歸屬月（取消月，格式 YYYY-MM）（格式限定）"
                  },
                  "amountTwd": {
                    "type": "number",
                    "description": "結轉金額（整數 TWD，預設殘餘成本）"
                  },
                  "description": {
                    "type": "string",
                    "description": "摘要（min 1）"
                  },
                  "note": {
                    "type": "string",
                    "description": "備註（選填）"
                  }
                },
                "required": [
                  "departureId",
                  "categoryId",
                  "period",
                  "amountTwd",
                  "description"
                ]
              }
            }
          }
        }
      }
    },
    "/internal-external-ledger/cancelled-departures/revert": {
      "post": {
        "operationId": "post_internal_external_ledger_cancelled_departures_revert",
        "tags": [
          "internal-external-ledger"
        ],
        "summary": "撤銷取消",
        "description": "POST /api/v1/internal-external-ledger/cancelled-departures/revert — 撤銷取消\n梯次的結轉 (operating-expenses §3.4). Mirrors\n`revertCancelledDepartureConversionAction`: same core fn, same permission\n(`operating_expense.manage`), same accounting-module gate, audit in core.\nDeletes the kind='special' operating_expense row (dropping its\nsource_departure_id link). CancelledConversionError → stable code.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：已還原取消梯次的轉列，回到未轉列狀態。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "operating_expense.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "departureId": {
                    "type": "string",
                    "description": "梯次 ID（min 1）"
                  }
                },
                "required": [
                  "departureId"
                ]
              }
            }
          }
        }
      }
    },
    "/internal-external-ledger/costs/{costId}": {
      "patch": {
        "operationId": "patch_internal_external_ledger_costs_costId_",
        "tags": [
          "internal-external-ledger"
        ],
        "description": "/api/v1/internal-external-ledger/costs/{costId}\n - PATCH  更新一筆成本（內外帳 + 外幣維度）。Mirrors `updateCostAction`（departure_cost.manage）；\n          同一 core fn `updateDepartureCost(db, id, input, actor)`，audit 已在 repo 內寫。\n - DELETE 刪除一筆成本。Mirrors `deleteCostAction`（departure_cost.manage）；\n          同一 core fn `deleteDepartureCost(db, id, actor)`。\nDepartureCostError → 409（含 ALREADY_LINKED / PROOF_APPROVED_LOCKED）；ExpenseProofError 經 ActionError → 409。",
        "parameters": [
          {
            "name": "costId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "成本列 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：成本列已更新。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_cost.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "category": {
                    "type": "string",
                    "description": "成本類別代碼（須為有效的成本分類）"
                  },
                  "vendorName": {
                    "type": "string",
                    "description": "廠商／供應商名稱"
                  },
                  "description": {
                    "type": "string",
                    "description": "成本摘要說明"
                  },
                  "amountTwd": {
                    "type": "number",
                    "description": "真實成本（台幣整數）。台幣路徑必填；外幣路徑忽略，改由外幣金額乘匯率換算"
                  },
                  "currency": {
                    "type": "string",
                    "description": "幣別；TWD 或留空走台幣路徑，其他幣別走外幣路徑"
                  },
                  "foreignAmount": {
                    "type": "number",
                    "description": "外幣金額（整數）；僅外幣路徑使用"
                  },
                  "internalRateSource": {
                    "type": "string",
                    "enum": [
                      "fx_account",
                      "published",
                      "manual"
                    ],
                    "description": "內帳匯率來源：fx_account 外幣帳戶加權成本、published 台銀牌告、manual 手填成交率"
                  },
                  "fxAccountId": {
                    "type": "string",
                    "description": "外幣帳戶 ID；內帳匯率來源為 fx_account 時使用"
                  },
                  "manualRate": {
                    "type": "string",
                    "description": "手填成交匯率（字串保精度）；內帳匯率來源為 manual 時使用"
                  },
                  "hasReceipt": {
                    "type": "boolean",
                    "description": "是否有發票憑證；預設 true，false 表示無發票並強制可申報額為 0、改填支出證明單欄位"
                  },
                  "invoiceAmountTwd": {
                    "type": "number",
                    "description": "外帳可申報額覆寫（台幣整數，須大於等於 0、無上限）"
                  },
                  "payeeName": {
                    "type": "string",
                    "description": "受款人姓名；無發票時的支出證明單欄位"
                  },
                  "reasonNoReceipt": {
                    "type": "string",
                    "description": "無發票原因；無發票時的支出證明單欄位"
                  },
                  "proofSummary": {
                    "type": "string",
                    "description": "支出證明摘要；無發票時的支出證明單欄位"
                  },
                  "quantityMode": {
                    "type": "string",
                    "enum": [
                      "fixed",
                      "headcount"
                    ],
                    "description": "計價方式；未給=一次性總額，fixed=單價×固定數量，headcount=單價×ceil(Σ人頭/組距)"
                  },
                  "headcountComponents": {
                    "type": "array",
                    "items": {},
                    "description": "依人頭計價的人頭組合（passenger/leader/assistant/driver，至少一項）"
                  },
                  "groupDivisor": {
                    "type": "number",
                    "description": "依人頭計價的組距（≥ 1；空=直接加總）"
                  },
                  "quantityFixed": {
                    "type": "number",
                    "description": "固定數量計價的數量（≥ 0）"
                  },
                  "unitPriceTwd": {
                    "type": "number",
                    "description": "單價（台幣整數）；計價方式給值時必填"
                  }
                },
                "required": [
                  "category"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_internal_external_ledger_costs_costId_",
        "tags": [
          "internal-external-ledger"
        ],
        "description": "/api/v1/internal-external-ledger/costs/{costId}\n - PATCH  更新一筆成本（內外帳 + 外幣維度）。Mirrors `updateCostAction`（departure_cost.manage）；\n          同一 core fn `updateDepartureCost(db, id, input, actor)`，audit 已在 repo 內寫。\n - DELETE 刪除一筆成本。Mirrors `deleteCostAction`（departure_cost.manage）；\n          同一 core fn `deleteDepartureCost(db, id, actor)`。\nDepartureCostError → 409（含 ALREADY_LINKED / PROOF_APPROVED_LOCKED）；ExpenseProofError 經 ActionError → 409。",
        "parameters": [
          {
            "name": "costId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "成本列 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：成本列已刪除。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_cost.manage"
      }
    },
    "/internal-external-ledger/costs/{costId}/approve-declaration": {
      "post": {
        "operationId": "post_internal_external_ledger_costs_costId_approve_declaration",
        "tags": [
          "internal-external-ledger"
        ],
        "description": "POST /api/v1/internal-external-ledger/costs/{costId}/approve-declaration\n覆核一筆待覆核成本（L' 嚮導自報 pending → approved，計入淨利 / 可申報）。\nMirrors `approveDeclarationAction`：ledger.approve 閘 + 進階會計模組閘 + 責任分離\n（覆核人 ≠ 登記者，repo SELF_REVIEW 兜底）。同一 core fn `approveDeclaration(db, id, actor)`，\naudit 已在 repo 內寫。DepartureCostError → 409；module 未啟用（ActionError）→ 409。",
        "parameters": [
          {
            "name": "costId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "成本列 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：成本自主申報已核准。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "ledger.approve"
      }
    },
    "/internal-external-ledger/declarations/pending": {
      "get": {
        "operationId": "get_internal_external_ledger_declarations_pending",
        "tags": [
          "internal-external-ledger"
        ],
        "summary": "待覆核的嚮導申報",
        "description": "GET /api/v1/internal-external-ledger/declarations/pending — 待覆核的嚮導申報\n成本 (review_status='pending')，跨梯次彙整給會計覆核。Tenant-wide; `ledger.read`.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "成本列 ID。"
                          },
                          "departureId": {
                            "type": "string",
                            "description": "所屬梯次 ID。"
                          },
                          "tripTitle": {
                            "type": "string",
                            "description": "團名。"
                          },
                          "departureDate": {
                            "type": "string",
                            "description": "出團日期（YYYY-MM-DD）。"
                          },
                          "category": {
                            "type": "string",
                            "description": "成本分類。"
                          },
                          "vendorName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "供應商 / 廠商名（選填）。"
                          },
                          "amountTwd": {
                            "type": "number",
                            "description": "代墊 / 實付額（內帳真實成本，整數 TWD）。"
                          },
                          "invoiceAmountTwd": {
                            "type": "number",
                            "description": "憑證 / 發票額（外帳可申報，整數 TWD）。"
                          },
                          "isDeclarable": {
                            "type": "boolean",
                            "description": "是否取得合法憑證。"
                          },
                          "createdByName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "登記者（經手人）姓名。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間（嚮導送出時間）。"
                          }
                        },
                        "required": [
                          "id",
                          "departureId",
                          "tripTitle",
                          "departureDate",
                          "category",
                          "vendorName",
                          "amountTwd",
                          "invoiceAmountTwd",
                          "isDeclarable",
                          "createdByName",
                          "createdAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "ledger.read",
        "x-module": "accounting"
      }
    },
    "/internal-external-ledger/departures": {
      "get": {
        "operationId": "get_internal_external_ledger_departures",
        "tags": [
          "internal-external-ledger"
        ],
        "summary": "per-departure 內外帳列表",
        "description": "GET /api/v1/internal-external-ledger/departures — per-departure 內外帳列表\n(毛利 / 內帳真實額 / 外帳可申報 / pending 證明單)，即 /admin/control 內外帳列表頁\nover HTTP. Tenant-wide sensitive finance — gated on `ledger.read`; no\nowner-scope (內外帳 nav 屬 admin/accountant). See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "windowDays",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "回看天數；只列出近 N 天內的梯次"
            }
          },
          {
            "name": "tripId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "行程 ID；只列出該行程的梯次"
            }
          },
          {
            "name": "period",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "出團月（格式 YYYY-MM）；只列出該月的梯次（格式限定）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "tripTitle": {
                            "type": "string",
                            "description": "梯次標題（trip title）。"
                          },
                          "tripSlug": {
                            "type": "string",
                            "description": "行程 slug（URL 識別）。"
                          },
                          "departureDate": {
                            "type": "string",
                            "description": "出團日期（YYYY-MM-DD）。"
                          },
                          "returnDate": {
                            "type": "string",
                            "description": "回程日期（YYYY-MM-DD）。"
                          },
                          "groupCode": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "團號（group-code），未產生為 null。"
                          },
                          "pax": {
                            "type": "number",
                            "description": "報名人數（非取消單 party_size 合計）。"
                          },
                          "departureId": {
                            "type": "string",
                            "description": "梯次 ID。"
                          },
                          "revenueTwd": {
                            "type": "number",
                            "description": "本團收入（梯次應收，排除已取消訂單，TWD 整數）。"
                          },
                          "realCostTwd": {
                            "type": "number",
                            "description": "內帳真實成本（TWD 整數）= 房費底價成本 + 已核准的逐筆成本合計。"
                          },
                          "declarableCostTwd": {
                            "type": "number",
                            "description": "外帳可申報成本（各成本列憑證額合計，TWD 整數）。"
                          },
                          "nonDeclarableCostTwd": {
                            "type": "number",
                            "description": "不可申報（無憑證）真實成本，逐列 Σ GREATEST(amount − invoice, 0)（非跨列 realCost − declarableCost）。"
                          },
                          "costBilledTwd": {
                            "type": "number",
                            "description": "已轉請款成本。"
                          },
                          "costUnbilledTwd": {
                            "type": "number",
                            "description": "未轉請款成本。"
                          },
                          "grossProfitTwd": {
                            "type": "number",
                            "description": "**每梯次權威數＝毛利** = revenue − realCost（不扣手續費 / 稅，operating-expenses §2.3）。 公司月損益（computeCompanyPnL）的「各區毛利」即逐梯次此值按區彙整；手續費 / 稅在公司層 用實際值扣一次，**不**用下面的預估費率重扣（避免雙重計）。"
                          },
                          "feeEcpayTwd": {
                            "type": "number",
                            "description": "預估綠界手續費（**參考預估**，非權威；公司層用實際值，§2.3）。"
                          },
                          "feeFongshouTwd": {
                            "type": "number",
                            "description": "預估豐收款手續費（**參考預估**，非權威）。"
                          },
                          "taxEstTwd": {
                            "type": "number",
                            "description": "預估發票 / 營所稅（**參考預估**，非權威；公司層用實繳值）。"
                          },
                          "estimatedNetProfitTwd": {
                            "type": "number",
                            "description": "**參考預估淨利**（非權威）= grossProfit − feeEcpay − feeFongshou − taxEst。純給現場 快速感覺（毛利扣預估費率），**非公司財務真相** —— 公司淨利以 operating-expenses 月損益表 （實際 overhead）為準。權威數請用 `grossProfitTwd`。"
                          },
                          "marginPct": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "毛利率（grossProfit / revenue），revenue=0 時為 null。"
                          },
                          "pendingProofCount": {
                            "type": "number",
                            "description": "待核（pending）支出證明單數。"
                          },
                          "feeRates": {
                            "type": "object",
                            "properties": {
                              "ecpayFeeBps": {
                                "type": "number",
                                "description": "預估綠界手續費率（basis points，270 = 2.70%）。"
                              },
                              "fongshouFeeBps": {
                                "type": "number",
                                "description": "預估豐收款手續費率（basis points，50 = 0.50%）。"
                              },
                              "profitTaxBps": {
                                "type": "number",
                                "description": "預估發票 / 營所稅率（basis points，500 = 5.00%）。"
                              }
                            },
                            "required": [
                              "ecpayFeeBps",
                              "fongshouFeeBps",
                              "profitTaxBps"
                            ],
                            "description": "套用的費率（呈現用）。"
                          }
                        },
                        "required": [
                          "tripTitle",
                          "tripSlug",
                          "departureDate",
                          "returnDate",
                          "groupCode",
                          "pax",
                          "departureId",
                          "revenueTwd",
                          "realCostTwd",
                          "declarableCostTwd",
                          "nonDeclarableCostTwd",
                          "costBilledTwd",
                          "costUnbilledTwd",
                          "grossProfitTwd",
                          "feeEcpayTwd",
                          "feeFongshouTwd",
                          "taxEstTwd",
                          "estimatedNetProfitTwd",
                          "marginPct",
                          "pendingProofCount",
                          "feeRates"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "ledger.read",
        "x-module": "accounting"
      }
    },
    "/internal-external-ledger/departures/{departureId}": {
      "get": {
        "operationId": "get_internal_external_ledger_departures_departureId_",
        "tags": [
          "internal-external-ledger"
        ],
        "summary": "single",
        "description": "GET /api/v1/internal-external-ledger/departures/{departureId} — single\ndeparture 內外帳派生 (revenue / realCost / declarable / grossProfit /\nestimatedNetProfit / pending proofs). Tenant-wide finance — `ledger.read`.",
        "parameters": [
          {
            "name": "departureId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "departureId": {
                          "type": "string",
                          "description": "梯次 ID。"
                        },
                        "revenueTwd": {
                          "type": "number",
                          "description": "本團收入（梯次應收，排除已取消訂單，TWD 整數）。"
                        },
                        "realCostTwd": {
                          "type": "number",
                          "description": "內帳真實成本（TWD 整數）= 房費底價成本 + 已核准的逐筆成本合計。"
                        },
                        "declarableCostTwd": {
                          "type": "number",
                          "description": "外帳可申報成本（各成本列憑證額合計，TWD 整數）。"
                        },
                        "nonDeclarableCostTwd": {
                          "type": "number",
                          "description": "不可申報（無憑證）真實成本，逐列 Σ GREATEST(amount − invoice, 0)（非跨列 realCost − declarableCost）。"
                        },
                        "costBilledTwd": {
                          "type": "number",
                          "description": "已轉請款成本。"
                        },
                        "costUnbilledTwd": {
                          "type": "number",
                          "description": "未轉請款成本。"
                        },
                        "grossProfitTwd": {
                          "type": "number",
                          "description": "**每梯次權威數＝毛利** = revenue − realCost（不扣手續費 / 稅，operating-expenses §2.3）。 公司月損益（computeCompanyPnL）的「各區毛利」即逐梯次此值按區彙整；手續費 / 稅在公司層 用實際值扣一次，**不**用下面的預估費率重扣（避免雙重計）。"
                        },
                        "feeEcpayTwd": {
                          "type": "number",
                          "description": "預估綠界手續費（**參考預估**，非權威；公司層用實際值，§2.3）。"
                        },
                        "feeFongshouTwd": {
                          "type": "number",
                          "description": "預估豐收款手續費（**參考預估**，非權威）。"
                        },
                        "taxEstTwd": {
                          "type": "number",
                          "description": "預估發票 / 營所稅（**參考預估**，非權威；公司層用實繳值）。"
                        },
                        "estimatedNetProfitTwd": {
                          "type": "number",
                          "description": "**參考預估淨利**（非權威）= grossProfit − feeEcpay − feeFongshou − taxEst。純給現場 快速感覺（毛利扣預估費率），**非公司財務真相** —— 公司淨利以 operating-expenses 月損益表 （實際 overhead）為準。權威數請用 `grossProfitTwd`。"
                        },
                        "marginPct": {
                          "type": [
                            "number",
                            "null"
                          ],
                          "description": "毛利率（grossProfit / revenue），revenue=0 時為 null。"
                        },
                        "pendingProofCount": {
                          "type": "number",
                          "description": "待核（pending）支出證明單數。"
                        },
                        "feeRates": {
                          "type": "object",
                          "properties": {
                            "ecpayFeeBps": {
                              "type": "number",
                              "description": "預估綠界手續費率（basis points，270 = 2.70%）。"
                            },
                            "fongshouFeeBps": {
                              "type": "number",
                              "description": "預估豐收款手續費率（basis points，50 = 0.50%）。"
                            },
                            "profitTaxBps": {
                              "type": "number",
                              "description": "預估發票 / 營所稅率（basis points，500 = 5.00%）。"
                            }
                          },
                          "required": [
                            "ecpayFeeBps",
                            "fongshouFeeBps",
                            "profitTaxBps"
                          ],
                          "description": "套用的費率（呈現用）。"
                        }
                      },
                      "required": [
                        "departureId",
                        "revenueTwd",
                        "realCostTwd",
                        "declarableCostTwd",
                        "nonDeclarableCostTwd",
                        "costBilledTwd",
                        "costUnbilledTwd",
                        "grossProfitTwd",
                        "feeEcpayTwd",
                        "feeFongshouTwd",
                        "taxEstTwd",
                        "estimatedNetProfitTwd",
                        "marginPct",
                        "pendingProofCount",
                        "feeRates"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "ledger.read",
        "x-module": "accounting"
      }
    },
    "/internal-external-ledger/departures/{departureId}/convert-to-payable": {
      "post": {
        "operationId": "post_internal_external_ledger_departures_departureId_convert_to_payable",
        "tags": [
          "internal-external-ledger"
        ],
        "description": "POST /api/v1/internal-external-ledger/departures/{departureId}/convert-to-payable\n成本轉請款核簽：選定未轉成本列 → 建一張 payable + 回填 payable_id（同 tx）。\nMirrors `convertCostsToPayableAction` —— DUAL gate: cliRoute 先過 `departure_cost.manage`\n（含 2FA chokepoint），handler 內再非拋出式檢查 `payable.create`（hasPermissionForRole）→\n缺權 throw ForbiddenError（403）。同一 core fn `convertCostsToPayable(db, input, actor)`，\naudit 已在 repo 內寫。DepartureCostError → 409。",
        "parameters": [
          {
            "name": "departureId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "payableId": {
                          "type": "string",
                          "description": "新建立應付單的 ID（pay_ 前綴）。"
                        },
                        "payableNumber": {
                          "type": "string",
                          "description": "應付單編號（租戶內流水序號，出款核簽用）。"
                        }
                      },
                      "required": [
                        "payableId",
                        "payableNumber"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_cost.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "costIds": {
                    "type": "array",
                    "items": {},
                    "description": "要轉成請款核簽的成本列 ID 陣列（至少一筆，須為尚未轉請款者）（min 1）"
                  },
                  "payeeType": {
                    "type": "string",
                    "enum": [
                      "supplier",
                      "guide",
                      "staff_commission",
                      "other"
                    ],
                    "description": "受款對象類型：supplier 供應商、guide 嚮導、staff_commission 員工佣金、other 其他"
                  },
                  "payeeName": {
                    "type": "string",
                    "description": "受款對象名稱（min 1）"
                  },
                  "payeeBankAccount": {
                    "type": "string",
                    "description": "受款銀行帳號"
                  },
                  "payeeBankName": {
                    "type": "string",
                    "description": "受款銀行名稱"
                  },
                  "payeeBankBranch": {
                    "type": "string",
                    "description": "受款銀行分行"
                  },
                  "payeeTaxId": {
                    "type": "string",
                    "description": "受款對象統一編號／稅籍編號"
                  },
                  "taxAmountTwd": {
                    "type": "number",
                    "description": "代扣稅額（台幣整數）"
                  },
                  "submitImmediately": {
                    "type": "boolean",
                    "description": "是否建立後立即送出核簽（true 直接送審）"
                  }
                },
                "required": [
                  "costIds",
                  "payeeName"
                ]
              }
            }
          }
        }
      }
    },
    "/internal-external-ledger/departures/{departureId}/costs": {
      "get": {
        "operationId": "get_internal_external_ledger_departures_departureId_costs",
        "tags": [
          "internal-external-ledger"
        ],
        "description": "/api/v1/internal-external-ledger/departures/{departureId}/costs\n - GET  逐筆成本登記列表 (vendor / amount / invoice / declarable / review_status / fx fields).\n        Optional `--created-by` narrows to one registrant's rows. `ledger.read`.\n - POST 登記一筆成本（內外帳 + 外幣維度）。Mirrors `createCostAction`（departure_cost.manage）；\n        同一 core fn `createDepartureCost(db, input, actor)`，audit 已在 repo 內寫。\n        DepartureCostError → 409；ExpenseProofError 經 ActionError → 409。",
        "parameters": [
          {
            "name": "departureId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          },
          {
            "name": "createdBy",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "登記者使用者 ID；只列出該人登記的成本列"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "成本列 ID。"
                          },
                          "departureId": {
                            "type": "string",
                            "description": "所屬梯次 ID。"
                          },
                          "category": {
                            "type": "string",
                            "description": "成本分類（如 交通 / 餐費 / 保險 / 嚮導）。"
                          },
                          "vendorName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "供應商 / 廠商名（選填）。"
                          },
                          "description": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "摘要說明（選填）。"
                          },
                          "receiptImageUrl": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "憑證照片 URL（G3-2）；未附照片 null。app-route 私有 URL，讀取經 route 權限閘。"
                          },
                          "amountTwd": {
                            "type": "number",
                            "description": "代墊 / 實付額（內帳真實成本，整數 TWD）。"
                          },
                          "invoiceAmountTwd": {
                            "type": "number",
                            "description": "外帳可申報額（internal-external-ledger §2.1）。"
                          },
                          "isDeclarable": {
                            "type": "boolean",
                            "description": "是否取得合法憑證。"
                          },
                          "reviewStatus": {
                            "type": "string",
                            "description": "覆核狀態 'pending' | 'approved'（L'）：pending 不計入淨利 / 可申報（UI 須標示、停用轉請款）。"
                          },
                          "currency": {
                            "type": "string",
                            "description": "成本幣別（ISO 4217）；'TWD' = 台幣列。"
                          },
                          "foreignAmount": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "外幣金額（最小單位整數）；TWD 列 null。"
                          },
                          "internalRateSource": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "內帳匯率來源；TWD 列 null。"
                          },
                          "fxAccountId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "internalRateSource='fx_account' 時的外幣帳戶 id。"
                          },
                          "internalRate": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "內帳匯率快照（numeric 字串）；TWD 列 null。"
                          },
                          "externalRate": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "外帳匯率快照（numeric 字串，台銀牌告）；TWD 列 null。"
                          },
                          "feeCategory": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "費用類型 tag（account-settlement §3.4，成本側類別→領域帳戶映射；null = 未 tag）。"
                          },
                          "quantityMode": {
                            "anyOf": [
                              {},
                              {
                                "type": "null"
                              }
                            ],
                            "description": "計價方式 'fixed' / 'headcount'；一次性總額列 null。"
                          },
                          "headcountComponents": {
                            "type": [
                              "array",
                              "null"
                            ],
                            "items": {},
                            "description": "headcount 人頭組合；非 headcount 列 null。"
                          },
                          "groupDivisor": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "headcount 組距；非 headcount 列 null。"
                          },
                          "quantity": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "解析後（headcount）或自訂（fixed）的數量；一次性總額列 null。"
                          },
                          "unitPriceTwd": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "單價（台幣整數）；一次性總額列 null。"
                          },
                          "expenseProofId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "無發票支出掛的支出證明單 id（null = 有憑證）。"
                          },
                          "proofNumber": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "支出證明單單號（join expense_proofs，null = 無）。"
                          },
                          "proofStatus": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "支出證明單狀態 'pending' | 'approved'（null = 無）。"
                          },
                          "payableId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "已轉請款時連結的請款單 ID（null = 未轉請款）。"
                          },
                          "payableNumber": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "連結請款單的人類可讀單號（null = 未轉請款）。"
                          },
                          "payableStatus": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "連結請款單的狀態（draft / submitted / approved / paid…；null = 未轉請款）。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          }
                        },
                        "required": [
                          "id",
                          "departureId",
                          "category",
                          "vendorName",
                          "description",
                          "receiptImageUrl",
                          "amountTwd",
                          "invoiceAmountTwd",
                          "isDeclarable",
                          "reviewStatus",
                          "currency",
                          "foreignAmount",
                          "internalRateSource",
                          "fxAccountId",
                          "internalRate",
                          "externalRate",
                          "feeCategory",
                          "quantityMode",
                          "headcountComponents",
                          "groupDivisor",
                          "quantity",
                          "unitPriceTwd",
                          "expenseProofId",
                          "proofNumber",
                          "proofStatus",
                          "payableId",
                          "payableNumber",
                          "payableStatus",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "ledger.read"
      },
      "post": {
        "operationId": "post_internal_external_ledger_departures_departureId_costs",
        "tags": [
          "internal-external-ledger"
        ],
        "description": "/api/v1/internal-external-ledger/departures/{departureId}/costs\n - GET  逐筆成本登記列表 (vendor / amount / invoice / declarable / review_status / fx fields).\n        Optional `--created-by` narrows to one registrant's rows. `ledger.read`.\n - POST 登記一筆成本（內外帳 + 外幣維度）。Mirrors `createCostAction`（departure_cost.manage）；\n        同一 core fn `createDepartureCost(db, input, actor)`，audit 已在 repo 內寫。\n        DepartureCostError → 409；ExpenseProofError 經 ActionError → 409。",
        "parameters": [
          {
            "name": "departureId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立成本列的 ID（dc_ 前綴）。"
                        },
                        "expenseProofId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "隨附憑證的 ID（若本次一併登記），無則為 null。"
                        }
                      },
                      "required": [
                        "id",
                        "expenseProofId"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure_cost.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "category": {
                    "type": "string",
                    "description": "成本類別代碼（須為有效的成本分類）"
                  },
                  "vendorName": {
                    "type": "string",
                    "description": "廠商／供應商名稱"
                  },
                  "description": {
                    "type": "string",
                    "description": "成本摘要說明"
                  },
                  "amountTwd": {
                    "type": "number",
                    "description": "真實成本（台幣整數）。台幣路徑必填；外幣路徑忽略，改由外幣金額乘匯率換算"
                  },
                  "currency": {
                    "type": "string",
                    "description": "幣別；TWD 或留空走台幣路徑，其他幣別走外幣路徑"
                  },
                  "foreignAmount": {
                    "type": "number",
                    "description": "外幣金額（整數）；僅外幣路徑使用"
                  },
                  "internalRateSource": {
                    "type": "string",
                    "enum": [
                      "fx_account",
                      "published",
                      "manual"
                    ],
                    "description": "內帳匯率來源：fx_account 外幣帳戶加權成本、published 台銀牌告、manual 手填成交率"
                  },
                  "fxAccountId": {
                    "type": "string",
                    "description": "外幣帳戶 ID；內帳匯率來源為 fx_account 時使用"
                  },
                  "manualRate": {
                    "type": "string",
                    "description": "手填成交匯率（字串保精度）；內帳匯率來源為 manual 時使用"
                  },
                  "hasReceipt": {
                    "type": "boolean",
                    "description": "是否有發票憑證；預設 true，false 表示無發票並強制可申報額為 0、改填支出證明單欄位"
                  },
                  "invoiceAmountTwd": {
                    "type": "number",
                    "description": "外帳可申報額覆寫（台幣整數，須大於等於 0、無上限）"
                  },
                  "payeeName": {
                    "type": "string",
                    "description": "受款人姓名；無發票時的支出證明單欄位"
                  },
                  "reasonNoReceipt": {
                    "type": "string",
                    "description": "無發票原因；無發票時的支出證明單欄位"
                  },
                  "proofSummary": {
                    "type": "string",
                    "description": "支出證明摘要；無發票時的支出證明單欄位"
                  },
                  "quantityMode": {
                    "type": "string",
                    "enum": [
                      "fixed",
                      "headcount"
                    ],
                    "description": "計價方式；未給=一次性總額，fixed=單價×固定數量，headcount=單價×ceil(Σ人頭/組距)"
                  },
                  "headcountComponents": {
                    "type": "array",
                    "items": {},
                    "description": "依人頭計價的人頭組合（passenger/leader/assistant/driver，至少一項）"
                  },
                  "groupDivisor": {
                    "type": "number",
                    "description": "依人頭計價的組距（≥ 1；空=直接加總）"
                  },
                  "quantityFixed": {
                    "type": "number",
                    "description": "固定數量計價的數量（≥ 0）"
                  },
                  "unitPriceTwd": {
                    "type": "number",
                    "description": "單價（台幣整數）；計價方式給值時必填"
                  }
                },
                "required": [
                  "category"
                ]
              }
            }
          }
        }
      }
    },
    "/internal-external-ledger/departures/{departureId}/proofs": {
      "get": {
        "operationId": "get_internal_external_ledger_departures_departureId_proofs",
        "tags": [
          "internal-external-ledger"
        ],
        "summary": "支出",
        "description": "GET /api/v1/internal-external-ledger/departures/{departureId}/proofs — 支出\n證明單列表 (無憑證成本隱含產生的 pending/approved proofs). `ledger.read`.",
        "parameters": [
          {
            "name": "departureId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "支出證明單 ID。"
                          },
                          "proofNumber": {
                            "type": "string",
                            "description": "人類可讀單號（EP-YYMMDD-NNN）。"
                          },
                          "departureId": {
                            "type": "string",
                            "description": "所屬梯次 ID。"
                          },
                          "payeeName": {
                            "type": "string",
                            "description": "受款對象（自然人 / 廠商）。"
                          },
                          "amountTwd": {
                            "type": "number",
                            "description": "金額（整數 TWD，對應所掛成本列的 amount_twd）。"
                          },
                          "reasonNoReceipt": {
                            "type": "string",
                            "description": "無法取得單據的原因（如「自然人」）。"
                          },
                          "summary": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "支出內容及摘要（選填）。"
                          },
                          "handlerUserId": {
                            "type": "string",
                            "description": "經手人（建單者）user ID。"
                          },
                          "approverUserId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "核准人 user ID（強制 ≠ 經手人）；未核准為 null。"
                          },
                          "status": {
                            "description": "狀態：pending 待核准 / approved 已核准（核准後 append-only）。"
                          },
                          "approvedAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time",
                            "description": "核准時間；未核准為 null。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          }
                        },
                        "required": [
                          "id",
                          "proofNumber",
                          "departureId",
                          "payeeName",
                          "amountTwd",
                          "reasonNoReceipt",
                          "summary",
                          "handlerUserId",
                          "approverUserId",
                          "status",
                          "approvedAt",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "ledger.read",
        "x-module": "accounting"
      }
    },
    "/internal-external-ledger/departures/{departureId}/proofs/{proofId}": {
      "get": {
        "operationId": "get_internal_external_ledger_departures_departureId_proofs_proofId_",
        "tags": [
          "internal-external-ledger"
        ],
        "description": "GET /api/v1/internal-external-ledger/departures/{departureId}/proofs/{proofId}\n— single 支出證明單明細. getExpenseProof is NOT departure-scoped, so we\nre-check the proof belongs to the path departure (IDOR) and 404 otherwise —\nmirrors the back-office scope re-check. `ledger.read`.",
        "parameters": [
          {
            "name": "departureId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（min 1）"
            }
          },
          {
            "name": "proofId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "支出證明單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "支出證明單 ID。"
                        },
                        "proofNumber": {
                          "type": "string",
                          "description": "人類可讀單號（EP-YYMMDD-NNN）。"
                        },
                        "departureId": {
                          "type": "string",
                          "description": "所屬梯次 ID。"
                        },
                        "payeeName": {
                          "type": "string",
                          "description": "受款對象（自然人 / 廠商）。"
                        },
                        "amountTwd": {
                          "type": "number",
                          "description": "金額（整數 TWD，對應所掛成本列的 amount_twd）。"
                        },
                        "reasonNoReceipt": {
                          "type": "string",
                          "description": "無法取得單據的原因（如「自然人」）。"
                        },
                        "summary": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "支出內容及摘要（選填）。"
                        },
                        "handlerUserId": {
                          "type": "string",
                          "description": "經手人（建單者）user ID。"
                        },
                        "approverUserId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "核准人 user ID（強制 ≠ 經手人）；未核准為 null。"
                        },
                        "status": {
                          "description": "狀態：pending 待核准 / approved 已核准（核准後 append-only）。"
                        },
                        "approvedAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "核准時間；未核准為 null。"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "建立時間。"
                        },
                        "updatedAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "最後更新時間。"
                        }
                      },
                      "required": [
                        "id",
                        "proofNumber",
                        "departureId",
                        "payeeName",
                        "amountTwd",
                        "reasonNoReceipt",
                        "summary",
                        "handlerUserId",
                        "approverUserId",
                        "status",
                        "approvedAt",
                        "createdAt",
                        "updatedAt"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "ledger.read",
        "x-module": "accounting"
      }
    },
    "/internal-external-ledger/proofs/{proofId}/approve": {
      "post": {
        "operationId": "post_internal_external_ledger_proofs_proofId_approve",
        "tags": [
          "internal-external-ledger"
        ],
        "description": "POST /api/v1/internal-external-ledger/proofs/{proofId}/approve\n核准支出證明單（pending → approved）。Mirrors `approveProofAction`：ledger.approve 閘 +\n進階會計模組閘 + 責任分離（核准人 ≠ 經手人，repo SELF_APPROVAL 兜底）。同一 core fn\n`approveExpenseProof(db, id, actor)`，audit 已在 repo 內寫。ExpenseProofError → 409；\nmodule 未啟用（ActionError）→ 409。",
        "parameters": [
          {
            "name": "proofId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "支出證明單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：憑證已核准。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "ledger.approve"
      }
    },
    "/journal": {
      "get": {
        "operationId": "get_journal",
        "tags": [
          "journal"
        ],
        "summary": "list/search 嚮導手記 posts",
        "description": "GET /api/v1/journal — list/search 嚮導手記 posts (the /admin/journal table\nover HTTP). Tenant-wide (no owner scope); status/q filters + pagination match\nthe back office.\n\nPOST /api/v1/journal — create a 嚮導手記 post. Same core op + audit as the back\noffice `createJournalAction`; gated `journal.manage`. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "draft",
                "published",
                "archived"
              ],
              "description": "依狀態篩選：all 全部、draft 草稿、published 已發佈、archived 已封存"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "關鍵字搜尋（標題／內容）"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "頁碼（從 1 起）"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "每頁筆數（上限 200）（max 200）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "手記文章 id（journalPost_ 前綴）。"
                              },
                              "slug": {
                                "type": "string",
                                "description": "文章公開頁網址代稱（slug）。"
                              },
                              "title": {
                                "type": "string",
                                "description": "文章標題。"
                              },
                              "excerpt": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "摘要（列表／SEO 用；可空）。"
                              },
                              "coverImageUrl": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "封面圖網址（可空）。"
                              },
                              "contentMdx": {
                                "type": "string",
                                "description": "內文原始 MDX 內容。"
                              },
                              "authorGuideId": {
                                "anyOf": [
                                  {},
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "作者嚮導 id（未指定作者時 null）。"
                              },
                              "seoTitle": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "SEO 標題（覆寫 <title>；可空）。"
                              },
                              "seoDescription": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "SEO 描述（meta description；可空）。"
                              },
                              "ogImageUrl": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "Open Graph 分享圖網址（可空）。"
                              },
                              "status": {
                                "description": "文章狀態：draft 草稿／published 已發佈／archived 已封存。"
                              },
                              "publishedAt": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "format": "date-time",
                                "description": "首次發佈時間（尚未發佈為 null）。"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "建檔時間。"
                              },
                              "updatedAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "最後更新時間。"
                              }
                            },
                            "required": [
                              "id",
                              "slug",
                              "title",
                              "excerpt",
                              "coverImageUrl",
                              "contentMdx",
                              "authorGuideId",
                              "seoTitle",
                              "seoDescription",
                              "ogImageUrl",
                              "status",
                              "publishedAt",
                              "createdAt",
                              "updatedAt"
                            ]
                          },
                          "description": "本頁的手記文章列表。"
                        },
                        "total": {
                          "type": "number",
                          "description": "符合條件的文章總數（跨頁）。"
                        },
                        "page": {
                          "type": "number",
                          "description": "目前頁碼（從 1 起）。"
                        },
                        "pageSize": {
                          "type": "number",
                          "description": "每頁筆數。"
                        }
                      },
                      "required": [
                        "rows",
                        "total",
                        "page",
                        "pageSize"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "journal.read"
      },
      "post": {
        "operationId": "post_journal",
        "tags": [
          "journal"
        ],
        "summary": "create a 嚮導手記 post",
        "description": "GET /api/v1/journal — list/search 嚮導手記 posts (the /admin/journal table\nover HTTP). Tenant-wide (no owner scope); status/q filters + pagination match\nthe back office.\n\nPOST /api/v1/journal — create a 嚮導手記 post. Same core op + audit as the back\noffice `createJournalAction`; gated `journal.manage`. See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立的手記文章 id。"
                        },
                        "slug": {
                          "type": "string",
                          "description": "文章公開頁網址代稱（slug）。"
                        }
                      },
                      "required": [
                        "id",
                        "slug"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "journal.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "手記標題，顯示於前台與後台列表（max 200 · min 1）"
                  },
                  "slug": {
                    "type": "string",
                    "description": "網址代稱（slug）；僅小寫英數與連字號，省略時由系統依標題產生（格式限定）"
                  },
                  "excerpt": {
                    "type": "string",
                    "description": "摘要，列表與分享預覽用；null 清除（max 1000）"
                  },
                  "coverImageUrl": {
                    "type": "string",
                    "description": "封面圖網址（http/https）；null 清除（max 500）"
                  },
                  "contentMdx": {
                    "type": "string",
                    "description": "內文（MDX 格式）（max 100000 · min 1）"
                  },
                  "authorGuideId": {
                    "type": "string",
                    "description": "作者嚮導 ID；null 表示無指定作者"
                  },
                  "seoTitle": {
                    "type": "string",
                    "description": "SEO 標題，省略時用 title；null 清除（max 200）"
                  },
                  "seoDescription": {
                    "type": "string",
                    "description": "SEO 描述（meta description）；null 清除（max 500）"
                  },
                  "ogImageUrl": {
                    "type": "string",
                    "description": "Open Graph 分享圖網址（http/https）；null 清除（max 500）"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "draft",
                      "published",
                      "archived"
                    ],
                    "description": "發佈狀態：draft 草稿、published 已發佈、archived 已封存"
                  }
                },
                "required": [
                  "title",
                  "contentMdx"
                ]
              }
            }
          }
        }
      }
    },
    "/journal/{id}": {
      "get": {
        "operationId": "get_journal_id_",
        "tags": [
          "journal"
        ],
        "summary": "full 嚮導手記 post detail",
        "description": "GET /api/v1/journal/{id} — full 嚮導手記 post detail (header + SEO/OG fields +\nraw contentMdx + lifecycle). Tenant-wide; missing → 404.\n\nPATCH /api/v1/journal/{id} — update a 嚮導手記 post (PUT-style full replace,\nmirroring the back office which validates the SAME full schema). Same core op\n+ audit as `updateJournalAction`; gated `journal.manage`. Missing → 404.\nSee specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "嚮導手記文章 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "手記文章 id（journalPost_ 前綴）。"
                        },
                        "slug": {
                          "type": "string",
                          "description": "文章公開頁網址代稱（slug）。"
                        },
                        "title": {
                          "type": "string",
                          "description": "文章標題。"
                        },
                        "excerpt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "摘要（列表／SEO 用；可空）。"
                        },
                        "coverImageUrl": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "封面圖網址（可空）。"
                        },
                        "contentMdx": {
                          "type": "string",
                          "description": "內文原始 MDX 內容。"
                        },
                        "authorGuideId": {
                          "anyOf": [
                            {},
                            {
                              "type": "null"
                            }
                          ],
                          "description": "作者嚮導 id（未指定作者時 null）。"
                        },
                        "seoTitle": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "SEO 標題（覆寫 <title>；可空）。"
                        },
                        "seoDescription": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "SEO 描述（meta description；可空）。"
                        },
                        "ogImageUrl": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Open Graph 分享圖網址（可空）。"
                        },
                        "status": {
                          "description": "文章狀態：draft 草稿／published 已發佈／archived 已封存。"
                        },
                        "publishedAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "首次發佈時間（尚未發佈為 null）。"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "建檔時間。"
                        },
                        "updatedAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "最後更新時間。"
                        }
                      },
                      "required": [
                        "id",
                        "slug",
                        "title",
                        "excerpt",
                        "coverImageUrl",
                        "contentMdx",
                        "authorGuideId",
                        "seoTitle",
                        "seoDescription",
                        "ogImageUrl",
                        "status",
                        "publishedAt",
                        "createdAt",
                        "updatedAt"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "journal.read"
      },
      "patch": {
        "operationId": "patch_journal_id_",
        "tags": [
          "journal"
        ],
        "summary": "update a 嚮導手記 post",
        "description": "GET /api/v1/journal/{id} — full 嚮導手記 post detail (header + SEO/OG fields +\nraw contentMdx + lifecycle). Tenant-wide; missing → 404.\n\nPATCH /api/v1/journal/{id} — update a 嚮導手記 post (PUT-style full replace,\nmirroring the back office which validates the SAME full schema). Same core op\n+ audit as `updateJournalAction`; gated `journal.manage`. Missing → 404.\nSee specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "嚮導手記文章 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "更新成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "journal.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "手記標題，顯示於前台與後台列表（max 200 · min 1）"
                  },
                  "slug": {
                    "type": "string",
                    "description": "網址代稱（slug）；僅小寫英數與連字號，省略時由系統依標題產生（格式限定）"
                  },
                  "excerpt": {
                    "type": "string",
                    "description": "摘要，列表與分享預覽用；null 清除（max 1000）"
                  },
                  "coverImageUrl": {
                    "type": "string",
                    "description": "封面圖網址（http/https）；null 清除（max 500）"
                  },
                  "contentMdx": {
                    "type": "string",
                    "description": "內文（MDX 格式）（max 100000 · min 1）"
                  },
                  "authorGuideId": {
                    "type": "string",
                    "description": "作者嚮導 ID；null 表示無指定作者"
                  },
                  "seoTitle": {
                    "type": "string",
                    "description": "SEO 標題，省略時用 title；null 清除（max 200）"
                  },
                  "seoDescription": {
                    "type": "string",
                    "description": "SEO 描述（meta description）；null 清除（max 500）"
                  },
                  "ogImageUrl": {
                    "type": "string",
                    "description": "Open Graph 分享圖網址（http/https）；null 清除（max 500）"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "draft",
                      "published",
                      "archived"
                    ],
                    "description": "發佈狀態：draft 草稿、published 已發佈、archived 已封存"
                  }
                },
                "required": [
                  "title",
                  "contentMdx"
                ]
              }
            }
          }
        }
      }
    },
    "/journal/{id}/archive": {
      "post": {
        "operationId": "post_journal_id_archive",
        "tags": [
          "journal"
        ],
        "summary": "archive a 嚮導手記 post",
        "description": "POST /api/v1/journal/{id}/archive — archive a 嚮導手記 post (status→archived).\nSame core op + audit as the back office `archiveJournalAction`; gated\n`journal.manage`. Missing → 404. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "嚮導手記文章 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "封存成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "journal.manage"
      }
    },
    "/journal/authors": {
      "get": {
        "operationId": "get_journal_authors",
        "tags": [
          "journal"
        ],
        "summary": "active guides as author options for journal",
        "description": "GET /api/v1/journal/authors — active guides as author options for journal\nauthorship (combobox values in the back office). Tenant-wide, no input.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "value": {
                            "type": "string",
                            "description": "作者嚮導 id（作為選項值）。"
                          },
                          "label": {
                            "type": "string",
                            "description": "顯示用的嚮導姓名。"
                          }
                        },
                        "required": [
                          "value",
                          "label"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "journal.read"
      }
    },
    "/leaderboard": {
      "get": {
        "operationId": "get_leaderboard",
        "tags": [
          "leaderboard"
        ],
        "summary": "全公司業務業績排行",
        "description": "GET /api/v1/leaderboard — 全公司業務業績排行（/admin/leaderboard 報表頁）。\nadmin-only（leaderboard.read 只在 admin grant 自動涵蓋）；tenant-wide 聚合，\n不套 owner-scope。依 period（month/quarter/year/all，default month）回每位業務的\n成交應收業績（SUM(order_charge_lines.amount_twd) over non-cancelled tour orders）。",
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "month",
                "quarter",
                "year",
                "all"
              ],
              "description": "業績統計區間：當月、當季、當年或全部，預設 month"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "userId": {
                            "type": "string",
                            "description": "業務的使用者 ID。"
                          },
                          "name": {
                            "type": "string",
                            "description": "業務顯示姓名。"
                          },
                          "email": {
                            "type": "string",
                            "description": "業務登入 Email。"
                          },
                          "role": {
                            "type": "string",
                            "description": "業務角色代碼（admin／sales／op／accountant）。"
                          },
                          "orderCount": {
                            "type": "number",
                            "description": "承作訂單總數（歸屬此業務、含各狀態的旅遊團訂單）。"
                          },
                          "paidCount": {
                            "type": "number",
                            "description": "已成交訂單數（已付款或履約完成）。"
                          },
                          "cancelledCount": {
                            "type": "number",
                            "description": "已取消訂單數。"
                          },
                          "revenue": {
                            "type": "number",
                            "description": "業績額（TWD 整數）：歸屬於該業務、未取消訂單的應收合計。"
                          },
                          "commissionTwd": {
                            "type": "number",
                            "description": "估算佣金 = round(revenue × sales_commission_bps / 10000)（tenant_settings 費率）。"
                          },
                          "bonusTwd": {
                            "type": "number",
                            "description": "月度第一名加碼 = round(revenue × monthly_top_bonus_bps / 10000)，僅當期 rank 1 且 revenue > 0；其餘為 0。與 isMonthlyTop 同步。"
                          },
                          "isMonthlyTop": {
                            "type": "boolean",
                            "description": "當期 rank 1（revenue > 0）＝月度第一，享 bonus。"
                          },
                          "avgOrderTwd": {
                            "type": "number",
                            "description": "客單均價 = round(revenue / orderCount)；0 單為 0。"
                          }
                        },
                        "required": [
                          "userId",
                          "name",
                          "email",
                          "role",
                          "orderCount",
                          "paidCount",
                          "cancelledCount",
                          "revenue",
                          "commissionTwd",
                          "bonusTwd",
                          "isMonthlyTop",
                          "avgOrderTwd"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "leaderboard.read"
      }
    },
    "/leaderboard/review-stats": {
      "get": {
        "operationId": "get_leaderboard_review_stats",
        "tags": [
          "leaderboard"
        ],
        "summary": "待派發訂單 KPI",
        "description": "GET /api/v1/leaderboard/review-stats — 待派發訂單 KPI（pending 數 / pending 應收 /\n最長等待時數 / 本月已派發）。leaderboard 頁以 admin 身分呼叫 → tenant-wide 聚合，\n不套 scope（leaderboard.read 持有者一律看全租戶聚合）。",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "pendingCount": {
                          "type": "number",
                          "description": "待派發（pending_review）訂單筆數。"
                        },
                        "pendingTotalTwd": {
                          "type": "number",
                          "description": "待派發訂單的應收金額合計（新台幣）。"
                        },
                        "longestWaitHours": {
                          "type": "number",
                          "description": "目前待派發訂單中，最長已等待的時數。"
                        },
                        "thisMonthAssigned": {
                          "type": "number",
                          "description": "本月（Asia/Taipei）已完成派發的訂單數。"
                        }
                      },
                      "required": [
                        "pendingCount",
                        "pendingTotalTwd",
                        "longestWaitHours",
                        "thisMonthAssigned"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "leaderboard.read"
      }
    },
    "/lodging/bookings": {
      "get": {
        "operationId": "get_lodging_bookings",
        "tags": [
          "lodging"
        ],
        "summary": "list staff-side direct lodging bookings",
        "description": "GET /api/v1/lodging/bookings — list staff-side direct lodging bookings (代訂)\nwith optional status + free-text filter. Tenant-wide read (mirrors the\n/admin/lodging bookings table, which gates on lodging.read).",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依訂單狀態篩選（省略則回全部）"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "自由文字關鍵字（訂房人、旅宿等）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "orderId": {
                            "type": "string",
                            "description": "訂單 id（ord_ 前綴）。"
                          },
                          "orderNumber": {
                            "type": "string",
                            "description": "訂單編號（人類可讀流水號）。"
                          },
                          "status": {
                            "type": "string",
                            "description": "顯示狀態（派生自三軸，沿用舊欄名供 UI badge / canCancel 相容）。"
                          },
                          "bookingState": {
                            "type": "string",
                            "description": "訂位軸狀態（如 confirmed / cancelled）。"
                          },
                          "paymentState": {
                            "type": "string",
                            "description": "付款軸狀態（如 unpaid / partial / paid）。"
                          },
                          "refundState": {
                            "type": "string",
                            "description": "退款軸狀態。"
                          },
                          "totalTwd": {
                            "type": "number",
                            "description": "應收總額（TWD 整數，訂單各應收明細加總）。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "訂單建立時間。"
                          },
                          "bookerName": {
                            "type": "string",
                            "description": "訂購人姓名。"
                          },
                          "bookerEmail": {
                            "type": "string",
                            "description": "訂購人 email。"
                          },
                          "propertyId": {
                            "type": "string",
                            "description": "住宿館 id（prop_ 前綴）。"
                          },
                          "propertyName": {
                            "type": "string",
                            "description": "住宿館名稱。"
                          },
                          "roomTypeId": {
                            "type": "string",
                            "description": "房型 id（rt_ 前綴）。"
                          },
                          "roomTypeName": {
                            "type": "string",
                            "description": "房型名稱。"
                          },
                          "checkIn": {
                            "type": "string",
                            "description": "入住日（ISO 'YYYY-MM-DD'）。"
                          },
                          "checkOut": {
                            "type": "string",
                            "description": "退房日（ISO 'YYYY-MM-DD'）。"
                          },
                          "units": {
                            "type": "number",
                            "description": "訂購房間數。"
                          },
                          "guestCount": {
                            "type": "number",
                            "description": "入住總人數。"
                          }
                        },
                        "required": [
                          "orderId",
                          "orderNumber",
                          "status",
                          "bookingState",
                          "paymentState",
                          "refundState",
                          "totalTwd",
                          "createdAt",
                          "bookerName",
                          "bookerEmail",
                          "propertyId",
                          "propertyName",
                          "roomTypeId",
                          "roomTypeName",
                          "checkIn",
                          "checkOut",
                          "units",
                          "guestCount"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.read"
      },
      "post": {
        "operationId": "post_lodging_bookings",
        "tags": [
          "lodging"
        ],
        "description": "GET /api/v1/lodging/bookings — list staff-side direct lodging bookings (代訂)\nwith optional status + free-text filter. Tenant-wide read (mirrors the\n/admin/lodging bookings table, which gates on lodging.read).",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "orderId": {
                          "type": "string",
                          "description": "新建立住宿訂單的 id（ord_ 前綴）。"
                        }
                      },
                      "required": [
                        "orderId"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.create",
        "x-module": "lodging",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "propertyId": {
                    "type": "string",
                    "description": "旅宿物件 ID（min 1）"
                  },
                  "roomTypeId": {
                    "type": "string",
                    "description": "房型 ID（須屬於該旅宿物件）（min 1）"
                  },
                  "checkIn": {
                    "type": "string",
                    "description": "入住日（YYYY-MM-DD，含此晚）（min 1）"
                  },
                  "checkOut": {
                    "type": "string",
                    "description": "退房日（YYYY-MM-DD，不含此晚，須晚於入住日）（min 1）"
                  },
                  "units": {
                    "type": "number",
                    "description": "預訂單元數（房數或床位數，1-50）"
                  },
                  "guestCount": {
                    "type": "number",
                    "description": "入住人數（1-100，不得超過房型總容納人數）"
                  },
                  "bookerEmail": {
                    "type": "string",
                    "description": "訂房人 Email（須為已註冊會員）（min 1）"
                  },
                  "paymentMethod": {
                    "type": "string",
                    "enum": [
                      "cash",
                      "atm",
                      "manual"
                    ],
                    "description": "付款方式：cash 現金／atm 轉帳／manual 其他人工"
                  },
                  "receivingAccountId": {
                    "type": "string",
                    "description": "收款帳戶 ID（搭配付款方式記帳，可省略）"
                  },
                  "notes": {
                    "type": "string",
                    "description": "代訂備註"
                  }
                },
                "required": [
                  "propertyId",
                  "roomTypeId",
                  "checkIn",
                  "checkOut",
                  "units",
                  "guestCount",
                  "bookerEmail",
                  "paymentMethod"
                ]
              }
            }
          }
        }
      }
    },
    "/lodging/bookings/{orderId}": {
      "get": {
        "operationId": "get_lodging_bookings_orderId_",
        "tags": [
          "lodging"
        ],
        "summary": "single lodging booking detail.",
        "description": "GET /api/v1/lodging/bookings/{orderId} — single lodging booking detail.\nMissing (or non-lodging order) → 404.",
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "旅宿訂單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "orderId": {
                          "type": "string",
                          "description": "訂單 id（ord_ 前綴）。"
                        },
                        "orderNumber": {
                          "type": "string",
                          "description": "訂單編號（人類可讀流水號）。"
                        },
                        "status": {
                          "type": "string",
                          "description": "顯示狀態（派生自三軸，沿用舊欄名供 UI badge / canCancel 相容）。"
                        },
                        "bookingState": {
                          "type": "string",
                          "description": "訂位軸狀態（如 confirmed / cancelled）。"
                        },
                        "paymentState": {
                          "type": "string",
                          "description": "付款軸狀態（如 unpaid / partial / paid）。"
                        },
                        "refundState": {
                          "type": "string",
                          "description": "退款軸狀態。"
                        },
                        "totalTwd": {
                          "type": "number",
                          "description": "應收總額（TWD 整數，訂單各應收明細加總）。"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "訂單建立時間。"
                        },
                        "bookerName": {
                          "type": "string",
                          "description": "訂購人姓名。"
                        },
                        "bookerEmail": {
                          "type": "string",
                          "description": "訂購人 email。"
                        },
                        "propertyId": {
                          "type": "string",
                          "description": "住宿館 id（prop_ 前綴）。"
                        },
                        "propertyName": {
                          "type": "string",
                          "description": "住宿館名稱。"
                        },
                        "roomTypeId": {
                          "type": "string",
                          "description": "房型 id（rt_ 前綴）。"
                        },
                        "roomTypeName": {
                          "type": "string",
                          "description": "房型名稱。"
                        },
                        "checkIn": {
                          "type": "string",
                          "description": "入住日（ISO 'YYYY-MM-DD'）。"
                        },
                        "checkOut": {
                          "type": "string",
                          "description": "退房日（ISO 'YYYY-MM-DD'）。"
                        },
                        "units": {
                          "type": "number",
                          "description": "訂購房間數。"
                        },
                        "guestCount": {
                          "type": "number",
                          "description": "入住總人數。"
                        }
                      },
                      "required": [
                        "orderId",
                        "orderNumber",
                        "status",
                        "bookingState",
                        "paymentState",
                        "refundState",
                        "totalTwd",
                        "createdAt",
                        "bookerName",
                        "bookerEmail",
                        "propertyId",
                        "propertyName",
                        "roomTypeId",
                        "roomTypeName",
                        "checkIn",
                        "checkOut",
                        "units",
                        "guestCount"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.read"
      }
    },
    "/lodging/bookings/{orderId}/cancel": {
      "post": {
        "operationId": "post_lodging_bookings_orderId_cancel",
        "tags": [
          "lodging"
        ],
        "summary": "cancel a direct lodging",
        "description": "POST /api/v1/lodging/bookings/{orderId}/cancel — cancel a direct lodging\nbooking (release reserved nights). Same core op as `cancelLodgingBookingAction`;\ngated `order.update`. Owner-scope re-derived server-side (sales can only\ncancel their own bookings; out-of-scope → 404). cancelLodgingBooking writes\nits own audit log.",
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "旅宿訂單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.update"
      }
    },
    "/lodging/images/{id}": {
      "delete": {
        "operationId": "delete_lodging_images_id_",
        "tags": [
          "lodging"
        ],
        "summary": "delete a gallery",
        "description": "DELETE /api/v1/lodging/images/{id}?kind=property|room-type — delete a gallery\nimage. Same core op as `deletePropertyImageAction` / `deleteRoomTypeImageAction`;\ngated `lodging.manage`. The two actions target different tables (property vs\nroom-type galleries) but the image id alone is opaque, so the caller picks the\ngallery with `?kind`. NOTE: neither core fn writes an audit log — faithfully\nmirroring the actions, which also write none.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "圖片 ID（min 1）"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "property",
                "room-type"
              ],
              "description": "圖片所屬相簿：property 旅宿相簿／room-type 房型相簿"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.manage",
        "x-module": "lodging"
      }
    },
    "/lodging/properties": {
      "get": {
        "operationId": "get_lodging_properties",
        "tags": [
          "lodging"
        ],
        "summary": "list tenant lodging properties",
        "description": "/api/v1/lodging/properties\n  GET  — list tenant lodging properties (the /admin/lodging inventory list).\n         Tenant-wide, no owner-scope.\n  POST — create a property. Same core op + audit as `createPropertyAction`;\n         gated `lodging.manage`. createProperty writes its own audit log.\nSee specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "object",
                            "properties": {
                              "length": {
                                "type": "number",
                                "description": "Returns the length of a String object."
                              }
                            },
                            "required": [
                              "length"
                            ],
                            "description": "住宿館 id（prop_ 前綴）。"
                          },
                          "slug": {
                            "type": "string",
                            "description": "網址 slug（公開站路徑，租戶內唯一）。"
                          },
                          "name": {
                            "type": "string",
                            "description": "住宿館名稱。"
                          },
                          "kind": {
                            "type": "string",
                            "description": "類型：hotel 旅館 / camp 營地。"
                          },
                          "isOverseas": {
                            "type": "boolean",
                            "description": "是否為海外住宿。"
                          },
                          "location": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "地點描述；null = 未設。"
                          },
                          "description": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "簡介文字；null = 未設。"
                          },
                          "contentMdx": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "內文（MDX 原始碼）；null = 未設。"
                          },
                          "facilities": {
                            "description": "設施清單（JSON）；null = 未設。"
                          },
                          "coverImageUrl": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "封面圖 URL；null = 未設。"
                          },
                          "usageHint": {
                            "type": "string",
                            "description": "用途：direct 散客直訂 / package 梯次配套 / both 兩者皆可。"
                          },
                          "checkInTime": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "入住時間文字（如「15:00」）；null = 未設。"
                          },
                          "checkOutTime": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "退房時間文字（如「11:00」）；null = 未設。"
                          },
                          "checkInInfo": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "入住須知；null = 未設。"
                          },
                          "houseRules": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "館內規範；null = 未設。"
                          },
                          "cancellationPolicy": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "取消政策；null = 未設。"
                          },
                          "addressRegion": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "地址：縣市／區域；null = 未設。"
                          },
                          "addressLocality": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "地址：鄉鎮／地區；null = 未設。"
                          },
                          "streetAddress": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "街道地址；null = 未設。"
                          },
                          "postalCode": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "郵遞區號；null = 未設。"
                          },
                          "latitude": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "緯度；null = 未設。"
                          },
                          "longitude": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "經度；null = 未設。"
                          },
                          "phone": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "聯絡電話；null = 未設。"
                          },
                          "petsAllowed": {
                            "type": [
                              "boolean",
                              "null"
                            ],
                            "description": "是否允許攜帶寵物；null = 未設。"
                          },
                          "smokingAllowed": {
                            "type": [
                              "boolean",
                              "null"
                            ],
                            "description": "是否允許吸菸；null = 未設。"
                          },
                          "status": {
                            "type": "string",
                            "description": "狀態：active 啟用 / inactive 停用。"
                          },
                          "seoTitle": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "SEO 標題覆寫；null = 沿用內容欄。"
                          },
                          "seoDescription": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "SEO 描述；null = 未設。"
                          },
                          "ogImageUrl": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Open Graph 分享圖 URL；null = 未設。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          }
                        },
                        "required": [
                          "id",
                          "slug",
                          "name",
                          "kind",
                          "isOverseas",
                          "location",
                          "description",
                          "contentMdx",
                          "facilities",
                          "coverImageUrl",
                          "usageHint",
                          "checkInTime",
                          "checkOutTime",
                          "checkInInfo",
                          "houseRules",
                          "cancellationPolicy",
                          "addressRegion",
                          "addressLocality",
                          "streetAddress",
                          "postalCode",
                          "latitude",
                          "longitude",
                          "phone",
                          "petsAllowed",
                          "smokingAllowed",
                          "status",
                          "seoTitle",
                          "seoDescription",
                          "ogImageUrl",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.read"
      },
      "post": {
        "operationId": "post_lodging_properties",
        "tags": [
          "lodging"
        ],
        "summary": "create a property",
        "description": "/api/v1/lodging/properties\n  GET  — list tenant lodging properties (the /admin/lodging inventory list).\n         Tenant-wide, no owner-scope.\n  POST — create a property. Same core op + audit as `createPropertyAction`;\n         gated `lodging.manage`. createProperty writes its own audit log.\nSee specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立住宿館的 id（prop_ 前綴）。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.manage",
        "x-module": "lodging",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "slug": {
                    "type": "string",
                    "description": "旅宿代稱（小寫英數與連字號，2-63 字，租戶內唯一，用於網址）（格式限定）"
                  },
                  "name": {
                    "type": "string",
                    "description": "旅宿名稱（對外顯示）（max 200 · min 1）"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "camp",
                      "hotel"
                    ],
                    "description": "旅宿類型：camp 營地／hotel 旅館，預設 hotel"
                  },
                  "isOverseas": {
                    "type": "boolean",
                    "description": "是否為海外旅宿，預設否"
                  },
                  "location": {
                    "type": "string",
                    "description": "所在地點概述（如縣市、區域）（max 200）"
                  },
                  "description": {
                    "type": "string",
                    "description": "旅宿介紹文字（max 2000）"
                  },
                  "usageHint": {
                    "type": "string",
                    "enum": [
                      "direct",
                      "package",
                      "both"
                    ],
                    "description": "銷售用途：direct 僅直接訂房／package 僅併入套裝行程／both 兩者皆可，預設 both"
                  }
                },
                "required": [
                  "slug",
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/lodging/properties/{id}": {
      "get": {
        "operationId": "get_lodging_properties_id_",
        "tags": [
          "lodging"
        ],
        "summary": "single lodging property",
        "description": "/api/v1/lodging/properties/{id}\n  GET   — single lodging property. Missing → 404.\n  PATCH — update a property. Same core op + audit as `updatePropertyAction`;\n          gated `lodging.manage`. updateProperty writes its own audit log.\n          Mirrors the action's facility validation, og-image-url check,\n          pets/smoking tri-state and present-blank-clears SEO patch.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "旅宿物件 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "object",
                          "properties": {
                            "length": {
                              "type": "number",
                              "description": "Returns the length of a String object."
                            }
                          },
                          "required": [
                            "length"
                          ],
                          "description": "住宿館 id（prop_ 前綴）。"
                        },
                        "slug": {
                          "type": "string",
                          "description": "網址 slug（公開站路徑，租戶內唯一）。"
                        },
                        "name": {
                          "type": "string",
                          "description": "住宿館名稱。"
                        },
                        "kind": {
                          "type": "string",
                          "description": "類型：hotel 旅館 / camp 營地。"
                        },
                        "isOverseas": {
                          "type": "boolean",
                          "description": "是否為海外住宿。"
                        },
                        "location": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "地點描述；null = 未設。"
                        },
                        "description": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "簡介文字；null = 未設。"
                        },
                        "contentMdx": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "內文（MDX 原始碼）；null = 未設。"
                        },
                        "facilities": {
                          "description": "設施清單（JSON）；null = 未設。"
                        },
                        "coverImageUrl": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "封面圖 URL；null = 未設。"
                        },
                        "usageHint": {
                          "type": "string",
                          "description": "用途：direct 散客直訂 / package 梯次配套 / both 兩者皆可。"
                        },
                        "checkInTime": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "入住時間文字（如「15:00」）；null = 未設。"
                        },
                        "checkOutTime": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "退房時間文字（如「11:00」）；null = 未設。"
                        },
                        "checkInInfo": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "入住須知；null = 未設。"
                        },
                        "houseRules": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "館內規範；null = 未設。"
                        },
                        "cancellationPolicy": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "取消政策；null = 未設。"
                        },
                        "addressRegion": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "地址：縣市／區域；null = 未設。"
                        },
                        "addressLocality": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "地址：鄉鎮／地區；null = 未設。"
                        },
                        "streetAddress": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "街道地址；null = 未設。"
                        },
                        "postalCode": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "郵遞區號；null = 未設。"
                        },
                        "latitude": {
                          "type": [
                            "number",
                            "null"
                          ],
                          "description": "緯度；null = 未設。"
                        },
                        "longitude": {
                          "type": [
                            "number",
                            "null"
                          ],
                          "description": "經度；null = 未設。"
                        },
                        "phone": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "聯絡電話；null = 未設。"
                        },
                        "petsAllowed": {
                          "type": [
                            "boolean",
                            "null"
                          ],
                          "description": "是否允許攜帶寵物；null = 未設。"
                        },
                        "smokingAllowed": {
                          "type": [
                            "boolean",
                            "null"
                          ],
                          "description": "是否允許吸菸；null = 未設。"
                        },
                        "status": {
                          "type": "string",
                          "description": "狀態：active 啟用 / inactive 停用。"
                        },
                        "seoTitle": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "SEO 標題覆寫；null = 沿用內容欄。"
                        },
                        "seoDescription": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "SEO 描述；null = 未設。"
                        },
                        "ogImageUrl": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Open Graph 分享圖 URL；null = 未設。"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "建立時間。"
                        },
                        "updatedAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "最後更新時間。"
                        }
                      },
                      "required": [
                        "id",
                        "slug",
                        "name",
                        "kind",
                        "isOverseas",
                        "location",
                        "description",
                        "contentMdx",
                        "facilities",
                        "coverImageUrl",
                        "usageHint",
                        "checkInTime",
                        "checkOutTime",
                        "checkInInfo",
                        "houseRules",
                        "cancellationPolicy",
                        "addressRegion",
                        "addressLocality",
                        "streetAddress",
                        "postalCode",
                        "latitude",
                        "longitude",
                        "phone",
                        "petsAllowed",
                        "smokingAllowed",
                        "status",
                        "seoTitle",
                        "seoDescription",
                        "ogImageUrl",
                        "createdAt",
                        "updatedAt"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.read"
      },
      "patch": {
        "operationId": "patch_lodging_properties_id_",
        "tags": [
          "lodging"
        ],
        "summary": "update a property",
        "description": "/api/v1/lodging/properties/{id}\n  GET   — single lodging property. Missing → 404.\n  PATCH — update a property. Same core op + audit as `updatePropertyAction`;\n          gated `lodging.manage`. updateProperty writes its own audit log.\n          Mirrors the action's facility validation, og-image-url check,\n          pets/smoking tri-state and present-blank-clears SEO patch.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "旅宿物件 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.manage",
        "x-module": "lodging",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "旅宿名稱（對外顯示）（max 200 · min 1）"
                  },
                  "location": {
                    "type": "string",
                    "description": "所在地點概述（如縣市、區域）（max 200）"
                  },
                  "description": {
                    "type": "string",
                    "description": "旅宿介紹文字（max 2000）"
                  },
                  "usageHint": {
                    "type": "string",
                    "enum": [
                      "direct",
                      "package",
                      "both"
                    ],
                    "description": "銷售用途：direct 僅直接訂房／package 僅併入套裝行程／both 兩者皆可"
                  },
                  "checkInTime": {
                    "type": "string",
                    "description": "入住時間（如 15:00）（max 10）"
                  },
                  "checkOutTime": {
                    "type": "string",
                    "description": "退房時間（如 11:00）（max 10）"
                  },
                  "checkInInfo": {
                    "type": "string",
                    "description": "入住須知與報到說明（max 2000）"
                  },
                  "houseRules": {
                    "type": "string",
                    "description": "住宿規範（max 2000）"
                  },
                  "cancellationPolicy": {
                    "type": "string",
                    "description": "取消政策說明（max 2000）"
                  },
                  "addressRegion": {
                    "type": "string",
                    "description": "地址行政區（縣市層級）（max 50）"
                  },
                  "addressLocality": {
                    "type": "string",
                    "description": "地址鄉鎮市區（max 50）"
                  },
                  "streetAddress": {
                    "type": "string",
                    "description": "街道地址（max 200）"
                  },
                  "postalCode": {
                    "type": "string",
                    "description": "郵遞區號（max 10）"
                  },
                  "latitude": {
                    "type": "number",
                    "description": "緯度（-90 至 90）（max 90）"
                  },
                  "longitude": {
                    "type": "number",
                    "description": "經度（-180 至 180）（max 180）"
                  },
                  "phone": {
                    "type": "string",
                    "description": "聯絡電話（max 50）"
                  },
                  "petsAllowed": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "disallow",
                      "unset"
                    ],
                    "description": "是否允許攜帶寵物：allow 允許／disallow 不允許／unset 清除設定，省略則不變更"
                  },
                  "smokingAllowed": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "disallow",
                      "unset"
                    ],
                    "description": "是否允許吸菸：allow 允許／disallow 不允許／unset 清除設定，省略則不變更"
                  },
                  "facilities": {
                    "type": "array",
                    "items": {},
                    "description": "設施代碼陣列（須為合法 amenity key；送空陣列代表清空）"
                  },
                  "seoTitle": {
                    "type": "string",
                    "description": "SEO 標題（送空字串代表清空，退回預設）"
                  },
                  "seoDescription": {
                    "type": "string",
                    "description": "SEO 描述（送空字串代表清空，退回預設）"
                  },
                  "ogImageUrl": {
                    "type": "string",
                    "description": "社群分享圖 URL（須為 http/https，送空字串代表清空）"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/lodging/properties/{id}/archive": {
      "post": {
        "operationId": "post_lodging_properties_id_archive",
        "tags": [
          "lodging"
        ],
        "summary": "archive",
        "description": "POST /api/v1/lodging/properties/{id}/archive — archive (status→inactive) a\nproperty. Same core op + audit as `archivePropertyAction`; gated\n`lodging.manage`. archiveProperty writes its own audit log.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "旅宿物件 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.manage",
        "x-module": "lodging"
      }
    },
    "/lodging/properties/{id}/images": {
      "get": {
        "operationId": "get_lodging_properties_id_images",
        "tags": [
          "lodging"
        ],
        "summary": "property gallery images.",
        "description": "/api/v1/lodging/properties/{id}/images\n  GET  — property gallery images.\n  POST — add a property gallery image. Same core op as `addPropertyImageAction`;\n         gated `lodging.manage`. NOTE: addPropertyImage writes NO audit log —\n         faithfully mirroring the action, which also writes none.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "旅宿物件 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "圖片資源 id（pimg_ / rtimg_ 前綴）。"
                          },
                          "url": {
                            "type": "string",
                            "description": "圖片公開 URL。"
                          },
                          "caption": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "圖說文字；null = 無。"
                          },
                          "displayOrder": {
                            "type": "number",
                            "description": "相簿中的排序（由小到大）。"
                          }
                        },
                        "required": [
                          "id",
                          "url",
                          "caption",
                          "displayOrder"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.read",
        "x-module": "lodging"
      },
      "post": {
        "operationId": "post_lodging_properties_id_images",
        "tags": [
          "lodging"
        ],
        "summary": "add a property gallery image",
        "description": "/api/v1/lodging/properties/{id}/images\n  GET  — property gallery images.\n  POST — add a property gallery image. Same core op as `addPropertyImageAction`;\n         gated `lodging.manage`. NOTE: addPropertyImage writes NO audit log —\n         faithfully mirroring the action, which also writes none.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "旅宿物件 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立住宿館圖片的 id（pimg_ 前綴）。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.manage",
        "x-module": "lodging",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "圖片網址（min 1）"
                  },
                  "caption": {
                    "type": "string",
                    "description": "圖片說明文字（可省略）"
                  },
                  "displayOrder": {
                    "type": "number",
                    "description": "在相簿中的排序序號，數字越小越前面，預設 0"
                  }
                },
                "required": [
                  "url"
                ]
              }
            }
          }
        }
      }
    },
    "/lodging/properties/{id}/room-types": {
      "get": {
        "operationId": "get_lodging_properties_id_room_types",
        "tags": [
          "lodging"
        ],
        "summary": "room types for one property",
        "description": "/api/v1/lodging/properties/{id}/room-types\n  GET  — room types for one property (tenant-wide read).\n  POST — create a room type under this property. Same core op + audit as\n         `createRoomTypeAction`; gated `lodging.manage`. createRoomType writes\n         its own audit log. Mirrors the action's bedConfig (single bed type\n         for MVP) + facility validation.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "旅宿物件 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "object",
                            "properties": {
                              "length": {
                                "type": "number",
                                "description": "Returns the length of a String object."
                              }
                            },
                            "required": [
                              "length"
                            ],
                            "description": "房型 id（rt_ 前綴）。"
                          },
                          "propertyId": {
                            "type": "object",
                            "properties": {
                              "length": {
                                "type": "number",
                                "description": "Returns the length of a String object."
                              }
                            },
                            "required": [
                              "length"
                            ],
                            "description": "所屬住宿館 id（prop_ 前綴）。"
                          },
                          "name": {
                            "type": "string",
                            "description": "房型名稱。"
                          },
                          "inventoryUnit": {
                            "type": "string",
                            "description": "庫存單位：room 以房計 / bed 以床位計。"
                          },
                          "unitsTotal": {
                            "type": "number",
                            "description": "總庫存量（房間數或床位數）。"
                          },
                          "capacityPerUnit": {
                            "type": "number",
                            "description": "每單位可住人數。"
                          },
                          "basePriceTwd": {
                            "type": "number",
                            "description": "底價（TWD 整數，每晚每單位；可被逐晚覆寫）。"
                          },
                          "description": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "房型描述；null = 未設。"
                          },
                          "facilities": {
                            "description": "設施清單（JSON）；null = 未設。"
                          },
                          "bedConfig": {
                            "description": "床型配置（JSON）；null = 未設。"
                          },
                          "floorSizeSqm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "房間坪數（平方公尺）；null = 未設。"
                          },
                          "status": {
                            "type": "string",
                            "description": "狀態：active 啟用 / inactive 停用。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          }
                        },
                        "required": [
                          "id",
                          "propertyId",
                          "name",
                          "inventoryUnit",
                          "unitsTotal",
                          "capacityPerUnit",
                          "basePriceTwd",
                          "description",
                          "facilities",
                          "bedConfig",
                          "floorSizeSqm",
                          "status",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.read"
      },
      "post": {
        "operationId": "post_lodging_properties_id_room_types",
        "tags": [
          "lodging"
        ],
        "summary": "create a room type under this property",
        "description": "/api/v1/lodging/properties/{id}/room-types\n  GET  — room types for one property (tenant-wide read).\n  POST — create a room type under this property. Same core op + audit as\n         `createRoomTypeAction`; gated `lodging.manage`. createRoomType writes\n         its own audit log. Mirrors the action's bedConfig (single bed type\n         for MVP) + facility validation.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "所屬旅宿物件 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立房型的 id（rt_ 前綴）。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.manage",
        "x-module": "lodging",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "房型名稱（如標準雙人房）（max 200 · min 1）"
                  },
                  "inventoryUnit": {
                    "type": "string",
                    "enum": [
                      "room",
                      "bed"
                    ],
                    "description": "庫存單位：room 以房計／bed 以床位計，預設 room"
                  },
                  "unitsTotal": {
                    "type": "number",
                    "description": "此房型可售總單元數（房數或床位數）（max 10000 · min 1）"
                  },
                  "capacityPerUnit": {
                    "type": "number",
                    "description": "每單元可容納人數，預設 1（max 100 · min 1）"
                  },
                  "basePriceTwd": {
                    "type": "number",
                    "description": "每晚每單元基準售價（新台幣）（max 10000000 · min 0）"
                  },
                  "description": {
                    "type": "string",
                    "description": "房型介紹文字（max 2000）"
                  },
                  "floorSizeSqm": {
                    "type": "number",
                    "description": "房間坪數（平方公尺）"
                  },
                  "bedType": {
                    "type": "string",
                    "description": "床型代碼（須為合法 bed type，搭配 bedCount 才生效）"
                  },
                  "bedCount": {
                    "type": "number",
                    "description": "該床型數量（須大於 0 才生效）"
                  },
                  "facilities": {
                    "type": "array",
                    "items": {},
                    "description": "房型設施代碼陣列（須為合法 amenity key）"
                  }
                },
                "required": [
                  "name",
                  "unitsTotal",
                  "basePriceTwd"
                ]
              }
            }
          }
        }
      }
    },
    "/lodging/room-types/{id}": {
      "get": {
        "operationId": "get_lodging_room_types_id_",
        "tags": [
          "lodging"
        ],
        "summary": "single room type",
        "description": "/api/v1/lodging/room-types/{id}\n  GET   — single room type. Missing → 404.\n  PATCH — update a room type. Same core op + audit as `updateRoomTypeAction`;\n          gated `lodging.manage`. updateRoomType writes its own audit log.\n          Mirrors bedConfig (single bed type, MVP) + facility validation; a\n          sent `facilities` array of [] means \"clear\", as in the action.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "房型 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "object",
                          "properties": {
                            "length": {
                              "type": "number",
                              "description": "Returns the length of a String object."
                            }
                          },
                          "required": [
                            "length"
                          ],
                          "description": "房型 id（rt_ 前綴）。"
                        },
                        "propertyId": {
                          "type": "object",
                          "properties": {
                            "length": {
                              "type": "number",
                              "description": "Returns the length of a String object."
                            }
                          },
                          "required": [
                            "length"
                          ],
                          "description": "所屬住宿館 id（prop_ 前綴）。"
                        },
                        "name": {
                          "type": "string",
                          "description": "房型名稱。"
                        },
                        "inventoryUnit": {
                          "type": "string",
                          "description": "庫存單位：room 以房計 / bed 以床位計。"
                        },
                        "unitsTotal": {
                          "type": "number",
                          "description": "總庫存量（房間數或床位數）。"
                        },
                        "capacityPerUnit": {
                          "type": "number",
                          "description": "每單位可住人數。"
                        },
                        "basePriceTwd": {
                          "type": "number",
                          "description": "底價（TWD 整數，每晚每單位；可被逐晚覆寫）。"
                        },
                        "description": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "房型描述；null = 未設。"
                        },
                        "facilities": {
                          "description": "設施清單（JSON）；null = 未設。"
                        },
                        "bedConfig": {
                          "description": "床型配置（JSON）；null = 未設。"
                        },
                        "floorSizeSqm": {
                          "type": [
                            "number",
                            "null"
                          ],
                          "description": "房間坪數（平方公尺）；null = 未設。"
                        },
                        "status": {
                          "type": "string",
                          "description": "狀態：active 啟用 / inactive 停用。"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "建立時間。"
                        },
                        "updatedAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "最後更新時間。"
                        }
                      },
                      "required": [
                        "id",
                        "propertyId",
                        "name",
                        "inventoryUnit",
                        "unitsTotal",
                        "capacityPerUnit",
                        "basePriceTwd",
                        "description",
                        "facilities",
                        "bedConfig",
                        "floorSizeSqm",
                        "status",
                        "createdAt",
                        "updatedAt"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.read"
      },
      "patch": {
        "operationId": "patch_lodging_room_types_id_",
        "tags": [
          "lodging"
        ],
        "summary": "update a room type",
        "description": "/api/v1/lodging/room-types/{id}\n  GET   — single room type. Missing → 404.\n  PATCH — update a room type. Same core op + audit as `updateRoomTypeAction`;\n          gated `lodging.manage`. updateRoomType writes its own audit log.\n          Mirrors bedConfig (single bed type, MVP) + facility validation; a\n          sent `facilities` array of [] means \"clear\", as in the action.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "房型 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.manage",
        "x-module": "lodging",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "房型名稱（如標準雙人房）（max 200 · min 1）"
                  },
                  "inventoryUnit": {
                    "type": "string",
                    "enum": [
                      "room",
                      "bed"
                    ],
                    "description": "庫存單位：room 以房計／bed 以床位計"
                  },
                  "unitsTotal": {
                    "type": "number",
                    "description": "此房型可售總單元數（房數或床位數）（max 10000 · min 1）"
                  },
                  "capacityPerUnit": {
                    "type": "number",
                    "description": "每單元可容納人數（max 100 · min 1）"
                  },
                  "basePriceTwd": {
                    "type": "number",
                    "description": "每晚每單元基準售價（新台幣）（max 10000000 · min 0）"
                  },
                  "description": {
                    "type": "string",
                    "description": "房型介紹文字（max 2000）"
                  },
                  "floorSizeSqm": {
                    "type": "number",
                    "description": "房間坪數（平方公尺）"
                  },
                  "bedType": {
                    "type": "string",
                    "description": "床型代碼（須為合法 bed type，搭配 bedCount 才生效）"
                  },
                  "bedCount": {
                    "type": "number",
                    "description": "該床型數量（須大於 0 才生效）"
                  },
                  "facilities": {
                    "type": "array",
                    "items": {},
                    "description": "房型設施代碼陣列（須為合法 amenity key；送空陣列代表清空）"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/lodging/room-types/{id}/archive": {
      "post": {
        "operationId": "post_lodging_room_types_id_archive",
        "tags": [
          "lodging"
        ],
        "summary": "archive",
        "description": "POST /api/v1/lodging/room-types/{id}/archive — archive (status→inactive) a\nroom type. Same core op + audit as `archiveRoomTypeAction`; gated\n`lodging.manage`. archiveRoomType writes its own audit log.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "房型 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.manage",
        "x-module": "lodging"
      }
    },
    "/lodging/room-types/{id}/availability": {
      "get": {
        "operationId": "get_lodging_room_types_id_availability",
        "tags": [
          "lodging"
        ],
        "summary": "per-night availability +",
        "description": "GET /api/v1/lodging/room-types/{id}/availability — per-night availability +\npricing for a stay range. Boundary is [checkIn, checkOut) (the last night is\nexclusive, matching the booking calendar). Both dates required.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "房型 ID（min 1）"
            }
          },
          {
            "name": "checkIn",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "入住日（YYYY-MM-DD，含此晚）（min 1）"
            }
          },
          {
            "name": "checkOut",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "退房日（YYYY-MM-DD，不含此晚）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "available": {
                          "type": "number",
                          "description": "整段住宿期間可訂房間數（各晚剩餘取最小；任一晚關閉則為 0）。"
                        },
                        "nights": {
                          "type": "number",
                          "description": "住宿晚數。"
                        },
                        "totalPriceTwd": {
                          "type": "number",
                          "description": "整段期間房價合計（TWD 整數，逐晚牌價加總）。"
                        },
                        "perNight": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "night": {
                                "type": "string",
                                "description": "該晚日期（ISO 'YYYY-MM-DD'）。"
                              },
                              "capacity": {
                                "type": "number",
                                "description": "該晚可售容量（房間數；有覆寫則用覆寫值，否則房型總數）。"
                              },
                              "booked": {
                                "type": "number",
                                "description": "該晚已訂數。"
                              },
                              "remaining": {
                                "type": "number",
                                "description": "該晚剩餘可訂數（capacity − booked，不小於 0）。"
                              },
                              "priceTwd": {
                                "type": "number",
                                "description": "該晚房價（TWD 整數；有逐晚覆寫則用覆寫值，否則房型底價）。"
                              },
                              "status": {
                                "type": "string",
                                "description": "該晚販售狀態：open 開放 / closed 關閉。"
                              }
                            },
                            "required": [
                              "night",
                              "capacity",
                              "booked",
                              "remaining",
                              "priceTwd",
                              "status"
                            ]
                          },
                          "description": "逐晚可售明細。"
                        }
                      },
                      "required": [
                        "available",
                        "nights",
                        "totalPriceTwd",
                        "perNight"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.read"
      }
    },
    "/lodging/room-types/{id}/availability/breakdown": {
      "get": {
        "operationId": "get_lodging_room_types_id_availability_breakdown",
        "tags": [
          "lodging"
        ],
        "summary": "per-night",
        "description": "GET /api/v1/lodging/room-types/{id}/availability/breakdown — per-night\nbooked-units split by source (direct vs package) over [from, to). Both dates\nrequired.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "房型 ID（min 1）"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "起始日（YYYY-MM-DD，含此晚）（min 1）"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "結束日（YYYY-MM-DD，不含此晚）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "night": {
                            "type": "string",
                            "description": "該晚日期（ISO 'YYYY-MM-DD'）。"
                          },
                          "directBooked": {
                            "type": "number",
                            "description": "該晚散客直訂的已訂數。"
                          },
                          "packageBooked": {
                            "type": "number",
                            "description": "該晚梯次配套佔用的已訂數。"
                          }
                        },
                        "required": [
                          "night",
                          "directBooked",
                          "packageBooked"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.read"
      }
    },
    "/lodging/room-types/{id}/images": {
      "get": {
        "operationId": "get_lodging_room_types_id_images",
        "tags": [
          "lodging"
        ],
        "summary": "room-type gallery images.",
        "description": "/api/v1/lodging/room-types/{id}/images\n  GET  — room-type gallery images.\n  POST — add a room-type gallery image. Same core op as `addRoomTypeImageAction`;\n         gated `lodging.manage`. NOTE: addRoomTypeImage writes NO audit log —\n         faithfully mirroring the action, which also writes none.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "房型 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "圖片資源 id（pimg_ / rtimg_ 前綴）。"
                          },
                          "url": {
                            "type": "string",
                            "description": "圖片公開 URL。"
                          },
                          "caption": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "圖說文字；null = 無。"
                          },
                          "displayOrder": {
                            "type": "number",
                            "description": "相簿中的排序（由小到大）。"
                          }
                        },
                        "required": [
                          "id",
                          "url",
                          "caption",
                          "displayOrder"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.read",
        "x-module": "lodging"
      },
      "post": {
        "operationId": "post_lodging_room_types_id_images",
        "tags": [
          "lodging"
        ],
        "summary": "add a room-type gallery image",
        "description": "/api/v1/lodging/room-types/{id}/images\n  GET  — room-type gallery images.\n  POST — add a room-type gallery image. Same core op as `addRoomTypeImageAction`;\n         gated `lodging.manage`. NOTE: addRoomTypeImage writes NO audit log —\n         faithfully mirroring the action, which also writes none.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "房型 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立房型圖片的 id（rtimg_ 前綴）。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.manage",
        "x-module": "lodging",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "圖片網址（min 1）"
                  },
                  "caption": {
                    "type": "string",
                    "description": "圖片說明文字（可省略）"
                  },
                  "displayOrder": {
                    "type": "number",
                    "description": "在相簿中的排序序號，數字越小越前面，預設 0"
                  }
                },
                "required": [
                  "url"
                ]
              }
            }
          }
        }
      }
    },
    "/lodging/room-types/{id}/nights/override": {
      "post": {
        "operationId": "post_lodging_room_types_id_nights_override",
        "tags": [
          "lodging"
        ],
        "summary": "batch-override the",
        "description": "POST /api/v1/lodging/room-types/{id}/nights/override — batch-override the\nprice / capacity / closed flag for every night in an inclusive [from, to]\nrange. Same core op + audit as `setNightlyOverrideAction`; gated\n`lodging.manage`. setNightlyOverride writes its own audit log. A capacity\nlowered below an already-booked night → 409 conflict (mirrors the action's\nActionError).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "房型 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.manage",
        "x-module": "lodging",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "from": {
                    "type": "string",
                    "description": "套用起始日（YYYY-MM-DD，含此日）"
                  },
                  "to": {
                    "type": "string",
                    "description": "套用結束日（YYYY-MM-DD，含此日；須不早於起始日）"
                  },
                  "priceTwd": {
                    "type": "number",
                    "description": "覆寫的每晚售價（新台幣），省略則不調整價格（max 10000000 · min 0）"
                  },
                  "capacity": {
                    "type": "number",
                    "description": "覆寫的每晚可售單元數，若低於已訂數量會回 409 衝突（max 10000 · min 1）"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "open",
                      "closed"
                    ],
                    "description": "每晚開關房狀態：open 開放／closed 封房"
                  }
                },
                "required": [
                  "from",
                  "to"
                ]
              }
            }
          }
        }
      }
    },
    "/lodging/stats": {
      "get": {
        "operationId": "get_lodging_stats",
        "tags": [
          "lodging"
        ],
        "summary": "旅宿 dashboard overview",
        "description": "GET /api/v1/lodging/stats — 旅宿 dashboard overview (tonight check-ins, next-7\noccupancy/availability, pending-payment counts). Tenant-wide read.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "tonightCheckInUnits": {
                          "type": "number",
                          "description": "今晚入住房間數（Asia/Taipei）。"
                        },
                        "tonightCheckInGuests": {
                          "type": "number",
                          "description": "今晚入住總人數（Asia/Taipei）。"
                        },
                        "weekOccupancyPct": {
                          "type": "number",
                          "description": "未來 7 晚住房率（已訂 / 可售，0–100）。"
                        },
                        "next7AvailableUnits": {
                          "type": "number",
                          "description": "未來 7 晚仍可售的房晚數。"
                        },
                        "pendingPaymentCount": {
                          "type": "number",
                          "description": "待收款訂單筆數。"
                        },
                        "pendingPaymentTwd": {
                          "type": "number",
                          "description": "待收款金額合計（TWD 整數）。"
                        }
                      },
                      "required": [
                        "tonightCheckInUnits",
                        "tonightCheckInGuests",
                        "weekOccupancyPct",
                        "next7AvailableUnits",
                        "pendingPaymentCount",
                        "pendingPaymentTwd"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lodging.read"
      }
    },
    "/members": {
      "get": {
        "operationId": "get_members",
        "tags": [
          "members"
        ],
        "summary": "list/search the tenant customer",
        "description": "GET /api/v1/members — list/search the tenant customer (\"member\") directory\n(the /admin/members table over HTTP). Members = customers only; staff\naccounts are excluded by the core repo (CUSTOMER_ONLY). Tenant-wide read, no\nowner-scope. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "關鍵字，模糊比對會員姓名、Email 或電話"
            }
          },
          {
            "name": "county",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "縣市篩選，僅回傳通訊地址在該縣市的會員"
            }
          },
          {
            "name": "year",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "加入年份（西元四位數），僅回傳該年註冊的會員（格式限定）"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "分頁頁碼，從 1 起算，預設第 1 頁"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "每頁筆數，上限 200，預設由後端決定（max 200）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "userId": {
                                "type": "string",
                                "description": "會員（顧客）的 user id。"
                              },
                              "email": {
                                "type": "string",
                                "description": "會員 Email（登入帳號）。"
                              },
                              "name": {
                                "type": "string",
                                "description": "會員姓名。"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "會員註冊時間。"
                              },
                              "phone": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "聯絡電話（未填 → null）。"
                              },
                              "address": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "通訊地址（未填 → null）。"
                              },
                              "birthDate": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "生日 YYYY-MM-DD（未填 → null）。"
                              },
                              "orderCount": {
                                "type": "number",
                                "description": "累計訂單數（含所有狀態與 kind）。"
                              },
                              "paidOrderCount": {
                                "type": "number",
                                "description": "已付清 / 已完成的訂單數（payment_state in paid/overpaid 或 booking_state=completed）。"
                              },
                              "totalSpent": {
                                "type": "number",
                                "description": "累計消費（上述已付清訂單的應收總額，TWD 整數）。"
                              },
                              "lastOrderAt": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "format": "date-time",
                                "description": "最後一筆訂單建立時間（無訂單 → null）。"
                              },
                              "pdpaSignedAt": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "format": "date-time",
                                "description": "最新版 PDPA 同意書簽署時間（未簽 → null）。"
                              },
                              "anonymizedAt": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "format": "date-time",
                                "description": "PDPA 匿名化時間；非空 = 已匿名化。"
                              }
                            },
                            "required": [
                              "userId",
                              "email",
                              "name",
                              "createdAt",
                              "phone",
                              "address",
                              "birthDate",
                              "orderCount",
                              "paidOrderCount",
                              "totalSpent",
                              "lastOrderAt",
                              "pdpaSignedAt",
                              "anonymizedAt"
                            ]
                          },
                          "description": "當前頁的會員列。"
                        },
                        "total": {
                          "type": "number",
                          "description": "符合篩選的會員總數。"
                        },
                        "page": {
                          "type": "number",
                          "description": "當前頁碼（從 1 起算）。"
                        },
                        "pageSize": {
                          "type": "number",
                          "description": "每頁筆數。"
                        }
                      },
                      "required": [
                        "rows",
                        "total",
                        "page",
                        "pageSize"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "member.read"
      }
    },
    "/members/{id}": {
      "get": {
        "operationId": "get_members_id_",
        "tags": [
          "members"
        ],
        "summary": "full member detail",
        "description": "GET /api/v1/members/{id} — full member detail (profile rollup + recent orders\n+ signed PDPA consents) for one customer userId. Missing → 404 (avoids\nleaking existence). Traveler PII is intentionally NOT included here — it lives\nbehind order.read on the order detail surface.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "會員（顧客）的使用者 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "profile": {
                          "type": "object",
                          "properties": {
                            "userId": {
                              "type": "string",
                              "description": "會員（顧客）的 user id。"
                            },
                            "email": {
                              "type": "string",
                              "description": "會員 Email（登入帳號）。"
                            },
                            "name": {
                              "type": "string",
                              "description": "會員姓名。"
                            },
                            "createdAt": {
                              "type": "string",
                              "format": "date-time",
                              "description": "會員註冊時間。"
                            },
                            "phone": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "聯絡電話（未填 → null）。"
                            },
                            "address": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "通訊地址（未填 → null）。"
                            },
                            "birthDate": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "生日 YYYY-MM-DD（未填 → null）。"
                            },
                            "orderCount": {
                              "type": "number",
                              "description": "累計訂單數（含所有狀態與 kind）。"
                            },
                            "paidOrderCount": {
                              "type": "number",
                              "description": "已付清 / 已完成的訂單數（payment_state in paid/overpaid 或 booking_state=completed）。"
                            },
                            "totalSpent": {
                              "type": "number",
                              "description": "累計消費（上述已付清訂單的應收總額，TWD 整數）。"
                            },
                            "lastOrderAt": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "format": "date-time",
                              "description": "最後一筆訂單建立時間（無訂單 → null）。"
                            },
                            "pdpaSignedAt": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "format": "date-time",
                              "description": "最新版 PDPA 同意書簽署時間（未簽 → null）。"
                            },
                            "anonymizedAt": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "format": "date-time",
                              "description": "PDPA 匿名化時間；非空 = 已匿名化。"
                            }
                          },
                          "required": [
                            "userId",
                            "email",
                            "name",
                            "createdAt",
                            "phone",
                            "address",
                            "birthDate",
                            "orderCount",
                            "paidOrderCount",
                            "totalSpent",
                            "lastOrderAt",
                            "pdpaSignedAt",
                            "anonymizedAt"
                          ],
                          "description": "會員基本資料 + 訂單彙整。"
                        },
                        "orders": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "訂單 id。"
                              },
                              "orderNumber": {
                                "type": "string",
                                "description": "人類可讀訂單編號。"
                              },
                              "status": {
                                "type": "string",
                                "description": "金流模型 v2：deriveOrderDisplayStatus(booking/payment/refund) 派生的單一顯示狀態。"
                              },
                              "total": {
                                "type": "number",
                                "description": "該會員所有訂單的應收總額（TWD 整數）。"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "訂單建立時間。"
                              },
                              "tripTitle": {
                                "type": "string",
                                "description": "行程 / 產品標題。"
                              }
                            },
                            "required": [
                              "id",
                              "orderNumber",
                              "status",
                              "total",
                              "createdAt",
                              "tripTitle"
                            ]
                          },
                          "description": "近期訂單列表（上限 50 筆，含 lodging）。"
                        },
                        "consents": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "簽署紀錄 id。"
                              },
                              "kind": {
                                "type": "string",
                                "description": "同意書類型（pdpa / tour_agreement / cancellation_policy / refund_policy）。"
                              },
                              "version": {
                                "type": "number",
                                "description": "簽署當下的範本版本號。"
                              },
                              "signedAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "簽署時間。"
                              },
                              "ipAddress": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "簽署時來源 IP（未記錄 → null）。"
                              }
                            },
                            "required": [
                              "id",
                              "kind",
                              "version",
                              "signedAt",
                              "ipAddress"
                            ]
                          },
                          "description": "已簽署的同意書紀錄（上限 50 筆）。"
                        }
                      },
                      "required": [
                        "profile",
                        "orders",
                        "consents"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "member.read"
      }
    },
    "/members/{id}/anonymize": {
      "post": {
        "operationId": "post_members_id_anonymize",
        "tags": [
          "members"
        ],
        "summary": "irreversible PDPA anonymization of one",
        "description": "POST /api/v1/members/{id}/anonymize — irreversible PDPA anonymization of one\nmember (customer) account. Thin wrap of the canonical `anonymizeMember`\nservice with `source:'admin'`: it scrubs PII, bans the login, revokes\ncredentials, and writes its OWN `member.anonymize` audit row inside the same\ntx (so the route does NOT replicate writeAuditLog). Mirrors\n`anonymizeMemberAction` (apps/web/src/app/(admin)/admin/members/[id]/actions.ts):\nsame `member.update` gate, same core fn + args, same reason→message mapping.\n`source:'admin'` deliberately bypasses the active-order guard (ops judgement);\nthe service records any open-order count into the audit metadata.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "欲匿名化的會員（顧客）使用者 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：會員個資已匿名化（PDPA 刪除權）。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "member.update",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "description": "匿名化原因，記入稽核紀錄備查"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/members/expiry-warnings": {
      "get": {
        "operationId": "get_members_expiry_warnings",
        "tags": [
          "members"
        ],
        "summary": "given a batch of member",
        "description": "GET /api/v1/members/expiry-warnings?ids=u1,u2,… — given a batch of member\nuserIds, return the subset whose travelers on active upcoming departures have\na passport expiring within the tenant's warning threshold. Designed to\ndecorate an already-fetched member page; the id batch is capped to bound URL\nlength / query cost. Core returns a Set — serialised here as a string[].",
        "parameters": [
          {
            "name": "ids",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "以逗號分隔的會員使用者 ID 批次，上限 200 個，回傳其中護照即將到期者"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "userIds": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "證件即將到期（或已過期）需提醒的會員 user id 清單。"
                        }
                      },
                      "required": [
                        "userIds"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "member.read"
      }
    },
    "/members/stats": {
      "get": {
        "operationId": "get_members_stats",
        "tags": [
          "members"
        ],
        "summary": "member directory KPI cards",
        "description": "GET /api/v1/members/stats — member directory KPI cards (total / new this\nmonth / with orders / average orders). Tenant-wide, no owner-scope.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "totalMembers": {
                          "type": "number",
                          "description": "會員（顧客）總數（排除員工帳號）。"
                        },
                        "newThisMonth": {
                          "type": "number",
                          "description": "本月新註冊會員數。"
                        },
                        "withOrders": {
                          "type": "number",
                          "description": "有下過訂單的會員數。"
                        },
                        "averageOrders": {
                          "type": "number",
                          "description": "平均訂單數（只計有訂單者，避免零訂單稀釋）。"
                        }
                      },
                      "required": [
                        "totalMembers",
                        "newThisMonth",
                        "withOrders",
                        "averageOrders"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "member.read"
      }
    },
    "/message-templates": {
      "get": {
        "operationId": "get_message_templates",
        "tags": [
          "message-templates"
        ],
        "summary": "list canned message templates",
        "description": "GET /api/v1/message-templates — list canned message templates (the\n/admin/message-templates table over HTTP). Optional `channel` filter\n(line|email). Tenant-wide (no owner-scope). Mirrors the back-office read;\nsame `message_template.read` chokepoint. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "line",
                "email"
              ],
              "description": "依發送管道篩選範本（line 或 email）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "範本 ID。"
                          },
                          "key": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "穩定識別碼（NULL = 未指定）。"
                          },
                          "stage": {
                            "type": "string",
                            "enum": [
                              "受理",
                              "審核不通過",
                              "未成團通知",
                              "中籤通知",
                              "行前說明",
                              "收尾款",
                              "訂餐調查",
                              "裝備調查",
                              "出團完成"
                            ],
                            "description": "SOP 階段（受理 → 出團完成）。"
                          },
                          "channel": {
                            "type": "string",
                            "enum": [
                              "email",
                              "line"
                            ],
                            "description": "發送管道：line 或 email。"
                          },
                          "title": {
                            "type": "string",
                            "description": "範本標題。"
                          },
                          "bodySingle": {
                            "type": "string",
                            "description": "單人版內文（含 {{...}} 合併變數）。"
                          },
                          "bodyMulti": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "多人版變體；NULL = 只有單人版。"
                          },
                          "isActive": {
                            "type": "boolean",
                            "description": "是否為該階段目前啟用的範本。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          },
                          "updatedBy": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "最後更新者姓名（LEFT JOIN 同庫 user；未知 / 帳號已刪為 null）。"
                          }
                        },
                        "required": [
                          "id",
                          "key",
                          "stage",
                          "channel",
                          "title",
                          "bodySingle",
                          "bodyMulti",
                          "isActive",
                          "createdAt",
                          "updatedAt",
                          "updatedBy"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "message_template.read"
      },
      "post": {
        "operationId": "post_message_templates",
        "tags": [
          "message-templates"
        ],
        "description": "GET /api/v1/message-templates — list canned message templates (the\n/admin/message-templates table over HTTP). Optional `channel` filter\n(line|email). Tenant-wide (no owner-scope). Mirrors the back-office read;\nsame `message_template.read` chokepoint. See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立的訊息範本 ID。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "message_template.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "key": {
                    "type": "string",
                    "description": "範本識別碼，2–64 碼大寫英數 / _ / -（用於程式化引用，選填，自動轉大寫）"
                  },
                  "stage": {
                    "type": "string",
                    "description": "訊息對應的 SOP 階段"
                  },
                  "channel": {
                    "type": "string",
                    "description": "發送管道（line 或 email）"
                  },
                  "title": {
                    "type": "string",
                    "description": "範本標題（供後台辨識）（max 200 · min 1）"
                  },
                  "bodySingle": {
                    "type": "string",
                    "description": "單人版訊息內文（max 5000 · min 1）"
                  },
                  "bodyMulti": {
                    "type": "string",
                    "description": "多人版訊息內文（留空表示沿用單人版；選填）（max 5000）"
                  },
                  "isActive": {
                    "type": "boolean",
                    "description": "是否啟用（停用後不出現在可選範本中）"
                  }
                },
                "required": [
                  "stage",
                  "channel",
                  "title",
                  "bodySingle"
                ]
              }
            }
          }
        }
      }
    },
    "/message-templates/{id}": {
      "get": {
        "operationId": "get_message_templates_id_",
        "tags": [
          "message-templates"
        ],
        "summary": "single canned message template detail.",
        "description": "GET /api/v1/message-templates/{id} — single canned message template detail.\nTenant-wide (no owner-scope); missing → 404. Same `message_template.read`\nchokepoint as the back office. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訊息範本 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "範本 ID。"
                        },
                        "key": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "穩定識別碼（NULL = 未指定）。"
                        },
                        "stage": {
                          "type": "string",
                          "enum": [
                            "受理",
                            "審核不通過",
                            "未成團通知",
                            "中籤通知",
                            "行前說明",
                            "收尾款",
                            "訂餐調查",
                            "裝備調查",
                            "出團完成"
                          ],
                          "description": "SOP 階段（受理 → 出團完成）。"
                        },
                        "channel": {
                          "type": "string",
                          "enum": [
                            "email",
                            "line"
                          ],
                          "description": "發送管道：line 或 email。"
                        },
                        "title": {
                          "type": "string",
                          "description": "範本標題。"
                        },
                        "bodySingle": {
                          "type": "string",
                          "description": "單人版內文（含 {{...}} 合併變數）。"
                        },
                        "bodyMulti": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "多人版變體；NULL = 只有單人版。"
                        },
                        "isActive": {
                          "type": "boolean",
                          "description": "是否為該階段目前啟用的範本。"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "建立時間。"
                        },
                        "updatedAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "最後更新時間。"
                        },
                        "updatedBy": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "最後更新者姓名（LEFT JOIN 同庫 user；未知 / 帳號已刪為 null）。"
                        }
                      },
                      "required": [
                        "id",
                        "key",
                        "stage",
                        "channel",
                        "title",
                        "bodySingle",
                        "bodyMulti",
                        "isActive",
                        "createdAt",
                        "updatedAt",
                        "updatedBy"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "message_template.read"
      },
      "patch": {
        "operationId": "patch_message_templates_id_",
        "tags": [
          "message-templates"
        ],
        "description": "GET /api/v1/message-templates/{id} — single canned message template detail.\nTenant-wide (no owner-scope); missing → 404. Same `message_template.read`\nchokepoint as the back office. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "要更新的訊息範本 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功更新訊息範本。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "message_template.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "key": {
                    "type": "string",
                    "description": "範本識別碼，2–64 碼大寫英數 / _ / -（用於程式化引用，選填，自動轉大寫）"
                  },
                  "stage": {
                    "type": "string",
                    "description": "訊息對應的 SOP 階段"
                  },
                  "channel": {
                    "type": "string",
                    "description": "發送管道（line 或 email）"
                  },
                  "title": {
                    "type": "string",
                    "description": "範本標題（供後台辨識）（max 200 · min 1）"
                  },
                  "bodySingle": {
                    "type": "string",
                    "description": "單人版訊息內文（max 5000 · min 1）"
                  },
                  "bodyMulti": {
                    "type": "string",
                    "description": "多人版訊息內文（留空表示沿用單人版；選填）（max 5000）"
                  },
                  "isActive": {
                    "type": "boolean",
                    "description": "是否啟用（停用後不出現在可選範本中）"
                  }
                },
                "required": [
                  "stage",
                  "channel",
                  "title",
                  "bodySingle"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_message_templates_id_",
        "tags": [
          "message-templates"
        ],
        "description": "GET /api/v1/message-templates/{id} — single canned message template detail.\nTenant-wide (no owner-scope); missing → 404. Same `message_template.read`\nchokepoint as the back office. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訊息範本 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功刪除訊息範本。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "message_template.manage"
      }
    },
    "/message-templates/{id}/active": {
      "post": {
        "operationId": "post_message_templates_id_active",
        "tags": [
          "message-templates"
        ],
        "summary": "enable / disable",
        "description": "POST /api/v1/message-templates/{id}/active — enable / disable (soft-delete) a\ncanned message template. Mirrors setMessageTemplateActiveAction: same\n`message_template.manage` chokepoint, same core fn + args, same audit log.\nNOT_FOUND → 404. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "要啟用 / 停用的訊息範本 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功切換訊息範本的啟用狀態。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "message_template.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "isActive": {
                    "type": "boolean",
                    "description": "true 啟用、false 停用（軟刪除）此範本"
                  }
                },
                "required": [
                  "isActive"
                ]
              }
            }
          }
        }
      }
    },
    "/orders": {
      "get": {
        "operationId": "get_orders",
        "tags": [
          "orders"
        ],
        "summary": "list/search/filter orders",
        "description": "GET /api/v1/orders — list/search/filter orders (the /admin/orders table over\nHTTP). Owner-scope is ALWAYS re-derived server-side from the bearer user's\nrole (deriveOrderScope) — never trusted from the client — so sales tokens see\nonly their own orders, identical to the back office. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依訂單顯示狀態篩選（如 pending、paid、cancelled）"
            }
          },
          {
            "name": "assignment",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依派發狀態篩選（如 unassigned、assigned）"
            }
          },
          {
            "name": "rooming",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依分房狀態篩選"
            }
          },
          {
            "name": "dateFrom",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "出發日期區間起（格式 YYYY-MM-DD，含當日）"
            }
          },
          {
            "name": "dateTo",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "出發日期區間迄（格式 YYYY-MM-DD，含當日）"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "關鍵字搜尋（訂單編號、訂購人姓名或 Email 等）"
            }
          },
          {
            "name": "agencyId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依合作旅行社 ID 篩選（同業單）"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "頁碼，從 1 起算，預設第 1 頁"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "每頁筆數，上限 200（max 200）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "訂單 id（前綴 `ord_`）。"
                              },
                              "orderNumber": {
                                "type": "string",
                                "description": "人類可讀訂單編號（每租戶 sequence 產生，如 `20260707-0001`）。"
                              },
                              "bookingState": {
                                "type": "string",
                                "description": "預訂狀態（真相軸）：pending_payment → confirmed → completed；cancelled 為終態。"
                              },
                              "paymentState": {
                                "type": "string",
                                "description": "付款狀態（派生自分類帳、快取於此供過濾）：unpaid / partially_paid / deposit_paid / paid / overpaid。paid 只代表「應收被現金覆蓋」，不代表錢未退。"
                              },
                              "refundState": {
                                "type": "string",
                                "description": "退款狀態（派生快取，只算會影響應收的已付退款）：none / partially_refunded / refunded。"
                              },
                              "grossReceivableTwd": {
                                "type": "number",
                                "description": "應收（TWD 整數，派生自應收分類帳）。"
                              },
                              "collectedTwd": {
                                "type": "number",
                                "description": "收到現金（TWD 整數，派生）。"
                              },
                              "customerCashAppliedTwd": {
                                "type": "number",
                                "description": "客戶現金淨套用（收款減已退現金，TWD 整數，派生）。"
                              },
                              "outstandingTwd": {
                                "type": "number",
                                "description": "未收（應收減客戶現金淨套用，TWD 整數，派生）。"
                              },
                              "partySize": {
                                "type": "number",
                                "description": "參團人數（tour 訂單）。"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "訂單建立時間。"
                              },
                              "notes": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "訂單備註（未填 → null）。"
                              },
                              "userId": {
                                "type": "string",
                                "description": "下單客戶的 user id（同庫 user 表）。"
                              },
                              "userName": {
                                "type": "string",
                                "description": "下單客戶顯示名。"
                              },
                              "userEmail": {
                                "type": "string",
                                "description": "下單客戶 Email。"
                              },
                              "primaryTravelerName": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "主要旅客姓名（is_primary，未登記 → null）。"
                              },
                              "primaryTravelerPhone": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "主要旅客電話（未登記 → null）。"
                              },
                              "tripId": {
                                "type": "string",
                                "description": "行程 id（tour 訂單經梯次反查；lodging 為空字串）。"
                              },
                              "tripTitle": {
                                "type": "string",
                                "description": "行程 / 產品標題。"
                              },
                              "tripSlug": {
                                "type": "string",
                                "description": "行程 slug。"
                              },
                              "departureId": {
                                "type": "string",
                                "description": "梯次 id（tour 訂單；lodging 為空字串）。"
                              },
                              "departureDate": {
                                "type": "string",
                                "description": "出發日 YYYY-MM-DD（lodging 為入住日）。"
                              },
                              "returnDate": {
                                "type": "string",
                                "description": "回程日 YYYY-MM-DD（lodging 為退房日）。"
                              },
                              "assignedToUserId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "派發給哪位業務的 user id（未派發 → null）。"
                              },
                              "assigneeName": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "承辦業務顯示名（未派發 / 查無 → null）。"
                              },
                              "assignmentStatus": {
                                "type": "string",
                                "description": "派發狀態：unassigned / assigned / reassigned / pending_review。"
                              },
                              "assignedAt": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "format": "date-time",
                                "description": "最近一次派發時間（未派發 → null）。"
                              },
                              "assignedByUserId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "執行派發者的 user id（未派發 → null）。"
                              },
                              "createdByUserId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "S5: who created the order. null / equal to `userId` = customer self-service (自助下單); a staff id ≠ userId = 業務代訂 / K單. Distinct from assignment — a self-service order can still be assigned to a sales rep."
                              },
                              "pendingConsent": {
                                "type": "boolean",
                                "description": "是否尚缺最新版 PDPA 同意書簽署（true = 待客戶重簽）。"
                              },
                              "roomingStatus": {
                                "description": "分房狀態：由訂單旅客的分房偏好與已分配房間派生。 'unregistered' | 'registered' | 'needs_single' | 'assigned'。"
                              },
                              "lotteryState": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "抽籤狀態（null = FCFS 非抽籤）。'applied'|'won'|'lost'。"
                              },
                              "failoverFromOrderId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "備案單反查主單用：備案單的 failover_from_order_id 指向主單 id。"
                              },
                              "isOverdue": {
                                "type": "boolean",
                                "description": "逾期旗標：存在 status='open' 且 due_at 已過的收款計畫（未收齊的到期款）。 供列表列以 `bg-destructive/5` 標紅提示。由 OVERDUE_SUBSELECT 一次算回。"
                              }
                            },
                            "required": [
                              "id",
                              "orderNumber",
                              "bookingState",
                              "paymentState",
                              "refundState",
                              "grossReceivableTwd",
                              "collectedTwd",
                              "customerCashAppliedTwd",
                              "outstandingTwd",
                              "partySize",
                              "createdAt",
                              "notes",
                              "userId",
                              "userName",
                              "userEmail",
                              "primaryTravelerName",
                              "primaryTravelerPhone",
                              "tripId",
                              "tripTitle",
                              "tripSlug",
                              "departureId",
                              "departureDate",
                              "returnDate",
                              "assignedToUserId",
                              "assigneeName",
                              "assignmentStatus",
                              "assignedAt",
                              "assignedByUserId",
                              "createdByUserId",
                              "pendingConsent",
                              "roomingStatus",
                              "lotteryState",
                              "failoverFromOrderId",
                              "isOverdue"
                            ]
                          },
                          "description": "當前頁的訂單列（tour-centric，每筆 tour line 一列）。"
                        },
                        "total": {
                          "type": "number",
                          "description": "符合篩選的訂單總數（DISTINCT 訂單，非列數）。"
                        },
                        "page": {
                          "type": "number",
                          "description": "當前頁碼（從 1 起算）。"
                        },
                        "pageSize": {
                          "type": "number",
                          "description": "每頁筆數。"
                        }
                      },
                      "required": [
                        "rows",
                        "total",
                        "page",
                        "pageSize"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.read"
      },
      "post": {
        "operationId": "post_orders",
        "tags": [
          "orders"
        ],
        "description": "GET /api/v1/orders — list/search/filter orders (the /admin/orders table over\nHTTP). Owner-scope is ALWAYS re-derived server-side from the bearer user's\nrole (deriveOrderScope) — never trusted from the client — so sales tokens see\nonly their own orders, identical to the back office. See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "orderId": {
                          "type": "string",
                          "description": "新建立訂單的 ID（ord_ 前綴）。"
                        },
                        "orderNumber": {
                          "type": "string",
                          "description": "訂單編號（租戶內流水序號，對外顯示用）。"
                        }
                      },
                      "required": [
                        "orderId",
                        "orderNumber"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.create",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tripId": {
                    "type": "string",
                    "description": "行程 ID（min 1）"
                  },
                  "departureId": {
                    "type": "string",
                    "description": "梯次 ID，決定佔位的出發團（min 1）"
                  },
                  "primaryEmail": {
                    "type": "string",
                    "description": "訂購人 Email，須對應已註冊會員（min 1）"
                  },
                  "partySize": {
                    "type": "number",
                    "description": "報名人數，決定佔位數，須為 1 至 20 之間整數"
                  },
                  "travelers": {
                    "type": "array",
                    "items": {},
                    "description": "旅客名單，筆數須與報名人數一致"
                  },
                  "paymentMethod": {
                    "type": "string",
                    "enum": [
                      "cash",
                      "atm",
                      "manual"
                    ],
                    "description": "收款方式：cash 現金、atm 轉帳、manual 人工"
                  },
                  "customerType": {
                    "type": "string",
                    "enum": [
                      "direct",
                      "agency"
                    ],
                    "description": "客戶類型：direct 直客、agency 同業，預設直客"
                  },
                  "paymentPlan": {
                    "type": "string",
                    "enum": [
                      "full",
                      "deposit"
                    ],
                    "description": "付款方案：full 全額、deposit 訂金，預設全額"
                  },
                  "receivingAccountId": {
                    "type": "string",
                    "description": "收款帳戶 ID，指定本筆款項入帳的帳戶"
                  },
                  "notes": {
                    "type": "string",
                    "description": "訂單備註"
                  },
                  "assigneeUserId": {
                    "type": "string",
                    "description": "指定業績歸屬業務的使用者 ID，省略或等於自己則歸屬建單者；指定他人需具備訂單指派權限"
                  }
                },
                "required": [
                  "tripId",
                  "departureId",
                  "primaryEmail",
                  "partySize",
                  "travelers",
                  "paymentMethod"
                ]
              }
            }
          }
        }
      }
    },
    "/orders/{id}": {
      "get": {
        "operationId": "get_orders_id_",
        "tags": [
          "orders"
        ],
        "summary": "full kind-aware order detail",
        "description": "GET /api/v1/orders/{id} — full kind-aware order detail (header + travelers +\ncharge lines + cash transactions + schedules + intents + refunds + consents).\nOwner-scoped; out-of-scope or missing → 404 (avoids leaking existence).\nTraveler PII (id_number/passport_no) is returned MASKED — full reveal is a\nseparate gated op.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "訂單 id（前綴 `ord_`）。"
                        },
                        "orderNumber": {
                          "type": "string",
                          "description": "人類可讀訂單編號（每租戶 sequence 產生，如 `20260707-0001`）。"
                        },
                        "bookingState": {
                          "type": "string",
                          "description": "預訂狀態（真相軸）：pending_payment → confirmed → completed；cancelled 為終態。"
                        },
                        "paymentState": {
                          "type": "string",
                          "description": "付款狀態（派生自分類帳、快取於此供過濾）：unpaid / partially_paid / deposit_paid / paid / overpaid。paid 只代表「應收被現金覆蓋」，不代表錢未退。"
                        },
                        "refundState": {
                          "type": "string",
                          "description": "退款狀態（派生快取，只算會影響應收的已付退款）：none / partially_refunded / refunded。"
                        },
                        "grossReceivableTwd": {
                          "type": "number",
                          "description": "應收（TWD 整數，派生自應收分類帳）。"
                        },
                        "collectedTwd": {
                          "type": "number",
                          "description": "收到現金（TWD 整數，派生）。"
                        },
                        "customerCashAppliedTwd": {
                          "type": "number",
                          "description": "客戶現金淨套用（收款減已退現金，TWD 整數，派生）。"
                        },
                        "outstandingTwd": {
                          "type": "number",
                          "description": "未收（應收減客戶現金淨套用，TWD 整數，派生）。"
                        },
                        "partySize": {
                          "type": "number",
                          "description": "參團人數（tour 訂單）。"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "訂單建立時間。"
                        },
                        "notes": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "訂單備註（未填 → null）。"
                        },
                        "userId": {
                          "type": "string",
                          "description": "下單客戶的 user id（同庫 user 表）。"
                        },
                        "userName": {
                          "type": "string",
                          "description": "下單客戶顯示名。"
                        },
                        "userEmail": {
                          "type": "string",
                          "description": "下單客戶 Email。"
                        },
                        "primaryTravelerName": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "主要旅客姓名（is_primary，未登記 → null）。"
                        },
                        "primaryTravelerPhone": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "主要旅客電話（未登記 → null）。"
                        },
                        "tripId": {
                          "type": "string",
                          "description": "行程 id（tour 訂單經梯次反查；lodging 為空字串）。"
                        },
                        "tripTitle": {
                          "type": "string",
                          "description": "行程 / 產品標題。"
                        },
                        "tripSlug": {
                          "type": "string",
                          "description": "行程 slug。"
                        },
                        "departureId": {
                          "type": "string",
                          "description": "梯次 id（tour 訂單；lodging 為空字串）。"
                        },
                        "departureDate": {
                          "type": "string",
                          "description": "出發日 YYYY-MM-DD（lodging 為入住日）。"
                        },
                        "returnDate": {
                          "type": "string",
                          "description": "回程日 YYYY-MM-DD（lodging 為退房日）。"
                        },
                        "assignedToUserId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "派發給哪位業務的 user id（未派發 → null）。"
                        },
                        "assigneeName": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "承辦業務顯示名（未派發 / 查無 → null）。"
                        },
                        "assignmentStatus": {
                          "type": "string",
                          "description": "派發狀態：unassigned / assigned / reassigned / pending_review。"
                        },
                        "assignedAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "最近一次派發時間（未派發 → null）。"
                        },
                        "assignedByUserId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "執行派發者的 user id（未派發 → null）。"
                        },
                        "createdByUserId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "S5: who created the order. null / equal to `userId` = customer self-service (自助下單); a staff id ≠ userId = 業務代訂 / K單. Distinct from assignment — a self-service order can still be assigned to a sales rep."
                        },
                        "pendingConsent": {
                          "type": "boolean",
                          "description": "是否尚缺最新版 PDPA 同意書簽署（true = 待客戶重簽）。"
                        },
                        "roomingStatus": {
                          "description": "分房狀態：由訂單旅客的分房偏好與已分配房間派生。 'unregistered' | 'registered' | 'needs_single' | 'assigned'。"
                        },
                        "lotteryState": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "抽籤狀態（null = FCFS 非抽籤）。'applied'|'won'|'lost'。"
                        },
                        "failoverFromOrderId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "備案單反查主單用：備案單的 failover_from_order_id 指向主單 id。"
                        },
                        "isOverdue": {
                          "type": "boolean",
                          "description": "逾期旗標：存在 status='open' 且 due_at 已過的收款計畫（未收齊的到期款）。 供列表列以 `bg-destructive/5` 標紅提示。由 OVERDUE_SUBSELECT 一次算回。"
                        },
                        "kind": {
                          "type": "string",
                          "enum": [
                            "lodging",
                            "tour"
                          ],
                          "description": "訂單種類（kind-agnostic 外殼）。'tour' 用既有 tour 區塊（梯次/分房/登山審核）； 'lodging' 隱藏 tour-only 區、改顯示住宿 header（見 `lodging`）。共用的金流/旅客/ 派發/同意書區塊兩者皆 order-scoped 通用。"
                        },
                        "lodging": {
                          "anyOf": [
                            {},
                            {
                              "type": "null"
                            }
                          ],
                          "description": "lodging 住宿 header（房型/住期/房數/人數）；tour 為 null。"
                        },
                        "travelers": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "旅客 id（前綴 `trv_`）。"
                              },
                              "fullName": {
                                "type": "string",
                                "description": "旅客姓名。"
                              },
                              "idNumberMask": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "遮罩碼（jsonb→mask，零解密）；NULL = 未填。全碼走 reveal action（Task 7）。"
                              },
                              "passportNoMask": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "護照號碼遮罩碼（零解密）；NULL = 未填。全碼走 order-scoped reveal。"
                              },
                              "birthDate": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "生日 YYYY-MM-DD（未填 → null）。"
                              },
                              "phone": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "聯絡電話（未填 → null）。"
                              },
                              "email": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "聯絡 Email（未填 → null）。"
                              },
                              "emergencyContactName": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "緊急聯絡人姓名（未填 → null）。"
                              },
                              "emergencyContactPhone": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "緊急聯絡人電話（未填 → null）。"
                              },
                              "isPrimary": {
                                "type": "boolean",
                                "description": "是否為主要旅客（訂單聯絡人）。"
                              },
                              "gender": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "性別（分房硬約束 + 顯示）：'male'|'female'|'other'|null。明文。"
                              },
                              "roomPreference": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "分房房型偏好（下單登記）。"
                              },
                              "roommatePref": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "指定房友 / 特殊需求自由文字。"
                              },
                              "diet": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "飲食需求（葷素）明文；null = 未填。非 PII，不走 reveal。"
                              },
                              "medicalNotes": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "醫療 / 過敏 / 病史備註明文；null = 未填。非 PII，不走 reveal。"
                              },
                              "address": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "通訊地址（未填 → null）。"
                              },
                              "roomLabel": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "團控已排房號的房間 label（null = 待團控分房）。"
                              }
                            },
                            "required": [
                              "id",
                              "fullName",
                              "idNumberMask",
                              "passportNoMask",
                              "birthDate",
                              "phone",
                              "email",
                              "emergencyContactName",
                              "emergencyContactPhone",
                              "isPrimary",
                              "gender",
                              "roomPreference",
                              "roommatePref",
                              "diet",
                              "medicalNotes",
                              "address",
                              "roomLabel"
                            ]
                          },
                          "description": "旅客名單（含 PII 遮罩欄；主要旅客排前）。"
                        },
                        "chargeLines": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "應收明細列 id。"
                              },
                              "type": {
                                "type": "string",
                                "description": "應收類型：base（原始價）/ room_upgrade（房升補款）/ adjustment / failover_deposit_credit 等。"
                              },
                              "amountTwd": {
                                "type": "number",
                                "description": "金額（TWD 整數，signed；credit / 沖銷為負）。"
                              },
                              "description": {
                                "type": "string",
                                "description": "明細說明文字。"
                              },
                              "sourceType": {
                                "type": "string",
                                "description": "來源：system（系統派生）/ manual（人工登錄）等。"
                              },
                              "reversesChargeLineId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "若為沖銷列，指向被沖銷的應收明細列 id（否則 null）。"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "建立時間。"
                              }
                            },
                            "required": [
                              "id",
                              "type",
                              "amountTwd",
                              "description",
                              "sourceType",
                              "reversesChargeLineId",
                              "createdAt"
                            ]
                          },
                          "description": "應收分類帳（itemized）。"
                        },
                        "transactions": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "現金交易列 id。"
                              },
                              "direction": {
                                "type": "string",
                                "description": "金流方向：in（收款）/ out（退款、扣款、沖銷）。"
                              },
                              "type": {
                                "type": "string",
                                "description": "交易類型：payment / refund / chargeback / reversal。"
                              },
                              "amountTwd": {
                                "type": "number",
                                "description": "交易金額（TWD 整數，正值）。"
                              },
                              "feeTwd": {
                                "type": "number",
                                "description": "金流商手續費（TWD 整數）。"
                              },
                              "netTwd": {
                                "type": "number",
                                "description": "淨額 = amount − fee（TWD 整數）。"
                              },
                              "provider": {
                                "type": "string",
                                "description": "金流商：manual / ecpay / test 等。"
                              },
                              "providerTradeNo": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "金流商交易序號（manual 入帳可能為 null）。"
                              },
                              "refundId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "若屬退款，指向 refunds 列 id（否則 null）。"
                              },
                              "occurredAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "交易發生時間。"
                              }
                            },
                            "required": [
                              "id",
                              "direction",
                              "type",
                              "amountTwd",
                              "feeTwd",
                              "netTwd",
                              "provider",
                              "providerTradeNo",
                              "refundId",
                              "occurredAt"
                            ]
                          },
                          "description": "現金分類帳。"
                        },
                        "schedules": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "收款計畫列 id。"
                              },
                              "purpose": {
                                "type": "string",
                                "description": "用途：full（全額）/ deposit（訂金）/ balance（尾款）/ adjustment（補款）。"
                              },
                              "targetAmountTwd": {
                                "type": "number",
                                "description": "應收目標金額（TWD 整數）。"
                              },
                              "status": {
                                "type": "string",
                                "description": "計畫狀態：open（未收齊）/ satisfied（已收齊）。"
                              },
                              "dueAt": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "format": "date-time",
                                "description": "到期日（null = 未設）。"
                              },
                              "sequence": {
                                "type": "number",
                                "description": "排序序號（deposit → balance → adjustment）。"
                              }
                            },
                            "required": [
                              "id",
                              "purpose",
                              "targetAmountTwd",
                              "status",
                              "dueAt",
                              "sequence"
                            ]
                          },
                          "description": "收款計畫（current + historical）。"
                        }
                      },
                      "required": [
                        "id",
                        "orderNumber",
                        "bookingState",
                        "paymentState",
                        "refundState",
                        "grossReceivableTwd",
                        "collectedTwd",
                        "customerCashAppliedTwd",
                        "outstandingTwd",
                        "partySize",
                        "createdAt",
                        "notes",
                        "userId",
                        "userName",
                        "userEmail",
                        "primaryTravelerName",
                        "primaryTravelerPhone",
                        "tripId",
                        "tripTitle",
                        "tripSlug",
                        "departureId",
                        "departureDate",
                        "returnDate",
                        "assignedToUserId",
                        "assigneeName",
                        "assignmentStatus",
                        "assignedAt",
                        "assignedByUserId",
                        "createdByUserId",
                        "pendingConsent",
                        "roomingStatus",
                        "lotteryState",
                        "failoverFromOrderId",
                        "isOverdue",
                        "kind",
                        "lodging",
                        "travelers",
                        "chargeLines",
                        "transactions",
                        "schedules"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.read"
      }
    },
    "/orders/{id}/adjust": {
      "post": {
        "operationId": "post_orders_id_adjust",
        "tags": [
          "orders"
        ],
        "summary": "manual charge adjustment",
        "description": "POST /api/v1/orders/{id}/adjust — manual charge adjustment (掛帳): append a\nsurcharge or allowance charge line + recompute money + audit. Same core op as\n`applyManualAdjustmentAction`; gated `order.adjust`. Invariant/state failures\nsurface as 409 via mapError (ManualChargeError / OrderInvariantError).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：訂單金額調整已套用。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.adjust",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "surcharge",
                      "allowance"
                    ],
                    "description": "調整類型：surcharge 加收、allowance 減免"
                  },
                  "amountTwd": {
                    "type": "number",
                    "description": "調整金額（新台幣，正整數）"
                  },
                  "description": {
                    "type": "string",
                    "description": "調整事由說明（min 1）"
                  }
                },
                "required": [
                  "kind",
                  "amountTwd",
                  "description"
                ]
              }
            }
          }
        }
      }
    },
    "/orders/{id}/assign": {
      "post": {
        "operationId": "post_orders_id_assign",
        "tags": [
          "orders"
        ],
        "summary": "首次派發訂單給承辦業務",
        "description": "POST /api/v1/orders/{id}/assign — 首次派發訂單給承辦業務（pending_review →\nassigned）。鏡像後台 `assignOrderAction`：同核心 op `assignOrderWithNotify`\n（指派 + best-effort 通知受派業務，audit 在 op 內），同權限 `order.assign`。\n重派已派單需 `order.reassign`，走 /reassign。idempotent no-op（重派同人）不通知。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：訂單已指派承辦。"
                        },
                        "idempotent": {
                          "type": "boolean",
                          "description": "true = 該訂單原已指派給同一承辦，本次為冪等無變更。"
                        }
                      },
                      "required": [
                        "ok",
                        "idempotent"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.assign",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "assigneeUserId": {
                    "type": "string",
                    "description": "受派業務的使用者 ID（min 1）"
                  },
                  "reason": {
                    "type": "string",
                    "description": "派發事由說明（上限 500 字）（max 500）"
                  }
                },
                "required": [
                  "assigneeUserId"
                ]
              }
            }
          }
        }
      }
    },
    "/orders/{id}/balance-link": {
      "post": {
        "operationId": "post_orders_id_balance_link",
        "tags": [
          "orders"
        ],
        "summary": "產生/重用尾款",
        "description": "POST /api/v1/orders/{id}/balance-link — 產生/重用尾款（purpose='balance'）付款\nintent，回傳待補金額。鏡像後台 `createBalancePaymentLinkAction`：同核心 op\n`prepareBalancePayment` + owner-scope（sales 僅能對自己負責的單建補款連結）+ 同\n`order.balance_link_created` 稽核，同權限 `order.update`。綠界表單由前端橋接頁取。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：尾款付款連結已產生。"
                        },
                        "amountTwd": {
                          "type": "number",
                          "description": "本次尾款金額（TWD 整數）。"
                        },
                        "scheduleId": {
                          "type": "string",
                          "description": "對應的收款計畫 ID。"
                        }
                      },
                      "required": [
                        "ok",
                        "amountTwd",
                        "scheduleId"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.update"
      }
    },
    "/orders/{id}/cancel": {
      "post": {
        "operationId": "post_orders_id_cancel",
        "tags": [
          "orders"
        ],
        "summary": "cancel a tour order",
        "description": "POST /api/v1/orders/{id}/cancel — cancel a tour order (release seats,\nbooking_state→cancelled; no auto-refund). Same core op + audit as the back\noffice `cancelOrderAction`; gated `order.update`. Owner-scope re-derived\nserver-side (sales can only cancel their own orders; out-of-scope → 404).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：訂單已取消（座位釋出、booking_state 轉 cancelled）。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.update",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "description": "取消事由說明"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/orders/{id}/claim": {
      "post": {
        "operationId": "post_orders_id_claim",
        "tags": [
          "orders"
        ],
        "summary": "業務自派搶單",
        "description": "POST /api/v1/orders/{id}/claim — 業務自派搶單（order-assignment §6）。鏡像後台\n`claimOrderAction`：同核心 op `claimOrderWithNotify`（race-safe CAS + banned claimant 拒\n+ audit order.claim + best-effort 通知），同能力閘 `order.claim`，並額外強制 per-tenant\n`allow_sales_claim` 開關（關即 403，fail-closed，與後台 action 一致）。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：訂單已由當前承辦認領。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.claim"
      }
    },
    "/orders/{id}/lottery/resolve": {
      "post": {
        "operationId": "post_orders_id_lottery_resolve",
        "tags": [
          "orders"
        ],
        "summary": "線控手動抽籤裁決：won",
        "description": "POST /api/v1/orders/{id}/lottery/resolve — 線控手動抽籤裁決：won（中籤確認）|\nlost（未中籤啟動備案 / 取消流程）。同核心 op + core 內建 audit，鏡像後台\n`resolveLotteryAction`；gated lottery.manage + lottery 模組閘（未啟用 → 409）。\nresolveLotteryOrder 的 state guard 失敗（already_resolved / backup_sold_out /\nnot_lottery）→ 409。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：抽籤結果已登錄。"
                        },
                        "outcome": {
                          "type": "string",
                          "enum": [
                            "won",
                            "lost"
                          ],
                          "description": "抽籤結果：won 中籤 / lost 未中籤。"
                        }
                      },
                      "required": [
                        "ok",
                        "outcome"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "lottery.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "outcome": {
                    "type": "string",
                    "enum": [
                      "won",
                      "lost"
                    ],
                    "description": "抽籤裁決結果：won 中籤確認、lost 未中籤（啟動備案或取消）"
                  }
                },
                "required": [
                  "outcome"
                ]
              }
            }
          }
        }
      }
    },
    "/orders/{id}/mark-paid": {
      "post": {
        "operationId": "post_orders_id_mark_paid",
        "tags": [
          "orders"
        ],
        "summary": "mark an order paid by manual",
        "description": "POST /api/v1/orders/{id}/mark-paid — mark an order paid by manual\nbank-transfer reconciliation (idempotent). Same core op + audit as the back\noffice `markPaidAction`; gated on `payment.update`. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "idempotent": {
                          "type": "boolean",
                          "description": "true = 訂單原已為已付狀態，本次為冪等無變更。"
                        }
                      },
                      "required": [
                        "idempotent"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payment.update",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "note": {
                    "type": "string",
                    "description": "對帳備註，記錄人工核款說明"
                  },
                  "receivingAccountId": {
                    "type": "string",
                    "description": "收款帳戶 ID，指定本筆款項入帳的帳戶"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/orders/{id}/reassign": {
      "post": {
        "operationId": "post_orders_id_reassign",
        "tags": [
          "orders"
        ],
        "summary": "重新指派已派發訂單",
        "description": "POST /api/v1/orders/{id}/reassign — 重新指派已派發訂單（→ reassigned）。\n鏡像後台 `reassignOrderAction`：同核心 op `assignOrderWithNotify`（mode='reassign'：\n通知新業務接單 + 舊業務轉走），同權限 `order.reassign`（admin-only，非 op 角色擁有，\n故與首派 audit 區隔）。idempotent no-op（重派同人）不通知。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：訂單已改派承辦。"
                        },
                        "idempotent": {
                          "type": "boolean",
                          "description": "true = 目標承辦與原承辦相同，本次為冪等無變更。"
                        }
                      },
                      "required": [
                        "ok",
                        "idempotent"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.reassign",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "assigneeUserId": {
                    "type": "string",
                    "description": "重新指派的承接業務使用者 ID（min 1）"
                  },
                  "reason": {
                    "type": "string",
                    "description": "重派事由說明（上限 500 字）（max 500）"
                  }
                },
                "required": [
                  "assigneeUserId"
                ]
              }
            }
          }
        }
      }
    },
    "/orders/{id}/refunds": {
      "post": {
        "operationId": "post_orders_id_refunds",
        "tags": [
          "orders"
        ],
        "summary": "create + submit a customer refund",
        "description": "POST /api/v1/orders/{id}/refunds — create + submit a customer refund\n(draft→submitted), capturing the execution-routing fields (account-settlement\n§3.5). Same core op + audit as `createRefundAction`; gated `refund.create`,\nowner-scope re-derived (sales only their own orders). RefundStateError → 409.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "退款單 id（前綴 `rfnd_`）。"
                        },
                        "refundNumber": {
                          "type": "string",
                          "description": "人類可讀退款單號。"
                        },
                        "status": {
                          "description": "退款工作流狀態：draft → submitted → approved → processing → paid。"
                        }
                      },
                      "required": [
                        "id",
                        "refundNumber",
                        "status"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "refund.create",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "refundKind": {
                    "type": "string",
                    "enum": [
                      "receivable_reduction",
                      "overpayment_return"
                    ],
                    "description": "退款種類：receivable_reduction 應收減免、overpayment_return 溢收退還"
                  },
                  "reason": {
                    "type": "string",
                    "description": "退款事由說明（min 1）"
                  },
                  "amountTwd": {
                    "type": "number",
                    "description": "退款總金額（新台幣，正整數）"
                  },
                  "executionMethod": {
                    "type": "string",
                    "enum": [
                      "chargeback",
                      "remit"
                    ],
                    "description": "退款執行方式：chargeback 原路退刷、remit 銀行匯款"
                  },
                  "originAccountId": {
                    "type": "string",
                    "description": "出款來源帳戶 ID（匯款退款時指定）"
                  },
                  "adminFeeTwd": {
                    "type": "number",
                    "description": "手續費／行政費（新台幣，非負整數）"
                  },
                  "remitFeeTwd": {
                    "type": "number",
                    "description": "匯款轉帳費（新台幣，非負整數）"
                  },
                  "payeeAccountName": {
                    "type": "string",
                    "description": "受款人戶名（匯款退款時填寫）"
                  },
                  "payeeBankCode": {
                    "type": "string",
                    "description": "受款銀行代碼（匯款退款時填寫）"
                  },
                  "payeeAccountNumber": {
                    "type": "string",
                    "description": "受款銀行帳號（匯款退款時填寫）"
                  },
                  "lines": {
                    "type": "array",
                    "items": {},
                    "description": "退款明細列；省略時依退款總額處理"
                  }
                },
                "required": [
                  "refundKind",
                  "reason",
                  "amountTwd"
                ]
              }
            }
          }
        }
      }
    },
    "/orders/{id}/refunds/{refundId}/approve": {
      "post": {
        "operationId": "post_orders_id_refunds_refundId_approve",
        "tags": [
          "orders"
        ],
        "summary": "approve a submitted",
        "description": "POST /api/v1/orders/{id}/refunds/{refundId}/approve — approve a submitted\nrefund (submitted→approved; responsibility separation: not the creator). Same\ncore op as `approveRefundAction`; gated `refund.approve`. RefundStateError →\n409 (incl CREATOR_CANNOT_APPROVE).",
        "parameters": [
          {
            "name": "refundId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "退款單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：退款申請已核准。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "refund.approve"
      }
    },
    "/orders/{id}/refunds/{refundId}/mark-paid": {
      "post": {
        "operationId": "post_orders_id_refunds_refundId_mark_paid",
        "tags": [
          "orders"
        ],
        "summary": "mark an approved",
        "description": "POST /api/v1/orders/{id}/refunds/{refundId}/mark-paid — mark an approved\nrefund as paid (approved→paid; cash integration point: H5 over-refund guard +\nreduce receivable + outbound cash row). Same core op as\n`markRefundPaidAction`; gated `refund.mark_paid`. RefundExecutionError /\nRefundStateError / OrderInvariantError → 409 via mapError. `remit` refunds\nneed a can_remit receivingAccountId.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（path）（min 1）"
            }
          },
          {
            "name": "refundId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "退款單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：退款已標記為完成出款。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "refund.mark_paid",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "bankReference": {
                    "type": "string",
                    "description": "出款的銀行交易參考號（匯款憑證）"
                  },
                  "receivingAccountId": {
                    "type": "string",
                    "description": "出款帳戶 ID；remit 退款須指定具匯款能力的帳戶"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/orders/{id}/refunds/{refundId}/reject": {
      "post": {
        "operationId": "post_orders_id_refunds_refundId_reject",
        "tags": [
          "orders"
        ],
        "summary": "reject a submitted",
        "description": "POST /api/v1/orders/{id}/refunds/{refundId}/reject — reject a submitted\nrefund (submitted→cancelled). Same core op as `rejectRefundAction`; gated\n`refund.reject`.",
        "parameters": [
          {
            "name": "refundId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "退款單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：退款申請已駁回。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "refund.reject",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "description": "退件事由說明"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/orders/{id}/reverse": {
      "post": {
        "operationId": "post_orders_id_reverse",
        "tags": [
          "orders"
        ],
        "summary": "reverse an existing charge line",
        "description": "POST /api/v1/orders/{id}/reverse — reverse an existing charge line (沖正):\nappend a type='reversal' counter-line. Same core op as\n`reverseChargeLineAction`; gated `order.adjust`. State/invariant failures →\n409 via mapError.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：訂單已沖銷（沖回應收與已認列項）。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.adjust",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "chargeLineId": {
                    "type": "string",
                    "description": "欲沖正的應收項目（charge line）ID（min 1）"
                  },
                  "description": {
                    "type": "string",
                    "description": "沖正事由說明（min 1）"
                  }
                },
                "required": [
                  "chargeLineId",
                  "description"
                ]
              }
            }
          }
        }
      }
    },
    "/orders/{id}/review-screening": {
      "post": {
        "operationId": "post_orders_id_review_screening",
        "tags": [
          "orders"
        ],
        "summary": "人工核可/駁回登山資格審核",
        "description": "POST /api/v1/orders/{id}/review-screening — 人工核可/駁回登山資格審核\n（climbing-screening §5.4/§6）。鏡像後台 `reviewScreeningAction`：同核心 op\n`reviewScreening`（寫 verdict/reviewedBy/audit），同權限 `screening.review`。\n駁回不自動退單。僅 verdict='needs_review' 可審。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：名單複核結果已登錄。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "screening.review",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "decision": {
                    "type": "string",
                    "enum": [
                      "approve",
                      "reject"
                    ],
                    "description": "登山資格審核裁決：approve 核可、reject 駁回"
                  },
                  "note": {
                    "type": "string",
                    "description": "審核註記說明（上限 500 字）（max 500）"
                  }
                },
                "required": [
                  "decision"
                ]
              }
            }
          }
        }
      }
    },
    "/orders/{id}/travelers": {
      "post": {
        "operationId": "post_orders_id_travelers",
        "tags": [
          "orders"
        ],
        "summary": "新增旅客到訂單",
        "description": "POST /api/v1/orders/{id}/travelers — 新增旅客到訂單。鏡像後台 `addTravelerAction`：\n同核心 op `addTraveler`（編輯窗檢查 + audit），同權限 `order.update`，同 owner-scope\nIDOR 邊界（sales 僅能改派給自己的單，out-of-scope → 404）。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：旅客已新增至訂單。"
                        },
                        "travelerId": {
                          "type": "string",
                          "description": "新建立旅客的 ID（trv_ 前綴）。"
                        }
                      },
                      "required": [
                        "ok",
                        "travelerId"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.update",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "fullName": {
                    "type": "string",
                    "description": "旅客全名，須與證件一致；新增旅客時必填，更新時可省略（min 1）"
                  },
                  "phone": {
                    "type": "string",
                    "description": "旅客聯絡電話"
                  },
                  "email": {
                    "type": "string",
                    "description": "旅客電子郵件"
                  },
                  "birthDate": {
                    "type": "string",
                    "description": "旅客出生日期（格式 YYYY-MM-DD）"
                  },
                  "emergencyContactName": {
                    "type": "string",
                    "description": "緊急聯絡人姓名"
                  },
                  "emergencyContactPhone": {
                    "type": "string",
                    "description": "緊急聯絡人電話"
                  },
                  "gender": {
                    "type": "string",
                    "enum": [
                      "male",
                      "female",
                      "other"
                    ],
                    "description": "旅客性別：male 男、female 女、other 其他"
                  },
                  "roomPreference": {
                    "type": "string",
                    "description": "房型偏好（用於分房作業）"
                  },
                  "roommatePref": {
                    "type": "string",
                    "description": "指定同住室友（用於分房作業）"
                  },
                  "diet": {
                    "type": "string",
                    "description": "飲食需求（葷 / 素 / 蛋奶素… 自由值），供餐食葷素彙總"
                  },
                  "medicalNotes": {
                    "type": "string",
                    "description": "醫療 / 過敏 / 病史備註（自由文字），供出團安全警示"
                  },
                  "address": {
                    "type": "string",
                    "description": "旅客通訊地址"
                  },
                  "idNumber": {
                    "type": "string",
                    "description": "身分證字號，屬個資將加密保存"
                  },
                  "passportNo": {
                    "type": "string",
                    "description": "護照號碼，屬個資將加密保存"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/orders/{id}/travelers/{travelerId}": {
      "patch": {
        "operationId": "patch_orders_id_travelers_travelerId_",
        "tags": [
          "orders"
        ],
        "summary": "更新旅客資料",
        "description": "PATCH  /api/v1/orders/{id}/travelers/{travelerId} — 更新旅客資料（updateTraveler）。\nDELETE /api/v1/orders/{id}/travelers/{travelerId} — 移除旅客（removeTraveler）。\n鏡像後台 `updateTravelerAction` / `removeTravelerAction`：同核心 op（編輯窗檢查 +\naudit）、同權限 `order.update`、同 owner-scope IDOR 邊界（out-of-scope → 404）。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（min 1）"
            }
          },
          {
            "name": "travelerId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "旅客 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：旅客資料已更新。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.update",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "fullName": {
                    "type": "string",
                    "description": "旅客全名，須與證件一致；新增旅客時必填，更新時可省略（min 1）"
                  },
                  "phone": {
                    "type": "string",
                    "description": "旅客聯絡電話"
                  },
                  "email": {
                    "type": "string",
                    "description": "旅客電子郵件"
                  },
                  "birthDate": {
                    "type": "string",
                    "description": "旅客出生日期（格式 YYYY-MM-DD）"
                  },
                  "emergencyContactName": {
                    "type": "string",
                    "description": "緊急聯絡人姓名"
                  },
                  "emergencyContactPhone": {
                    "type": "string",
                    "description": "緊急聯絡人電話"
                  },
                  "gender": {
                    "type": "string",
                    "enum": [
                      "male",
                      "female",
                      "other"
                    ],
                    "description": "旅客性別：male 男、female 女、other 其他"
                  },
                  "roomPreference": {
                    "type": "string",
                    "description": "房型偏好（用於分房作業）"
                  },
                  "roommatePref": {
                    "type": "string",
                    "description": "指定同住室友（用於分房作業）"
                  },
                  "diet": {
                    "type": "string",
                    "description": "飲食需求（葷 / 素 / 蛋奶素… 自由值），供餐食葷素彙總"
                  },
                  "medicalNotes": {
                    "type": "string",
                    "description": "醫療 / 過敏 / 病史備註（自由文字），供出團安全警示"
                  },
                  "address": {
                    "type": "string",
                    "description": "旅客通訊地址"
                  },
                  "idNumber": {
                    "type": "string",
                    "description": "身分證字號，屬個資將加密保存"
                  },
                  "passportNo": {
                    "type": "string",
                    "description": "護照號碼，屬個資將加密保存"
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_orders_id_travelers_travelerId_",
        "tags": [
          "orders"
        ],
        "summary": "移除旅客",
        "description": "PATCH  /api/v1/orders/{id}/travelers/{travelerId} — 更新旅客資料（updateTraveler）。\nDELETE /api/v1/orders/{id}/travelers/{travelerId} — 移除旅客（removeTraveler）。\n鏡像後台 `updateTravelerAction` / `removeTravelerAction`：同核心 op（編輯窗檢查 +\naudit）、同權限 `order.update`、同 owner-scope IDOR 邊界（out-of-scope → 404）。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（min 1）"
            }
          },
          {
            "name": "travelerId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "旅客 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：旅客已自訂單移除。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.update"
      }
    },
    "/orders/{id}/travelers/{travelerId}/reveal": {
      "post": {
        "operationId": "post_orders_id_travelers_travelerId_reveal",
        "tags": [
          "orders"
        ],
        "summary": "顯示旅客證號/護照全碼",
        "description": "POST /api/v1/orders/{id}/travelers/{travelerId}/reveal — 顯示旅客證號/護照全碼。\n鏡像後台 `revealTravelerPiiAction`：同核心 op `revealTravelerPii`（owner-scope 防 IDOR\n在 core 內重推 + 信封解密 + traveler.decrypt 稽核）。order.read 是純 RBAC，scope 在\nhandler 由 bearer 角色重推（絕不信任 client）。這是「會寫稽核的讀取」故為 POST。\nout-of-scope/查無 → 404；解密失敗 → 500。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（min 1）"
            }
          },
          {
            "name": "travelerId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "旅客 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "field": {
                          "type": "string",
                          "enum": [
                            "idNumber",
                            "passportNo"
                          ],
                          "description": "本次解密的欄位：idNumber 身分證字號 / passportNo 護照號碼。"
                        },
                        "value": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "解密後的證件明碼；null = 該欄未填。每次呼叫都會寫入解密稽核紀錄。"
                        }
                      },
                      "required": [
                        "field",
                        "value"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.read",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "field": {
                    "type": "string",
                    "enum": [
                      "idNumber",
                      "passportNo"
                    ],
                    "description": "欲顯示全碼的個資欄位：idNumber 身分證字號、passportNo 護照號碼"
                  }
                },
                "required": [
                  "field"
                ]
              }
            }
          }
        }
      }
    },
    "/orders/{id}/travelers/{travelerId}/rooming": {
      "patch": {
        "operationId": "patch_orders_id_travelers_travelerId_rooming",
        "tags": [
          "orders"
        ],
        "summary": "更新旅客分房需求",
        "description": "PATCH /api/v1/orders/{id}/travelers/{travelerId}/rooming — 更新旅客分房需求\n（房型偏好 / 指定室友）。鏡像後台 `updateRoomingPreferenceAction`：同核心 op\n`updateRoomingPreference`（與 updateTraveler 分開：無編輯窗限制、各自 audit），\n同權限 `order.update`、同 owner-scope IDOR 邊界（out-of-scope → 404）。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "訂單 ID（min 1）"
            }
          },
          {
            "name": "travelerId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "旅客 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：旅客分房設定已更新。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.update",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "roomPreference": {
                    "type": "string",
                    "description": "房型偏好（用於分房作業）"
                  },
                  "roommatePref": {
                    "type": "string",
                    "description": "指定同住室友（用於分房作業）"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/orders/bulk-assign": {
      "post": {
        "operationId": "post_orders_bulk_assign",
        "tags": [
          "orders"
        ],
        "summary": "批次把多張訂單派給同一位業務",
        "description": "POST /api/v1/orders/bulk-assign — 批次把多張訂單派給同一位業務（all-or-nothing\ntransaction）。鏡像後台 `bulkAssignOrdersAction`：同核心 op\n`bulkAssignOrdersWithNotify`（只對實際派成的單通知），同權限 `order.assign`。\n回傳 assignedCount / skippedCount（已取消/已派/同人會被 skip，非錯誤）。",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：批次指派已執行。"
                        },
                        "assignedCount": {
                          "type": "number",
                          "description": "成功指派的訂單筆數。"
                        },
                        "skippedCount": {
                          "type": "number",
                          "description": "略過的訂單筆數（如已指派或不在可指派範圍）。"
                        }
                      },
                      "required": [
                        "ok",
                        "assignedCount",
                        "skippedCount"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.assign",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "orderIds": {
                    "type": "array",
                    "items": {},
                    "description": "欲批次派發的訂單 ID 陣列（1 至 100 筆）（max 100 · min 1）"
                  },
                  "assigneeUserId": {
                    "type": "string",
                    "description": "受派業務的使用者 ID（所有訂單派給同一人）（min 1）"
                  },
                  "reason": {
                    "type": "string",
                    "description": "派發事由說明（上限 500 字）（max 500）"
                  }
                },
                "required": [
                  "orderIds",
                  "assigneeUserId"
                ]
              }
            }
          }
        }
      }
    },
    "/orders/export": {
      "get": {
        "operationId": "get_orders_export",
        "tags": [
          "orders"
        ],
        "summary": "匯出訂單",
        "description": "GET /api/v1/orders/export — 匯出訂單（同 /api/v1/orders 的 filter + owner-scope，但取全頁）。\n重用 listAdminOrders（同 query/filter/scope，零漂移）經 collectAllPages 逐頁取全，帶安全\n上限；達上限回 `truncated: true`（CLI 應提示，不可無聲截斷）。owner-scope 一律由 bearer\n角色重推（deriveOrderScope），絕不信任 client。",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依訂單顯示狀態篩選（如 pending、paid、cancelled）"
            }
          },
          {
            "name": "assignment",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依派發狀態篩選（如 unassigned、assigned）"
            }
          },
          {
            "name": "rooming",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依分房狀態篩選"
            }
          },
          {
            "name": "dateFrom",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "出發日期區間起（格式 YYYY-MM-DD，含當日）"
            }
          },
          {
            "name": "dateTo",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "出發日期區間迄（格式 YYYY-MM-DD，含當日）"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "關鍵字搜尋（訂單編號、訂購人姓名或 Email 等）"
            }
          },
          {
            "name": "agencyId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依合作旅行社 ID 篩選（同業單）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "訂單 id（前綴 `ord_`）。"
                              },
                              "orderNumber": {
                                "type": "string",
                                "description": "人類可讀訂單編號（每租戶 sequence 產生，如 `20260707-0001`）。"
                              },
                              "bookingState": {
                                "type": "string",
                                "description": "預訂狀態（真相軸）：pending_payment → confirmed → completed；cancelled 為終態。"
                              },
                              "paymentState": {
                                "type": "string",
                                "description": "付款狀態（派生自分類帳、快取於此供過濾）：unpaid / partially_paid / deposit_paid / paid / overpaid。paid 只代表「應收被現金覆蓋」，不代表錢未退。"
                              },
                              "refundState": {
                                "type": "string",
                                "description": "退款狀態（派生快取，只算會影響應收的已付退款）：none / partially_refunded / refunded。"
                              },
                              "grossReceivableTwd": {
                                "type": "number",
                                "description": "應收（TWD 整數，派生自應收分類帳）。"
                              },
                              "collectedTwd": {
                                "type": "number",
                                "description": "收到現金（TWD 整數，派生）。"
                              },
                              "customerCashAppliedTwd": {
                                "type": "number",
                                "description": "客戶現金淨套用（收款減已退現金，TWD 整數，派生）。"
                              },
                              "outstandingTwd": {
                                "type": "number",
                                "description": "未收（應收減客戶現金淨套用，TWD 整數，派生）。"
                              },
                              "partySize": {
                                "type": "number",
                                "description": "參團人數（tour 訂單）。"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "訂單建立時間。"
                              },
                              "notes": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "訂單備註（未填 → null）。"
                              },
                              "userId": {
                                "type": "string",
                                "description": "下單客戶的 user id（同庫 user 表）。"
                              },
                              "userName": {
                                "type": "string",
                                "description": "下單客戶顯示名。"
                              },
                              "userEmail": {
                                "type": "string",
                                "description": "下單客戶 Email。"
                              },
                              "primaryTravelerName": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "主要旅客姓名（is_primary，未登記 → null）。"
                              },
                              "primaryTravelerPhone": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "主要旅客電話（未登記 → null）。"
                              },
                              "tripId": {
                                "type": "string",
                                "description": "行程 id（tour 訂單經梯次反查；lodging 為空字串）。"
                              },
                              "tripTitle": {
                                "type": "string",
                                "description": "行程 / 產品標題。"
                              },
                              "tripSlug": {
                                "type": "string",
                                "description": "行程 slug。"
                              },
                              "departureId": {
                                "type": "string",
                                "description": "梯次 id（tour 訂單；lodging 為空字串）。"
                              },
                              "departureDate": {
                                "type": "string",
                                "description": "出發日 YYYY-MM-DD（lodging 為入住日）。"
                              },
                              "returnDate": {
                                "type": "string",
                                "description": "回程日 YYYY-MM-DD（lodging 為退房日）。"
                              },
                              "assignedToUserId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "派發給哪位業務的 user id（未派發 → null）。"
                              },
                              "assigneeName": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "承辦業務顯示名（未派發 / 查無 → null）。"
                              },
                              "assignmentStatus": {
                                "type": "string",
                                "description": "派發狀態：unassigned / assigned / reassigned / pending_review。"
                              },
                              "assignedAt": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "format": "date-time",
                                "description": "最近一次派發時間（未派發 → null）。"
                              },
                              "assignedByUserId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "執行派發者的 user id（未派發 → null）。"
                              },
                              "createdByUserId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "S5: who created the order. null / equal to `userId` = customer self-service (自助下單); a staff id ≠ userId = 業務代訂 / K單. Distinct from assignment — a self-service order can still be assigned to a sales rep."
                              },
                              "pendingConsent": {
                                "type": "boolean",
                                "description": "是否尚缺最新版 PDPA 同意書簽署（true = 待客戶重簽）。"
                              },
                              "roomingStatus": {
                                "description": "分房狀態：由訂單旅客的分房偏好與已分配房間派生。 'unregistered' | 'registered' | 'needs_single' | 'assigned'。"
                              },
                              "lotteryState": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "抽籤狀態（null = FCFS 非抽籤）。'applied'|'won'|'lost'。"
                              },
                              "failoverFromOrderId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "備案單反查主單用：備案單的 failover_from_order_id 指向主單 id。"
                              },
                              "isOverdue": {
                                "type": "boolean",
                                "description": "逾期旗標：存在 status='open' 且 due_at 已過的收款計畫（未收齊的到期款）。 供列表列以 `bg-destructive/5` 標紅提示。由 OVERDUE_SUBSELECT 一次算回。"
                              }
                            },
                            "required": [
                              "id",
                              "orderNumber",
                              "bookingState",
                              "paymentState",
                              "refundState",
                              "grossReceivableTwd",
                              "collectedTwd",
                              "customerCashAppliedTwd",
                              "outstandingTwd",
                              "partySize",
                              "createdAt",
                              "notes",
                              "userId",
                              "userName",
                              "userEmail",
                              "primaryTravelerName",
                              "primaryTravelerPhone",
                              "tripId",
                              "tripTitle",
                              "tripSlug",
                              "departureId",
                              "departureDate",
                              "returnDate",
                              "assignedToUserId",
                              "assigneeName",
                              "assignmentStatus",
                              "assignedAt",
                              "assignedByUserId",
                              "createdByUserId",
                              "pendingConsent",
                              "roomingStatus",
                              "lotteryState",
                              "failoverFromOrderId",
                              "isOverdue"
                            ]
                          },
                          "description": "符合篩選條件的所有列（逐頁累積；達安全上限時截斷）。"
                        },
                        "total": {
                          "type": "number",
                          "description": "符合篩選條件的總筆數。"
                        },
                        "truncated": {
                          "type": "boolean",
                          "description": "是否因達安全上限而截斷（true 表未回傳完整結果，呼叫端應提示）。"
                        }
                      },
                      "required": [
                        "rows",
                        "total",
                        "truncated"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.read"
      }
    },
    "/orders/stats": {
      "get": {
        "operationId": "get_orders_stats",
        "tags": [
          "orders"
        ],
        "summary": "order KPI counts",
        "description": "GET /api/v1/orders/stats — order KPI counts (pending/paid/cancelled + this\nmonth's collected TWD), owner-scoped to the bearer user.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "pendingPayment": {
                          "type": "number",
                          "description": "待付款訂單數（未取消 / 未完成 / 未退款且 payment_state=unpaid）。"
                        },
                        "depositPaid": {
                          "type": "number",
                          "description": "已付訂金訂單數（payment_state=deposit_paid）。"
                        },
                        "paid": {
                          "type": "number",
                          "description": "已收齊訂單數（payment_state in paid/overpaid）。"
                        },
                        "cancelled": {
                          "type": "number",
                          "description": "已取消訂單數（booking_state=cancelled）。"
                        },
                        "refunded": {
                          "type": "number",
                          "description": "有退款的訂單數（refund_state in refunded/partially_refunded）。"
                        },
                        "completed": {
                          "type": "number",
                          "description": "已完成訂單數（booking_state=completed）。"
                        },
                        "thisMonthPaidTwd": {
                          "type": "number",
                          "description": "本月實收現金（payment_transactions direction=in 加總，TWD 整數）。"
                        },
                        "thisMonthNewOrders": {
                          "type": "number",
                          "description": "本月新建訂單數。"
                        },
                        "thisMonthCancelled": {
                          "type": "number",
                          "description": "本月取消訂單數。"
                        }
                      },
                      "required": [
                        "pendingPayment",
                        "depositPaid",
                        "paid",
                        "cancelled",
                        "refunded",
                        "completed",
                        "thisMonthPaidTwd",
                        "thisMonthNewOrders",
                        "thisMonthCancelled"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.read"
      }
    },
    "/payment-requests": {
      "get": {
        "operationId": "get_payment_requests",
        "tags": [
          "payment-requests"
        ],
        "summary": "list/search/filter 對外應付",
        "description": "GET /api/v1/payment-requests — list/search/filter 對外應付（payables）核簽工作流\n的請款單（the /admin/payment-requests table over HTTP）。Tenant-wide（無 owner\nscope）— 比照後台 payable.read gate。底層表 payables + payable_items。\nSee specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "submitted",
                "approved",
                "paid",
                "rejected",
                "cancelled",
                "all"
              ],
              "description": "依狀態篩選（draft 草稿 / submitted 已送審 / approved 已核准 / paid 已付款 / rejected 已退件 / cancelled 已取消 / all 全部）"
            }
          },
          {
            "name": "payeeType",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "supplier",
                "guide",
                "staff_commission",
                "other",
                "all"
              ],
              "description": "依收款對象類型篩選（supplier 供應商 / guide 領隊嚮導 / staff_commission 員工獎金 / other 其他 / all 全部）"
            }
          },
          {
            "name": "departureId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依關聯梯次 id 篩選"
            }
          },
          {
            "name": "createdByUserId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依建單人 user id 篩選"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "關鍵字搜尋（請款單號、收款對象名稱等）"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "頁碼（從 1 起算）"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "每頁筆數（上限 200）（max 200）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "請款單 ID。"
                              },
                              "requestNumber": {
                                "type": "string",
                                "description": "請款單號（人可讀，每租戶流水號）。"
                              },
                              "status": {
                                "description": "核簽工作流狀態：draft / submitted / approved / paid / rejected / cancelled。"
                              },
                              "payeeType": {
                                "description": "收款對象類型：supplier 供應商 / guide 領隊嚮導 / staff_commission 員工獎金 / other 其他。"
                              },
                              "payeeName": {
                                "type": "string",
                                "description": "收款對象名稱。"
                              },
                              "amountTwd": {
                                "type": "number",
                                "description": "請款總額（TWD 整數；= 細項小計合計，代扣稅前）。"
                              },
                              "netAmountTwd": {
                                "type": "number",
                                "description": "實付淨額（TWD 整數；= 請款總額 − 代扣稅額，即實際匯款金額）。"
                              },
                              "taxAmountTwd": {
                                "type": "number",
                                "description": "代扣稅額（TWD 整數）。"
                              },
                              "departureId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "關聯梯次 ID；未歸屬特定出團為 null。"
                              },
                              "departureLabel": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "關聯梯次顯示標籤（行程名稱＋出發日）；無則為 null。"
                              },
                              "description": {
                                "type": "string",
                                "description": "請款單摘要說明。"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "建立時間。"
                              },
                              "updatedAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "最後更新時間。"
                              },
                              "createdByUserId": {
                                "type": "string",
                                "description": "建單人 user ID。"
                              },
                              "createdByName": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "建單人姓名；查無為 null。"
                              },
                              "paidAt": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "format": "date-time",
                                "description": "標記付款完成時間；未付為 null。"
                              },
                              "submittedAt": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "format": "date-time",
                                "description": "送審時間；未送審為 null。"
                              },
                              "approvedAt": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "format": "date-time",
                                "description": "核准時間；未核准為 null。"
                              }
                            },
                            "required": [
                              "id",
                              "requestNumber",
                              "status",
                              "payeeType",
                              "payeeName",
                              "amountTwd",
                              "netAmountTwd",
                              "taxAmountTwd",
                              "departureId",
                              "departureLabel",
                              "description",
                              "createdAt",
                              "updatedAt",
                              "createdByUserId",
                              "createdByName",
                              "paidAt",
                              "submittedAt",
                              "approvedAt"
                            ]
                          },
                          "description": "本頁請款單列。"
                        },
                        "total": {
                          "type": "number",
                          "description": "符合篩選條件的總筆數（跨全部分頁）。"
                        },
                        "page": {
                          "type": "number",
                          "description": "目前頁碼（從 1 起算）。"
                        },
                        "pageSize": {
                          "type": "number",
                          "description": "每頁筆數。"
                        }
                      },
                      "required": [
                        "rows",
                        "total",
                        "page",
                        "pageSize"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payable.read"
      },
      "post": {
        "operationId": "post_payment_requests",
        "tags": [
          "payment-requests"
        ],
        "description": "GET /api/v1/payment-requests — list/search/filter 對外應付（payables）核簽工作流\n的請款單（the /admin/payment-requests table over HTTP）。Tenant-wide（無 owner\nscope）— 比照後台 payable.read gate。底層表 payables + payable_items。\nSee specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立請款單的 id。"
                        },
                        "requestNumber": {
                          "type": "string",
                          "description": "新建立請款單的單號（人可讀）。"
                        },
                        "status": {
                          "description": "建立後狀態（draft，或 submitImmediately 時為 submitted）。"
                        }
                      },
                      "required": [
                        "id",
                        "requestNumber",
                        "status"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payable.create",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "payeeType": {
                    "type": "string",
                    "enum": [
                      "supplier",
                      "guide",
                      "staff_commission",
                      "other"
                    ],
                    "description": "收款對象類型（supplier 供應商 / guide 領隊嚮導 / staff_commission 員工獎金 / other 其他）"
                  },
                  "payeeName": {
                    "type": "string",
                    "description": "收款對象名稱（min 1）"
                  },
                  "payeeBankAccount": {
                    "type": "string",
                    "description": "收款銀行帳號"
                  },
                  "payeeBankName": {
                    "type": "string",
                    "description": "收款銀行名稱"
                  },
                  "payeeBankBranch": {
                    "type": "string",
                    "description": "收款銀行分行"
                  },
                  "payeeTaxId": {
                    "type": "string",
                    "description": "收款對象統一編號 / 稅籍編號"
                  },
                  "departureId": {
                    "type": "string",
                    "description": "關聯梯次 id（將此請款歸屬至特定出團）"
                  },
                  "description": {
                    "type": "string",
                    "description": "請款單摘要說明（min 1）"
                  },
                  "taxAmountTwd": {
                    "type": "number",
                    "description": "稅額（TWD），未填視為 0"
                  },
                  "items": {
                    "type": "array",
                    "items": {},
                    "description": "請款細項陣列（至少一筆）（min 1）"
                  },
                  "submitImmediately": {
                    "type": "boolean",
                    "description": "是否建立後立即送審（true 則同交易送出，跳過草稿）"
                  }
                },
                "required": [
                  "payeeType",
                  "payeeName",
                  "description",
                  "items"
                ]
              }
            }
          }
        }
      }
    },
    "/payment-requests/{id}": {
      "get": {
        "operationId": "get_payment_requests_id_",
        "tags": [
          "payment-requests"
        ],
        "summary": "單一對外應付請款單完整明細",
        "description": "GET /api/v1/payment-requests/{id} — 單一對外應付請款單完整明細（header +\npayee 銀行資料 + 細項 payable_items + 狀態機時間戳 + audit trail）。\nTenant-wide（payable.read gate）；查無 → 404（避免洩漏存在性）。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "請款單 id（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "payeeBankAccount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "收款銀行帳號。"
                        },
                        "payeeBankName": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "收款銀行名稱。"
                        },
                        "payeeBankBranch": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "收款銀行分行。"
                        },
                        "payeeTaxId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "收款對象統一編號 / 稅籍編號。"
                        },
                        "submittedByUserId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "送審人 user ID；未送審為 null。"
                        },
                        "submittedByName": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "送審人姓名；無則為 null。"
                        },
                        "approvedByUserId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "核准人 user ID；未核准為 null。"
                        },
                        "approvedByName": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "核准人姓名；無則為 null。"
                        },
                        "paidByUserId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "標記付款人 user ID；未付為 null。"
                        },
                        "paidByName": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "標記付款人姓名；無則為 null。"
                        },
                        "rejectedAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "退件時間；未退件為 null。"
                        },
                        "rejectedByName": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "退件人姓名；無則為 null。"
                        },
                        "rejectionReason": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "退件原因；無則為 null。"
                        },
                        "cancelledAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "取消時間；未取消為 null。"
                        },
                        "cancelledByName": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "取消人姓名；無則為 null。"
                        },
                        "cancellationReason": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "取消原因；無則為 null。"
                        },
                        "pdfGeneratedAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "請款單 PDF 產生時間；未產生為 null。"
                        },
                        "paperPrintedAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "紙本列印時間；未列印為 null。"
                        },
                        "paperSignedBy": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "紙本簽核人；未簽為 null。"
                        },
                        "bankReference": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "銀行匯款交易參考號（付款後回填）；無則為 null。"
                        },
                        "items": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "請款細項 ID。"
                              },
                              "category": {
                                "type": "string",
                                "description": "細項類別（如住宿、交通、餐食）。"
                              },
                              "description": {
                                "type": "string",
                                "description": "細項說明。"
                              },
                              "quantity": {
                                "type": "number",
                                "description": "數量。"
                              },
                              "unitPriceTwd": {
                                "type": "number",
                                "description": "單價（TWD 整數；負值表折讓）。"
                              },
                              "totalTwd": {
                                "type": "number",
                                "description": "細項小計（TWD 整數；= 數量 × 單價）。"
                              },
                              "notes": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "細項備註；無則為 null。"
                              },
                              "sortOrder": {
                                "type": "number",
                                "description": "顯示排序（由小到大）。"
                              }
                            },
                            "required": [
                              "id",
                              "category",
                              "description",
                              "quantity",
                              "unitPriceTwd",
                              "totalTwd",
                              "notes",
                              "sortOrder"
                            ]
                          },
                          "description": "請款細項清單。"
                        },
                        "audit": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "稽核記錄 ID。"
                              },
                              "action": {
                                "type": "string",
                                "description": "動作代號（如 payable.create、payable.submit、payable.approve）。"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "動作發生時間。"
                              },
                              "actorUserId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "操作者 user ID；系統動作為 null。"
                              },
                              "actorName": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "操作者姓名；無則為 null。"
                              },
                              "metadata": {
                                "description": "動作附帶的結構化資料（欄位隨 action 而定）。"
                              },
                              "ipAddress": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "操作來源 IP；無則為 null。"
                              }
                            },
                            "required": [
                              "id",
                              "action",
                              "createdAt",
                              "actorUserId",
                              "actorName",
                              "metadata",
                              "ipAddress"
                            ]
                          },
                          "description": "稽核軌跡（狀態機每次轉移一筆，時間新到舊或建立序）。"
                        },
                        "id": {
                          "type": "string",
                          "description": "請款單 ID。"
                        },
                        "requestNumber": {
                          "type": "string",
                          "description": "請款單號（人可讀，每租戶流水號）。"
                        },
                        "status": {
                          "description": "核簽工作流狀態：draft / submitted / approved / paid / rejected / cancelled。"
                        },
                        "payeeType": {
                          "description": "收款對象類型：supplier 供應商 / guide 領隊嚮導 / staff_commission 員工獎金 / other 其他。"
                        },
                        "payeeName": {
                          "type": "string",
                          "description": "收款對象名稱。"
                        },
                        "amountTwd": {
                          "type": "number",
                          "description": "請款總額（TWD 整數；= 細項小計合計，代扣稅前）。"
                        },
                        "netAmountTwd": {
                          "type": "number",
                          "description": "實付淨額（TWD 整數；= 請款總額 − 代扣稅額，即實際匯款金額）。"
                        },
                        "taxAmountTwd": {
                          "type": "number",
                          "description": "代扣稅額（TWD 整數）。"
                        },
                        "departureId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "關聯梯次 ID；未歸屬特定出團為 null。"
                        },
                        "departureLabel": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "關聯梯次顯示標籤（行程名稱＋出發日）；無則為 null。"
                        },
                        "description": {
                          "type": "string",
                          "description": "請款單摘要說明。"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "建立時間。"
                        },
                        "updatedAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "最後更新時間。"
                        },
                        "createdByUserId": {
                          "type": "string",
                          "description": "建單人 user ID。"
                        },
                        "createdByName": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "建單人姓名；查無為 null。"
                        },
                        "paidAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "標記付款完成時間；未付為 null。"
                        },
                        "submittedAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "送審時間；未送審為 null。"
                        },
                        "approvedAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "核准時間；未核准為 null。"
                        }
                      },
                      "required": [
                        "payeeBankAccount",
                        "payeeBankName",
                        "payeeBankBranch",
                        "payeeTaxId",
                        "submittedByUserId",
                        "submittedByName",
                        "approvedByUserId",
                        "approvedByName",
                        "paidByUserId",
                        "paidByName",
                        "rejectedAt",
                        "rejectedByName",
                        "rejectionReason",
                        "cancelledAt",
                        "cancelledByName",
                        "cancellationReason",
                        "pdfGeneratedAt",
                        "paperPrintedAt",
                        "paperSignedBy",
                        "bankReference",
                        "items",
                        "audit",
                        "id",
                        "requestNumber",
                        "status",
                        "payeeType",
                        "payeeName",
                        "amountTwd",
                        "netAmountTwd",
                        "taxAmountTwd",
                        "departureId",
                        "departureLabel",
                        "description",
                        "createdAt",
                        "updatedAt",
                        "createdByUserId",
                        "createdByName",
                        "paidAt",
                        "submittedAt",
                        "approvedAt"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payable.read"
      }
    },
    "/payment-requests/{id}/approve": {
      "post": {
        "operationId": "post_payment_requests_id_approve",
        "tags": [
          "payment-requests"
        ],
        "summary": "核可請款單",
        "description": "POST /api/v1/payment-requests/{id}/approve — 核可請款單（submitted→approved）。\n鏡像 `approvePaymentRequestAction`：同 core op `approvePaymentRequestWithNotify`\n（核可 + best-effort 通知建單人，audit 在 op 內），同權限 `payable.approve`（責任\n分離：approve 與 create 不同權）。PaymentRequestStateError → NOT_FOUND 404 / 其餘 409。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "請款單 id（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否核可成功（submitted→approved）。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payable.approve"
      }
    },
    "/payment-requests/{id}/cancel": {
      "post": {
        "operationId": "post_payment_requests_id_cancel",
        "tags": [
          "payment-requests"
        ],
        "summary": "取消請款單",
        "description": "POST /api/v1/payment-requests/{id}/cancel — 取消請款單（非 paid；idempotent on\ncancelled）。Mirrors `cancelPaymentRequestAction`：同 payable.create gate、同\ncore fn `cancelPaymentRequest(db, { requestId, actorUserId, reason })`、audit\n在 core fn 內。\n\n責任分離 owner-scope 在 shell（非 core）：只有建單人或 admin 可取消。此處忠實\n複製該檢查——先 getPaymentRequestById 取 createdByUserId，非 admin 且非建單人 →\n403 forbidden（同後台訊息）。reason 預設「使用者取消」、上限 200 字。\nPaymentRequestStateError → NOT_FOUND 404 / 其餘（PAID_LOCKED 等）409 conflict。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "請款單 id（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否取消成功（idempotent，已取消再呼叫仍為 true）。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payable.create",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "description": "取消原因；留空預設為「使用者取消」（上限 200 字）"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/payment-requests/{id}/mark-paid": {
      "post": {
        "operationId": "post_payment_requests_id_mark_paid",
        "tags": [
          "payment-requests"
        ],
        "summary": "標記請款單已付",
        "description": "POST /api/v1/payment-requests/{id}/mark-paid — 標記請款單已付（approved→paid，\n記錄網銀交易序號 / 紙本簽核人 / 出款帳戶）。Mirrors\n`markPaymentRequestPaidAction`：同 payable.mark_paid gate、同 core fn\n`markPaymentRequestPaid(db, { requestId, actorUserId, bankReference,\npaperSignedBy, receivingAccountId })`、audit 在 core fn 內。\nPaymentRequestStateError → NOT_FOUND 404 / 其餘 409 conflict。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "請款單 id（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否標記付款成功（approved→paid）。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payable.mark_paid",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "bankReference": {
                    "type": "string",
                    "description": "網銀交易序號 / 轉帳憑證號（必填）（min 1）"
                  },
                  "paperSignedBy": {
                    "type": "string",
                    "description": "紙本簽核人姓名"
                  },
                  "receivingAccountId": {
                    "type": "string",
                    "description": "出款帳戶 id（從哪個收款帳戶付出）"
                  }
                },
                "required": [
                  "bankReference"
                ]
              }
            }
          }
        }
      }
    },
    "/payment-requests/{id}/mark-printed": {
      "post": {
        "operationId": "post_payment_requests_id_mark_printed",
        "tags": [
          "payment-requests"
        ],
        "summary": "標記 PDF/紙本已產生",
        "description": "POST /api/v1/payment-requests/{id}/mark-printed — 標記 PDF/紙本已產生\n（idempotent，更新時間戳）。Mirrors `markPdfGeneratedAction`：同 payable.print\ngate、同 core fn `markPdfGenerated(db, { requestId, actorUserId })`、audit 在\ncore fn 內。PaymentRequestStateError → NOT_FOUND 404 / 其餘 409 conflict。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "請款單 id（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否標記 PDF / 紙本已產生成功（idempotent）。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payable.print"
      }
    },
    "/payment-requests/{id}/mark-signed": {
      "post": {
        "operationId": "post_payment_requests_id_mark_signed",
        "tags": [
          "payment-requests"
        ],
        "summary": "記錄紙本簽核人",
        "description": "POST /api/v1/payment-requests/{id}/mark-signed — 記錄紙本簽核人。Mirrors\n`markPaperSignedAction`：同 payable.create gate、同 core fn\n`markPaperSignedBy(db, { requestId, actorUserId, signedBy })`、audit 在 core\nfn 內。PaymentRequestStateError → NOT_FOUND 404 / 其餘 409 conflict。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "請款單 id（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否記錄紙本簽核人成功。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payable.create",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "signedBy": {
                    "type": "string",
                    "description": "紙本簽核人姓名（必填）（min 1）"
                  }
                },
                "required": [
                  "signedBy"
                ]
              }
            }
          }
        }
      }
    },
    "/payment-requests/{id}/reject": {
      "post": {
        "operationId": "post_payment_requests_id_reject",
        "tags": [
          "payment-requests"
        ],
        "summary": "退件請款單",
        "description": "POST /api/v1/payment-requests/{id}/reject — 退件請款單（submitted→draft，記錄\n退件原因）。Mirrors `rejectPaymentRequestAction`：同 payable.approve gate、同\ncore fn `rejectPaymentRequest(db, { requestId, actorUserId, reason })`、audit\n在 core fn 內。PaymentRequestStateError → NOT_FOUND 404 / 其餘 409 conflict。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "請款單 id（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否退件成功（submitted→draft）。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payable.approve",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "description": "退件原因（必填，回饋給建單人）（min 1）"
                  }
                },
                "required": [
                  "reason"
                ]
              }
            }
          }
        }
      }
    },
    "/payment-requests/{id}/submit": {
      "post": {
        "operationId": "post_payment_requests_id_submit",
        "tags": [
          "payment-requests"
        ],
        "summary": "送審請款單",
        "description": "POST /api/v1/payment-requests/{id}/submit — 送審請款單（draft→submitted）。\nMirrors `submitPaymentRequestAction`：同 payable.create gate、同 core fn\n`submitPaymentRequest(db, { requestId, actorUserId })`、audit 在 core fn 內。\nPaymentRequestStateError → NOT_FOUND 404 / 其餘 409 conflict。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "請款單 id（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否送審成功（draft→submitted）。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payable.create"
      }
    },
    "/payment-requests/stats": {
      "get": {
        "operationId": "get_payment_requests_stats",
        "tags": [
          "payment-requests"
        ],
        "summary": "對外應付請款單 KPI 計數",
        "description": "GET /api/v1/payment-requests/stats — 對外應付請款單 KPI 計數（draft/submitted/\napproved/paid + 本月已付筆數/金額 + 已核准未付金額）。Tenant-wide（payable.read gate）。",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "draftCount": {
                          "type": "number",
                          "description": "草稿狀態的請款單數。"
                        },
                        "submittedCount": {
                          "type": "number",
                          "description": "已送審待核准的請款單數。"
                        },
                        "approvedCount": {
                          "type": "number",
                          "description": "已核准待付款的請款單數。"
                        },
                        "paidCount": {
                          "type": "number",
                          "description": "已付款的請款單數。"
                        },
                        "thisMonthPaidCount": {
                          "type": "number",
                          "description": "本月已付款的請款單數。"
                        },
                        "thisMonthAmount": {
                          "type": "number",
                          "description": "本月已付款的實付淨額合計（TWD 整數；台北月起算）。"
                        },
                        "totalApprovedAmount": {
                          "type": "number",
                          "description": "已核准未付的實付淨額合計（TWD 整數；待出款金額）。"
                        }
                      },
                      "required": [
                        "draftCount",
                        "submittedCount",
                        "approvedCount",
                        "paidCount",
                        "thisMonthPaidCount",
                        "thisMonthAmount",
                        "totalApprovedAmount"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payable.read"
      }
    },
    "/payment-requests/supplier-suggestions": {
      "get": {
        "operationId": "get_payment_requests_supplier_suggestions",
        "tags": [
          "payment-requests"
        ],
        "summary": "由某梯次的",
        "description": "GET /api/v1/payment-requests/supplier-suggestions?departureId=… — 由某梯次的\ndeparture_rooms 推導供應商請款細項建議（住宿廠商 × 間數 / 晚數 / 成本），供建單\n時帶入。Gated payable.create（建單前置動作）。底層 reuse\nsuggestSupplierItemsForDeparture。",
        "parameters": [
          {
            "name": "departureId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 id；用於推導該梯次住宿供應商的請款細項建議（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "category": {
                            "type": "string",
                            "description": "建議的請款細項類別（如住宿）。"
                          },
                          "description": {
                            "type": "string",
                            "description": "建議的細項說明（住宿廠商 × 房型 × 晚數）。"
                          },
                          "quantity": {
                            "type": "number",
                            "description": "建議數量（間數 × 晚數）。"
                          },
                          "unitPriceTwd": {
                            "type": "number",
                            "description": "建議單價（TWD 整數；每間每晚成本）。"
                          },
                          "totalTwd": {
                            "type": "number",
                            "description": "建議小計（TWD 整數；= 數量 × 單價）。"
                          },
                          "suggestedPayee": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "建議的收款對象（住宿供應商名稱）；查無為 null。"
                          }
                        },
                        "required": [
                          "category",
                          "description",
                          "quantity",
                          "unitPriceTwd",
                          "totalTwd",
                          "suggestedPayee"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payable.create"
      }
    },
    "/payments": {
      "get": {
        "operationId": "get_payments",
        "tags": [
          "payments"
        ],
        "summary": "list/search/filter the customer→agency payment ledger",
        "description": "GET /api/v1/payments — list/search/filter the customer→agency payment ledger\n(the /admin/payments table over HTTP). Rows hang off payment_attempts; amount\ncomes from the intent, paidAt is backfilled once settled. Tenant-wide read\n(payment.read) — no owner scope. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依金流狀態篩選（如 paid 已收款 / pending 待付 / failed 失敗 / refunded 已退款）"
            }
          },
          {
            "name": "method",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依付款方式篩選（如信用卡、ATM 轉帳）"
            }
          },
          {
            "name": "dateFrom",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "收款日期區間起日（YYYY-MM-DD）"
            }
          },
          {
            "name": "dateTo",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "收款日期區間迄日（YYYY-MM-DD）"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "關鍵字搜尋（訂單編號、客戶名稱等）"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "頁碼（從 1 起算）"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "每頁筆數（上限 200）（max 200）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "付款嘗試（payment attempt）ID，此列的唯一識別。"
                              },
                              "orderId": {
                                "type": "string",
                                "description": "所屬訂單 ID。"
                              },
                              "orderNumber": {
                                "type": "string",
                                "description": "所屬訂單編號（人可讀）。"
                              },
                              "merchantTradeNo": {
                                "type": "string",
                                "description": "provider_order_ref（= 我們產的 MerchantTradeNo）。"
                              },
                              "providerTradeNo": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "金流商回傳的交易序號（未成交或手動入帳為 null）。"
                              },
                              "provider": {
                                "type": "string",
                                "description": "金流商代號（如 ecpay、test；手動入帳為 manual）。"
                              },
                              "paymentMethod": {
                                "type": "string",
                                "description": "付款方式（如信用卡、ATM 虛擬帳號）。"
                              },
                              "amountTwd": {
                                "type": "number",
                                "description": "此筆嘗試的金額（TWD 整數）。"
                              },
                              "status": {
                                "type": "string",
                                "description": "attempt 狀態：pending | submitted | succeeded | failed | expired。"
                              },
                              "refunded": {
                                "type": "boolean",
                                "description": "此 attempt 是否關聯到任何退款 / 退單交易（out 方向）。"
                              },
                              "paidAt": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "format": "date-time",
                                "description": "實際入帳（現金結算）時間；未結算為 null。"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "此筆付款嘗試的建立時間。"
                              },
                              "customerName": {
                                "type": "string",
                                "description": "付款客戶姓名。"
                              },
                              "customerEmail": {
                                "type": "string",
                                "description": "付款客戶 email。"
                              },
                              "tripTitle": {
                                "type": "string",
                                "description": "訂單對應的行程名稱。"
                              }
                            },
                            "required": [
                              "id",
                              "orderId",
                              "orderNumber",
                              "merchantTradeNo",
                              "providerTradeNo",
                              "provider",
                              "paymentMethod",
                              "amountTwd",
                              "status",
                              "refunded",
                              "paidAt",
                              "createdAt",
                              "customerName",
                              "customerEmail",
                              "tripTitle"
                            ]
                          },
                          "description": "本頁付款嘗試列。"
                        },
                        "total": {
                          "type": "number",
                          "description": "符合篩選條件的總筆數（跨全部分頁）。"
                        },
                        "page": {
                          "type": "number",
                          "description": "目前頁碼（從 1 起算）。"
                        },
                        "pageSize": {
                          "type": "number",
                          "description": "每頁筆數。"
                        }
                      },
                      "required": [
                        "rows",
                        "total",
                        "page",
                        "pageSize"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payment.read"
      }
    },
    "/payments/export": {
      "get": {
        "operationId": "get_payments_export",
        "tags": [
          "payments"
        ],
        "summary": "匯出金流分類帳",
        "description": "GET /api/v1/payments/export — 匯出金流分類帳（同 /api/v1/payments 的 filter，但取全頁）。\n重用 listPayments（同 query/filter，零漂移）經 collectAllPages 逐頁取全，帶安全上限；達上限\n回 `truncated: true`（CLI 應提示）。tenant-wide read（payment.read）。",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依金流狀態篩選（如 paid 已收款 / pending 待付 / failed 失敗 / refunded 已退款）"
            }
          },
          {
            "name": "method",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依付款方式篩選（如信用卡、ATM 轉帳）"
            }
          },
          {
            "name": "dateFrom",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "收款日期區間起日（YYYY-MM-DD）"
            }
          },
          {
            "name": "dateTo",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "收款日期區間迄日（YYYY-MM-DD）"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "關鍵字搜尋（訂單編號、客戶名稱等）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "付款嘗試（payment attempt）ID，此列的唯一識別。"
                              },
                              "orderId": {
                                "type": "string",
                                "description": "所屬訂單 ID。"
                              },
                              "orderNumber": {
                                "type": "string",
                                "description": "所屬訂單編號（人可讀）。"
                              },
                              "merchantTradeNo": {
                                "type": "string",
                                "description": "provider_order_ref（= 我們產的 MerchantTradeNo）。"
                              },
                              "providerTradeNo": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "金流商回傳的交易序號（未成交或手動入帳為 null）。"
                              },
                              "provider": {
                                "type": "string",
                                "description": "金流商代號（如 ecpay、test；手動入帳為 manual）。"
                              },
                              "paymentMethod": {
                                "type": "string",
                                "description": "付款方式（如信用卡、ATM 虛擬帳號）。"
                              },
                              "amountTwd": {
                                "type": "number",
                                "description": "此筆嘗試的金額（TWD 整數）。"
                              },
                              "status": {
                                "type": "string",
                                "description": "attempt 狀態：pending | submitted | succeeded | failed | expired。"
                              },
                              "refunded": {
                                "type": "boolean",
                                "description": "此 attempt 是否關聯到任何退款 / 退單交易（out 方向）。"
                              },
                              "paidAt": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "format": "date-time",
                                "description": "實際入帳（現金結算）時間；未結算為 null。"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "此筆付款嘗試的建立時間。"
                              },
                              "customerName": {
                                "type": "string",
                                "description": "付款客戶姓名。"
                              },
                              "customerEmail": {
                                "type": "string",
                                "description": "付款客戶 email。"
                              },
                              "tripTitle": {
                                "type": "string",
                                "description": "訂單對應的行程名稱。"
                              }
                            },
                            "required": [
                              "id",
                              "orderId",
                              "orderNumber",
                              "merchantTradeNo",
                              "providerTradeNo",
                              "provider",
                              "paymentMethod",
                              "amountTwd",
                              "status",
                              "refunded",
                              "paidAt",
                              "createdAt",
                              "customerName",
                              "customerEmail",
                              "tripTitle"
                            ]
                          },
                          "description": "符合篩選條件的所有列（逐頁累積；達安全上限時截斷）。"
                        },
                        "total": {
                          "type": "number",
                          "description": "符合篩選條件的總筆數。"
                        },
                        "truncated": {
                          "type": "boolean",
                          "description": "是否因達安全上限而截斷（true 表未回傳完整結果，呼叫端應提示）。"
                        }
                      },
                      "required": [
                        "rows",
                        "total",
                        "truncated"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payment.read"
      }
    },
    "/payments/stats": {
      "get": {
        "operationId": "get_payments_stats",
        "tags": [
          "payments"
        ],
        "summary": "payment KPI counts",
        "description": "GET /api/v1/payments/stats — payment KPI counts (paid/pending/failed/refunded\n+ total collected cash + this month's collected TWD). Tenant-wide read\n(payment.read) — no owner scope.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "totalAmount": {
                          "type": "number",
                          "description": "累計實收現金（payment_transactions in）。"
                        },
                        "paidCount": {
                          "type": "number",
                          "description": "已成功收款的付款嘗試數。"
                        },
                        "pendingCount": {
                          "type": "number",
                          "description": "待付 / 處理中的付款嘗試數（pending、submitted）。"
                        },
                        "failedCount": {
                          "type": "number",
                          "description": "失敗或逾期的付款嘗試數（failed、expired）。"
                        },
                        "refundedCount": {
                          "type": "number",
                          "description": "有關聯退款 / 退單的付款嘗試數。"
                        },
                        "thisMonthAmount": {
                          "type": "number",
                          "description": "本月累計實收現金（TWD 整數）。"
                        }
                      },
                      "required": [
                        "totalAmount",
                        "paidCount",
                        "pendingCount",
                        "failedCount",
                        "refundedCount",
                        "thisMonthAmount"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payment.read"
      }
    },
    "/payouts/aggregate": {
      "get": {
        "operationId": "get_payouts_aggregate",
        "tags": [
          "payouts"
        ],
        "summary": "派生當月",
        "description": "GET /api/v1/payouts/aggregate — 派生當月（period）已核准未付 payable 依收款對象\ngroup 成出款列（建批前的 preview）。tenant-wide（出納面），無 owner-scope。\npayeeScope = guide | supplier | staff。回傳的 payeeRefId 即建批時 lines 的 group key。",
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "出款月份（YYYY-MM），彙整該月已核准未付的應付（格式限定）"
            }
          },
          {
            "name": "scope",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "guide",
                "supplier",
                "staff"
              ],
              "description": "收款對象範圍（guide 領隊嚮導 / supplier 供應商 / staff 員工）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "payeeType": {
                            "description": "收款對象類型：guide 領隊嚮導 / supplier 供應商 / staff 員工。"
                          },
                          "payeeRefId": {
                            "type": "string",
                            "description": "收款對象識別 key：供應商為其 ID，領隊 / 員工為收款人姓名。"
                          },
                          "payeeName": {
                            "type": "string",
                            "description": "收款對象名稱。"
                          },
                          "payeeAccountName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "收款人戶名（supplier 取 suppliers / guide 取 guides；staff 暫無主檔 → null）。"
                          },
                          "payeeBankCode": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "收款銀行代號（同上來源；無主檔為 null）。"
                          },
                          "payeeAccountNumber": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "收款帳號（同上來源；無主檔為 null，遮罩回傳）。"
                          },
                          "grossTwd": {
                            "type": "number",
                            "description": "當月已核准未付的請款單淨額合計（TWD 整數）。"
                          },
                          "items": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "payableId": {
                                  "type": "string",
                                  "description": "請款單 ID。"
                                },
                                "payableNumber": {
                                  "type": "string",
                                  "description": "請款單人類可讀單號。"
                                },
                                "date": {
                                  "type": [
                                    "string",
                                    "null"
                                  ],
                                  "description": "梯次出發日（'YYYY-MM-DD'）；無連梯次時 null。"
                                },
                                "tripLabel": {
                                  "type": [
                                    "string",
                                    "null"
                                  ],
                                  "description": "團名；無連梯次時 null。"
                                },
                                "amountTwd": {
                                  "type": "number",
                                  "description": "該請款單的應付淨額（TWD 整數）。"
                                }
                              },
                              "required": [
                                "payableId",
                                "payableNumber",
                                "date",
                                "tripLabel",
                                "amountTwd"
                              ]
                            },
                            "description": "彙整明細（日期 + 團名 + 金額，唯讀派生，不另存）。"
                          }
                        },
                        "required": [
                          "payeeType",
                          "payeeRefId",
                          "payeeName",
                          "payeeAccountName",
                          "payeeBankCode",
                          "payeeAccountNumber",
                          "grossTwd",
                          "items"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "supplier.read",
        "x-module": "accounting"
      }
    },
    "/payouts/batches": {
      "post": {
        "operationId": "post_payouts_batches",
        "tags": [
          "payouts"
        ],
        "summary": "建立出款批次草稿",
        "description": "POST /api/v1/payouts/batches — 建立出款批次草稿（control-finance §5.5）。\n\n把選定的彙整列（gross + 通用扣款項）持久化成 draft batch + payout_batch_lines\n（net = gross − Σ deductions）；**不在此 mark paid**（留 confirm 階段）。Mirrors\n`createPayoutBatchAction`：同 `supplier.read` 閘、同 `createPayoutBatch` core fn +\n同參數（actorUserId）、同 accounting-module fail-closed gate。core 內部寫 audit\n（`payout_batch.create`），route 不另行 replicate。PayoutBatchError → 409（errors.ts\nCONFLICT_ERROR_NAMES）。`lines` 直接以 JSON body 帶入（非 FormData）。",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立出款批次的 ID（pob_ 前綴）。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "supplier.read",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "period": {
                    "type": "string",
                    "description": "出款月份（YYYY-MM）（格式限定）"
                  },
                  "payeeScope": {
                    "type": "string",
                    "description": "收款對象範圍（guide 領隊嚮導 / supplier 供應商 / staff 員工）"
                  },
                  "paidFromAccountId": {
                    "type": "string",
                    "description": "出帳帳戶 id（從哪個收款帳戶付出）；可留空待確認時指定（min 1）"
                  },
                  "lines": {
                    "type": "array",
                    "items": {},
                    "description": "納入批次的出款列（至少一列）（min 1）"
                  }
                },
                "required": [
                  "period",
                  "payeeScope",
                  "lines"
                ]
              }
            }
          }
        }
      }
    },
    "/payouts/batches/{id}/confirm": {
      "post": {
        "operationId": "post_payouts_batches_id_confirm",
        "tags": [
          "payouts"
        ],
        "summary": "確認出款批次",
        "description": "POST /api/v1/payouts/batches/{id}/confirm — 確認出款批次（draft → confirmed，§5.5）。\n\n把該批次每列收款對象當月 approved 未付 payable 一併 mark paid + 依 net 記出帳進對帳。\nMirrors `confirmPayoutBatchAction`：同 `payable.mark_paid` 閘（admin / accountant）、同\n`confirmPayoutBatch(db, batchId, { actorUserId, bankReference })` core fn + 同參數、同\naccounting-module fail-closed gate。core 內部寫 audit，route 不另行 replicate。\nPayoutBatchError → 409（errors.ts CONFLICT_ERROR_NAMES）。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "出款批次 id（路徑參數，格式 pob_…）（格式限定）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：出款批次已確認送出。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payable.mark_paid",
        "x-module": "accounting",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "bankReference": {
                    "type": "string",
                    "description": "網銀交易序號 / 轉帳憑證號（可選）（max 64）"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/payouts/batches/{id}/transfer-file": {
      "get": {
        "operationId": "get_payouts_batches_id_transfer_file",
        "tags": [
          "payouts"
        ],
        "summary": "出款批次的標準四欄批次轉帳檔",
        "description": "GET /api/v1/payouts/batches/{id}/transfer-file — 出款批次的標準四欄批次轉帳檔。\n從 batch 的 confirmed 列攤平（戶名 / 帳號 / 銀行代號 / 金額）；缺三欄者整批 fail-closed。\n\n輸出收款帳號「明文」(unmasked)，故閘比 supplier.read 嚴 → payable.mark_paid（出納面）。\nformat=json（預設）→ 完整 BatchTransferExport（含 csv / clipboardTsv 欄）；\nformat=csv → 只回 { csv } 字串，方便 CLI 直接寫檔。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "出款批次 id（路徑參數）（min 1）"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "csv",
                "json"
              ],
              "description": "輸出格式：json 完整匯出（預設）或 csv 僅回傳轉帳檔字串"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {}
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "payable.mark_paid",
        "x-module": "accounting"
      }
    },
    "/payouts/lines/{lineId}/confirm-token": {
      "post": {
        "operationId": "post_payouts_lines_lineId_confirm_token",
        "tags": [
          "payouts"
        ],
        "summary": "為某出款批次列簽發廠商自助確認",
        "description": "POST /api/v1/payouts/lines/{lineId}/confirm-token — 為某出款批次列簽發廠商自助確認\ntoken（§5.5；對外頁 /supplier-confirm/[token]）。idempotent：已簽發回原 token。\n\nMirrors `issueSupplierConfirmTokenAction`：同 `supplier.read` 閘、同\n`issueSupplierConfirmToken(db, lineId)` core fn、同 accounting-module fail-closed gate。\n差別：web shell 丟棄 token（client 另讀頁取 confirmUrl），CLI/API 無頁面上下文，故\n**回傳 token**（非機密 PII / 密碼，是操作者本就可見的確認連結 token）。token→URL 的\ncanonical-host 拼接邏輯留在 page.tsx，CLI 端自行組裝。PayoutBatchError → 409。",
        "parameters": [
          {
            "name": "lineId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "出款批次列 id（路徑參數，格式 pobl_…）（格式限定）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "token": {
                          "type": "string",
                          "description": "廠商自助確認 token（拼成對外確認頁網址；idempotent，重複簽發回原 token）。"
                        }
                      },
                      "required": [
                        "token"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "supplier.read",
        "x-module": "accounting"
      }
    },
    "/payouts/remit-accounts": {
      "get": {
        "operationId": "get_payouts_remit_accounts",
        "tags": [
          "payouts"
        ],
        "summary": "出款批次的「出帳帳戶」選項",
        "description": "GET /api/v1/payouts/remit-accounts — 出款批次的「出帳帳戶」選項（收款帳戶目錄）。\n建批 / 確認批時指定 paid_from_account。tenant-wide，無 owner-scope。",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "收款帳戶 ID。"
                          },
                          "code": {
                            "type": "string",
                            "description": "帳戶代碼（租戶內唯一穩定識別）。"
                          },
                          "displayName": {
                            "type": "string",
                            "description": "帳戶顯示名。"
                          },
                          "kind": {
                            "description": "帳戶類型：bank 銀行 / cash 現金 / gateway 金流閘道。"
                          },
                          "bankName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "銀行名稱；現金／閘道帳戶為 null。"
                          },
                          "accountNo": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "銀行帳號；現金／閘道帳戶為 null。"
                          },
                          "canReceive": {
                            "type": "boolean",
                            "description": "可收款（幾乎都 true）。"
                          },
                          "canRemit": {
                            "type": "boolean",
                            "description": "可對外匯款（ATM / 匯出退款 / 補款匯出）。荒野只有永豐。"
                          },
                          "canChargeback": {
                            "type": "boolean",
                            "description": "可刷退（退回原信用卡）。荒野只有綠界（gateway）。"
                          },
                          "isDeprecated": {
                            "type": "boolean",
                            "description": "廢帳戶：仍可零星收款，但其收款需由他帳戶代墊歸集。荒野＝RU 台銀 / 登山社。"
                          },
                          "isSettlementMaster": {
                            "type": "boolean",
                            "description": "主結算帳戶：所有資金最終向它彙整。每租戶恰一個（partial unique index）。荒野＝永豐。"
                          },
                          "currency": {
                            "type": "string",
                            "description": "帳戶幣別（ISO 4217；既有帳戶皆 'TWD'，外幣帳戶如 IDR / USD）。"
                          },
                          "isActive": {
                            "type": "boolean",
                            "description": "此帳戶是否啟用。"
                          },
                          "displayOrder": {
                            "type": "number",
                            "description": "後台清單排序序位（小者在前）。"
                          },
                          "usedCount": {
                            "type": "number",
                            "description": "被多少 payment_transactions 引用（UI 鎖頭 / 「使用中 N」）。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          }
                        },
                        "required": [
                          "id",
                          "code",
                          "displayName",
                          "kind",
                          "bankName",
                          "accountNo",
                          "canReceive",
                          "canRemit",
                          "canChargeback",
                          "isDeprecated",
                          "isSettlementMaster",
                          "currency",
                          "isActive",
                          "displayOrder",
                          "usedCount",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "supplier.read",
        "x-module": "accounting"
      }
    },
    "/pnl/expense-categories": {
      "get": {
        "operationId": "get_pnl_expense_categories",
        "tags": [
          "pnl"
        ],
        "summary": "list the company expense-category",
        "description": "GET /api/v1/pnl/expense-categories — list the company expense-category\ncatalog (per-tenant, kind-bucketed: opex / tax / platform_fee / special).\n`--active-only` returns only enabled rows (the expense-register dropdown\nview); default includes disabled rows (the settings view). Accounting-module-\ngated server-side (fail-closed). See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "activeOnly",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "是否只回傳啟用中的費用類別；預設含停用列"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "費用類別 ID。"
                          },
                          "code": {
                            "type": "string",
                            "description": "科目代碼（租戶內唯一穩定識別，如 rent / salary_admin / tax_vat）。"
                          },
                          "displayName": {
                            "type": "string",
                            "description": "顯示名（如 房租 / 行政薪資 / 營業稅）。"
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "opex",
                              "tax",
                              "platform_fee",
                              "special"
                            ],
                            "description": "費用大類：opex 營業費用 / tax 稅 / platform_fee 平台手續費 / special 特殊損益（損益表據此 roll-up）。"
                          },
                          "isActive": {
                            "type": "boolean",
                            "description": "是否啟用（停用不刪，既有費用列仍引用得到）。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          }
                        },
                        "required": [
                          "id",
                          "code",
                          "displayName",
                          "kind",
                          "isActive",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "operating_expense.read"
      }
    },
    "/pnl/expenses": {
      "get": {
        "operationId": "get_pnl_expenses",
        "tags": [
          "pnl"
        ],
        "summary": "list company operating-expense ledger rows",
        "description": "GET /api/v1/pnl/expenses — list company operating-expense ledger rows\n(/admin/pnl/operating-expenses over HTTP), filterable by period / kind /\ncategory. Returns RAW rows (raw ints); the page-layer viaBatch/special\ncuration is a presentation concern the caller filters, not re-implemented per\ntransport. Accounting-module-gated server-side (fail-closed) before any read.\nSee specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "歸屬月（格式 YYYY-MM）；只列出該月的費用"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "費用類別 ID；只列出該類別的費用"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "opex",
                "tax",
                "platform_fee",
                "special"
              ],
              "description": "費用大類：opex 營業費用、tax 稅、platform_fee 平台手續費、special 特殊損益"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "費用列 ID。"
                          },
                          "categoryId": {
                            "type": "string",
                            "description": "費用科目 ID。"
                          },
                          "categoryCode": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "費用科目代碼（如 rent / salary_admin）。"
                          },
                          "categoryDisplayName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "費用科目顯示名。"
                          },
                          "categoryKind": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "費用科目大類（opex / tax / platform_fee / special）。"
                          },
                          "period": {
                            "type": "string",
                            "description": "歸屬月（YYYY-MM，損益表據此彙整；可與支付日不同月）。"
                          },
                          "incurredOn": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "發生 / 支付日期（YYYY-MM-DD）；金流商內扣 / 攤提無單一發生日者為 null。"
                          },
                          "amountTwd": {
                            "type": "number",
                            "description": "金額（整數 TWD）。"
                          },
                          "description": {
                            "type": "string",
                            "description": "摘要（廠商 / 品名，如 台中房租 / 委外廣告投放）。"
                          },
                          "paidFromAccountId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "出帳帳戶 ID；金流商內扣者為 null。"
                          },
                          "paidFromAccountName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "出帳帳戶顯示名。"
                          },
                          "frontedByUserId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "代墊者 user ID；非空代表由此人代墊待回補（走請款回補代墊者）。"
                          },
                          "frontedByName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "代墊者姓名。"
                          },
                          "payableId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "若走出款核簽，連結的請款單 ID；否則 null。"
                          },
                          "payableNumber": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "連結請款單的人類可讀單號。"
                          },
                          "recurring": {
                            "type": "boolean",
                            "description": "月固定標記（人工登記時備註「月固定」；自動生成走範本表，非此欄）。"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "confirmed",
                              "draft"
                            ],
                            "description": "'draft'（月固定範本自動生成、待確認，不入損益）| 'confirmed'（計入損益）。"
                          },
                          "origin": {
                            "type": "string",
                            "enum": [
                              "manual",
                              "recurring",
                              "departure_conversion"
                            ],
                            "description": "'manual'（手動登記）| 'recurring'（月固定範本自動生成）| 'departure_conversion'（取消梯次結轉，§3.4）。"
                          },
                          "sourceTemplateId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "生成來源範本（origin='recurring'）；手動登記為 null。"
                          },
                          "note": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "備註。"
                          },
                          "createdByUserId": {
                            "type": "string",
                            "description": "經手人 user ID（建立此費用列者）。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          }
                        },
                        "required": [
                          "id",
                          "categoryId",
                          "categoryCode",
                          "categoryDisplayName",
                          "categoryKind",
                          "period",
                          "incurredOn",
                          "amountTwd",
                          "description",
                          "paidFromAccountId",
                          "paidFromAccountName",
                          "frontedByUserId",
                          "frontedByName",
                          "payableId",
                          "payableNumber",
                          "recurring",
                          "status",
                          "origin",
                          "sourceTemplateId",
                          "note",
                          "createdByUserId",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "operating_expense.read"
      },
      "post": {
        "operationId": "post_pnl_expenses",
        "tags": [
          "pnl"
        ],
        "description": "GET /api/v1/pnl/expenses — list company operating-expense ledger rows\n(/admin/pnl/operating-expenses over HTTP), filterable by period / kind /\ncategory. Returns RAW rows (raw ints); the page-layer viaBatch/special\ncuration is a presentation concern the caller filters, not re-implemented per\ntransport. Accounting-module-gated server-side (fail-closed) before any read.\nSee specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：營業費用列已新增。"
                        },
                        "id": {
                          "type": "string",
                          "description": "新建立營業費用列的 ID（opx_ 前綴）。"
                        }
                      },
                      "required": [
                        "ok",
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "operating_expense.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "categoryId": {
                    "type": "string",
                    "description": "費用類別 ID（對應公司費用類別目錄）（min 1）"
                  },
                  "period": {
                    "type": "string",
                    "description": "歸屬月（格式 YYYY-MM），供月損益表彙整（格式限定）"
                  },
                  "description": {
                    "type": "string",
                    "description": "費用摘要（min 1）"
                  },
                  "amountTwd": {
                    "type": "number",
                    "description": "費用金額（台幣非負整數）"
                  },
                  "incurredOn": {
                    "type": "string",
                    "description": "費用發生日期（格式 YYYY-MM-DD）"
                  },
                  "paidFromAccountId": {
                    "type": "string",
                    "description": "支付來源帳戶 ID"
                  },
                  "frontedByUserId": {
                    "type": "string",
                    "description": "代墊人使用者 ID（由員工先行墊付時填寫）"
                  },
                  "note": {
                    "type": "string",
                    "description": "備註"
                  },
                  "recurring": {
                    "type": "boolean",
                    "description": "是否為週期性費用"
                  }
                },
                "required": [
                  "categoryId",
                  "period",
                  "description",
                  "amountTwd"
                ]
              }
            }
          }
        }
      }
    },
    "/pnl/expenses/{id}": {
      "patch": {
        "operationId": "patch_pnl_expenses_id_",
        "tags": [
          "pnl"
        ],
        "summary": "更正一筆公司營業費用",
        "description": "PATCH /api/v1/pnl/expenses/{id} — 更正一筆公司營業費用（整列覆寫；非 append-only）。\n鏡像 `updateOperatingExpenseAction`：同 core op `updateOperatingExpense`（FOR UPDATE\n鎖 + audit 含金額 diff），同權限 `operating_expense.manage` + 進階會計模組閘。\npayableId 是核簽連結，整列覆寫時須原樣帶回（省略 → 清成 null）。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "營業費用列 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：營業費用列已更新。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "operating_expense.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "categoryId": {
                    "type": "string",
                    "description": "費用類別 ID（對應公司費用類別目錄）（min 1）"
                  },
                  "period": {
                    "type": "string",
                    "description": "歸屬月（格式 YYYY-MM），供月損益表彙整（格式限定）"
                  },
                  "description": {
                    "type": "string",
                    "description": "費用摘要（min 1）"
                  },
                  "amountTwd": {
                    "type": "number",
                    "description": "費用金額（台幣非負整數）"
                  },
                  "incurredOn": {
                    "type": "string",
                    "description": "費用發生日期（格式 YYYY-MM-DD）"
                  },
                  "paidFromAccountId": {
                    "type": "string",
                    "description": "支付來源帳戶 ID"
                  },
                  "frontedByUserId": {
                    "type": "string",
                    "description": "代墊人使用者 ID（由員工先行墊付時填寫）"
                  },
                  "note": {
                    "type": "string",
                    "description": "備註"
                  },
                  "recurring": {
                    "type": "boolean",
                    "description": "是否為週期性費用"
                  },
                  "payableId": {
                    "type": "string",
                    "description": "關聯的請款核簽 ID；整列覆寫時須原樣帶回，省略則清為 null"
                  }
                },
                "required": [
                  "categoryId",
                  "period",
                  "description",
                  "amountTwd"
                ]
              }
            }
          }
        }
      }
    },
    "/pnl/statement": {
      "get": {
        "operationId": "get_pnl_statement",
        "tags": [
          "pnl"
        ],
        "summary": "the company monthly P&L statement",
        "description": "GET /api/v1/pnl/statement?period=YYYY-MM — the company monthly P&L statement\n(各區毛利 + 其他收入 − 公司營業費用 ± 特殊損益 = 公司淨利). Pure read derivation;\nreturns RAW ints (民國/twd label formatting stays client-side). `extraIncome`\nis an optional caller-supplied opt to computeCompanyPnL (defaults 0 until the\n額外收入 table lands). Accounting-module-gated server-side (fail-closed).\nSee specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "損益表結算月（格式 YYYY-MM）（格式限定）"
            }
          },
          {
            "name": "extraIncome",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "額外收入（台幣非負整數），併入公司淨利計算；預設 0"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "period": {
                          "type": "string",
                          "description": "結算期間（YYYY-MM）。"
                        },
                        "regions": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "region": {
                                "type": "string",
                                "description": "派生 region key（穩定，由 trip 屬性派生）。"
                              },
                              "label": {
                                "type": "string",
                                "description": "顯示標籤（destination 原文 / 衍生）。"
                              },
                              "revenueTwd": {
                                "type": "number",
                                "description": "本區成交應收（出團月落 period 的梯次合計，TWD 整數）。"
                              },
                              "directCostTwd": {
                                "type": "number",
                                "description": "本區真實直接成本（TWD 整數）= 房費底價成本 + 已核准的逐筆成本合計。"
                              },
                              "marginTwd": {
                                "type": "number",
                                "description": "本區毛利 = revenue − directCost。"
                              },
                              "departures": {
                                "type": "number",
                                "description": "本區梯次數（出團月落 period）。"
                              }
                            },
                            "required": [
                              "region",
                              "label",
                              "revenueTwd",
                              "directCostTwd",
                              "marginTwd",
                              "departures"
                            ]
                          },
                          "description": "各區毛利明細（出團月落 period 的梯次按區 roll-up）。"
                        },
                        "grossMarginTwd": {
                          "type": "number",
                          "description": "各區毛利加總（整數 TWD）。"
                        },
                        "revenueTotalTwd": {
                          "type": "number",
                          "description": "各區營收加總（整數 TWD）。"
                        },
                        "extraIncomeTwd": {
                          "type": "number",
                          "description": "額外收入（GS 二、額外收入總計；本批無 schema 載體 → 0，見 §5）。"
                        },
                        "adminFeeIncomeTwd": {
                          "type": "number",
                          "description": "行政手續費收入（退款收取的行政手續費，只計未出團 / 取消單，TWD 整數）。"
                        },
                        "otherIncomeTwd": {
                          "type": "number",
                          "description": "其他收入合計 = extraIncome + adminFeeIncome（整數 TWD）。"
                        },
                        "expensesByKind": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "description": "'opex' / 'tax' / 'platform_fee'。"
                              },
                              "amountTwd": {
                                "type": "number",
                                "description": "該 kind 本期費用合計（整數 TWD）。"
                              },
                              "count": {
                                "type": "number",
                                "description": "該 kind 本期費用筆數。"
                              }
                            },
                            "required": [
                              "kind",
                              "amountTwd",
                              "count"
                            ]
                          },
                          "description": "公司營業費用按 kind roll-up（opex / tax / platform_fee，只計已確認）。"
                        },
                        "operatingExpenseTotalTwd": {
                          "type": "number",
                          "description": "公司營業費用合計 = Σ opex / tax / platform_fee（整數 TWD）。"
                        },
                        "special": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "費用列 ID。"
                              },
                              "categoryId": {
                                "type": "string",
                                "description": "費用科目 ID（特殊損益科目）。"
                              },
                              "categoryDisplayName": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "費用科目顯示名。"
                              },
                              "description": {
                                "type": "string",
                                "description": "摘要（如 取消神山床位沒收訂金）。"
                              },
                              "amountTwd": {
                                "type": "number",
                                "description": "金額（整數 TWD ≥ 0，DB CHECK operating_expenses_amount_nonneg）。**第一版 special 一律視為「損」**（扣減淨利，與營業費用同向）——對齊 GS 五月事件「取消神山床位沒收」= 損。schema 無 sign 欄，無法表達一次性「益」；一次性收益（§3.4）落地 sign 欄後再分流， 屆時 specialTotal 改帶號。當前 specialTotalTwd 一律從淨利扣減。"
                              }
                            },
                            "required": [
                              "id",
                              "categoryId",
                              "categoryDisplayName",
                              "description",
                              "amountTwd"
                            ]
                          },
                          "description": "特殊損益逐筆（kind='special'，一次性、獨立列，只計已確認）。"
                        },
                        "specialTotalTwd": {
                          "type": "number",
                          "description": "特殊損益加總（整數 TWD，第一版一律視為損）。"
                        },
                        "netProfitTwd": {
                          "type": "number",
                          "description": "公司淨利 = grossMargin + otherIncome − operatingExpenseTotal − specialTotal。"
                        },
                        "netMarginPct": {
                          "type": [
                            "number",
                            "null"
                          ],
                          "description": "淨利率（netProfit / revenueTotal），revenue=0 時 null。"
                        }
                      },
                      "required": [
                        "period",
                        "regions",
                        "grossMarginTwd",
                        "revenueTotalTwd",
                        "extraIncomeTwd",
                        "adminFeeIncomeTwd",
                        "otherIncomeTwd",
                        "expensesByKind",
                        "operatingExpenseTotalTwd",
                        "special",
                        "specialTotalTwd",
                        "netProfitTwd",
                        "netMarginPct"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "operating_expense.read"
      }
    },
    "/reconciliation/accounts": {
      "get": {
        "operationId": "get_reconciliation_accounts",
        "tags": [
          "reconciliation"
        ],
        "summary": "逐收款帳戶現金進出對帳",
        "description": "GET /api/v1/reconciliation/accounts — 逐收款帳戶現金進出對帳（/admin/control 對帳視圖\n的 HTTP 版）。期間以 Asia/Taipei 牆鐘日界（dateFrom 含、dateTo 含整日），零活動帳戶不列。\nTenant-wide（無 owner-scope）；以 receiving_account.read 把關。See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "dateFrom",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "對帳期間起日（YYYY-MM-DD，含當日），以 Asia/Taipei 牆鐘日界計；省略則不設下界"
            }
          },
          {
            "name": "dateTo",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "對帳期間迄日（YYYY-MM-DD，含整日），以 Asia/Taipei 牆鐘日界計；省略則不設上界"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "accountId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "收款帳戶 id；null = 未歸戶桶。"
                          },
                          "code": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "帳戶代碼；未歸戶桶為 null。"
                          },
                          "displayName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "帳戶顯示名；未歸戶桶為 null。"
                          },
                          "kind": {
                            "anyOf": [
                              {},
                              {
                                "type": "null"
                              }
                            ],
                            "description": "帳戶類型（bank / cash / gateway）；未歸戶桶為 null。"
                          },
                          "inTwd": {
                            "type": "number",
                            "description": "期間內 direction='in' 的金額合計。"
                          },
                          "outTwd": {
                            "type": "number",
                            "description": "期間內 payment_transactions direction='out' 的金額合計（客戶退款 / gateway 出）。"
                          },
                          "payableOutTwd": {
                            "type": "number",
                            "description": "期間內供應商出款合計（payables paid 的 net_amount_twd；非 order-scoped，獨立來源 §3.1）。"
                          },
                          "netTwd": {
                            "type": "number",
                            "description": "淨額 = in − out − payableOut（不扣手續費，純現金流向；對帳找銀行入帳用毛額）。"
                          },
                          "txCount": {
                            "type": "number",
                            "description": "期間內這帳戶的活動筆數（payment_transactions + payables paid）。"
                          }
                        },
                        "required": [
                          "accountId",
                          "code",
                          "displayName",
                          "kind",
                          "inTwd",
                          "outTwd",
                          "payableOutTwd",
                          "netTwd",
                          "txCount"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "receiving_account.read"
      }
    },
    "/reconciliation/obligations": {
      "get": {
        "operationId": "get_reconciliation_obligations",
        "tags": [
          "reconciliation"
        ],
        "summary": "未結掛帳追蹤",
        "description": "GET /api/v1/reconciliation/obligations — 未結掛帳追蹤（debtor/creditor 帳戶間應結金額），\n可依月結來源期間 / 原因 / 狀態過濾。Tenant-wide；以 account_settlement.read 把關。\nSee specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "月結來源期間（YYYY-MM），篩選由該期月結互抵推導出的掛帳；省略則不限期間"
            }
          },
          {
            "name": "reason",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "掛帳原因代碼，篩選特定成因的掛帳；省略則不限原因"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "掛帳狀態（如未結清 / 已結清），篩選特定結清狀態；省略則含全部"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "帳戶間掛帳 ID。"
                          },
                          "debtorAccountId": {
                            "type": "string",
                            "description": "欠款方（債務人）收款帳戶 ID。"
                          },
                          "creditorAccountId": {
                            "type": "string",
                            "description": "收款方（債權人）收款帳戶 ID。"
                          },
                          "amountTwd": {
                            "type": "number",
                            "description": "應補目標總額（TWD 整數，恆正）。"
                          },
                          "settledAmountTwd": {
                            "type": "number",
                            "description": "已結清金額（TWD 整數，0 ≤ settled ≤ amount）。"
                          },
                          "outstandingTwd": {
                            "type": "number",
                            "description": "待結餘額（派生 = amount − settled，>= 0）。"
                          },
                          "reason": {
                            "description": "掛帳成因：period_settlement 月結互抵 / advance_repayment 代墊償還 / refund_advance 退款代墊 / adjustment 手動調整。"
                          },
                          "originPeriod": {
                            "type": "string",
                            "description": "產生月份（YYYY-MM，Asia/Taipei）。"
                          },
                          "status": {
                            "description": "結清狀態：outstanding 未結 / partially_settled 部分結清 / settled 已結清。"
                          },
                          "note": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "備註；無則為 null。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          }
                        },
                        "required": [
                          "id",
                          "debtorAccountId",
                          "creditorAccountId",
                          "amountTwd",
                          "settledAmountTwd",
                          "outstandingTwd",
                          "reason",
                          "originPeriod",
                          "status",
                          "note",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "account_settlement.read",
        "x-module": "accounting"
      }
    },
    "/reconciliation/receiving-accounts": {
      "get": {
        "operationId": "get_reconciliation_receiving_accounts",
        "tags": [
          "reconciliation"
        ],
        "summary": "收款帳戶目錄清單",
        "description": "GET /api/v1/reconciliation/receiving-accounts — 收款帳戶目錄清單（含停用，除非 activeOnly）。\nTenant-wide；以 receiving_account.read 把關。See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "activeOnly",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "是否只回傳啟用中的收款帳戶（true/false）；省略則含停用"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "收款帳戶 ID。"
                          },
                          "code": {
                            "type": "string",
                            "description": "帳戶代碼（租戶內唯一穩定識別）。"
                          },
                          "displayName": {
                            "type": "string",
                            "description": "帳戶顯示名。"
                          },
                          "kind": {
                            "description": "帳戶類型：bank 銀行 / cash 現金 / gateway 金流閘道。"
                          },
                          "bankName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "銀行名稱；現金／閘道帳戶為 null。"
                          },
                          "accountNo": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "銀行帳號；現金／閘道帳戶為 null。"
                          },
                          "canReceive": {
                            "type": "boolean",
                            "description": "可收款（幾乎都 true）。"
                          },
                          "canRemit": {
                            "type": "boolean",
                            "description": "可對外匯款（ATM / 匯出退款 / 補款匯出）。荒野只有永豐。"
                          },
                          "canChargeback": {
                            "type": "boolean",
                            "description": "可刷退（退回原信用卡）。荒野只有綠界（gateway）。"
                          },
                          "isDeprecated": {
                            "type": "boolean",
                            "description": "廢帳戶：仍可零星收款，但其收款需由他帳戶代墊歸集。荒野＝RU 台銀 / 登山社。"
                          },
                          "isSettlementMaster": {
                            "type": "boolean",
                            "description": "主結算帳戶：所有資金最終向它彙整。每租戶恰一個（partial unique index）。荒野＝永豐。"
                          },
                          "currency": {
                            "type": "string",
                            "description": "帳戶幣別（ISO 4217；既有帳戶皆 'TWD'，外幣帳戶如 IDR / USD）。"
                          },
                          "isActive": {
                            "type": "boolean",
                            "description": "此帳戶是否啟用。"
                          },
                          "displayOrder": {
                            "type": "number",
                            "description": "後台清單排序序位（小者在前）。"
                          },
                          "usedCount": {
                            "type": "number",
                            "description": "被多少 payment_transactions 引用（UI 鎖頭 / 「使用中 N」）。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          }
                        },
                        "required": [
                          "id",
                          "code",
                          "displayName",
                          "kind",
                          "bankName",
                          "accountNo",
                          "canReceive",
                          "canRemit",
                          "canChargeback",
                          "isDeprecated",
                          "isSettlementMaster",
                          "currency",
                          "isActive",
                          "displayOrder",
                          "usedCount",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "receiving_account.read"
      }
    },
    "/reconciliation/refund-executions": {
      "get": {
        "operationId": "get_reconciliation_refund_executions",
        "tags": [
          "reconciliation"
        ],
        "summary": "退款執行清單",
        "description": "GET /api/v1/reconciliation/refund-executions — 退款執行清單（待執行 approved + 已執行 paid）。\n預設合併 approved + paid；`status` 可收斂為單一段。Tenant-wide；以 account_settlement.read\n把關（退款執行清單在帳戶結算區）。See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "approved",
                "paid"
              ],
              "description": "退款狀態篩選：approved 待執行（已核准）、paid 已執行（已出款）；省略則合併回傳兩者"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "退款單 ID。"
                              },
                              "refundNumber": {
                                "type": "string",
                                "description": "退款單號（人可讀，每租戶流水號）。"
                              },
                              "orderId": {
                                "type": "string",
                                "description": "所屬訂單 ID。"
                              },
                              "orderNumber": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "所屬訂單編號（人可讀）；無則為 null。"
                              },
                              "status": {
                                "description": "退款工作流狀態：draft / submitted / approved / processing / paid / failed / cancelled。"
                              },
                              "refundKind": {
                                "description": "退款種類：receivable_reduction 減應收退款（取消 / 降價 / 服務失敗）/ overpayment_return 溢收退還（不動應收，只退多收現金）。"
                              },
                              "affectsReceivable": {
                                "type": "boolean",
                                "description": "是否減少應收（receivable_reduction 為 true、overpayment_return 為 false；溢收退還不列入 refund_state）。"
                              },
                              "amountTwd": {
                                "type": "number",
                                "description": "退款金額（TWD 整數，正值）。"
                              },
                              "method": {
                                "description": "退款方式：original_gateway 原路退刷 / bank_transfer 銀行匯款 / cash 現金 / manual 手動。"
                              },
                              "reason": {
                                "type": "string",
                                "description": "退款原因說明。"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "退款單建立時間。"
                              },
                              "paidAt": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "format": "date-time",
                                "description": "實際退款出款（現金結算）時間；未執行為 null。"
                              },
                              "createdByName": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "建單人姓名；無則為 null。"
                              },
                              "executionMethod": {
                                "anyOf": [
                                  {},
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "退款執行方法：chargeback 原信用卡刷退 / remit 匯出；未指定為 null。"
                              },
                              "originAccountId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "出款來源帳戶 ID（從哪個收款帳戶退出）；未指定為 null。"
                              },
                              "adminFeeTwd": {
                                "type": "number",
                                "description": "內扣手續費（TWD 整數；自退款金額中扣除的行政費）。"
                              },
                              "remitFeeTwd": {
                                "type": "number",
                                "description": "匯款手續費（TWD 整數；銀行匯出的轉帳費）。"
                              },
                              "payeeAccountName": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "收款人戶名（匯款退款用）；無則為 null。"
                              },
                              "payeeBankCode": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "收款銀行代碼（匯款退款用）；無則為 null。"
                              },
                              "payeeAccountNumber": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "收款帳號（匯款退款用）；無則為 null。"
                              }
                            },
                            "required": [
                              "id",
                              "refundNumber",
                              "orderId",
                              "orderNumber",
                              "status",
                              "refundKind",
                              "affectsReceivable",
                              "amountTwd",
                              "method",
                              "reason",
                              "createdAt",
                              "paidAt",
                              "createdByName",
                              "executionMethod",
                              "originAccountId",
                              "adminFeeTwd",
                              "remitFeeTwd",
                              "payeeAccountName",
                              "payeeBankCode",
                              "payeeAccountNumber"
                            ]
                          },
                          "description": "退款執行列（合併 approved 待執行 + paid 已執行，或收斂為指定段）。"
                        },
                        "total": {
                          "type": "number",
                          "description": "回傳的退款執行筆數。"
                        }
                      },
                      "required": [
                        "rows",
                        "total"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "account_settlement.read",
        "x-module": "accounting"
      }
    },
    "/reconciliation/settlement-overview": {
      "get": {
        "operationId": "get_reconciliation_settlement_overview",
        "tags": [
          "reconciliation"
        ],
        "summary": "子系統 B 月結互抵派生總覽",
        "description": "GET /api/v1/reconciliation/settlement-overview — 子系統 B 月結互抵派生總覽（兩層彙整 +\n掛帳對帳 + 退款執行）。`period` 須為 YYYY-MM。同時是 settlementMatrixReport 報表的資料源\n（CSV 為 CLI 端輸出格式化，core 仍回 typed object）。Tenant-wide；以 account_settlement.read\n把關（會計職能，op 看不到）。See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "要查詢月結互抵總覽的結算期（YYYY-MM）（格式限定）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "period": {
                          "type": "string",
                          "description": "結算月份（YYYY-MM，Asia/Taipei）。"
                        },
                        "matrix": {
                          "type": "object",
                          "properties": {
                            "lines": {
                              "type": "array",
                              "items": {
                                "type": "object"
                              },
                              "description": "各帳戶對主結算帳戶（或其類別 final）的有向淨額；恆正、方向由 debtor/creditor。"
                            },
                            "unclassified": {
                              "type": "object",
                              "description": "未分類（未標費用類型）收款彙總，不進互抵，供 UI 提示補 tag。"
                            }
                          },
                          "required": [
                            "lines",
                            "unclassified"
                          ],
                          "description": "兩層互抵矩陣（各帳戶對主結算帳戶的有向淨額 + 未分類彙總）。"
                        },
                        "obligations": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "帳戶間掛帳 ID。"
                              },
                              "debtorAccountId": {
                                "type": "string",
                                "description": "欠款方（債務人）收款帳戶 ID。"
                              },
                              "creditorAccountId": {
                                "type": "string",
                                "description": "收款方（債權人）收款帳戶 ID。"
                              },
                              "amountTwd": {
                                "type": "number",
                                "description": "應補目標總額（TWD 整數，恆正）。"
                              },
                              "settledAmountTwd": {
                                "type": "number",
                                "description": "已結清金額（TWD 整數，0 ≤ settled ≤ amount）。"
                              },
                              "outstandingTwd": {
                                "type": "number",
                                "description": "待結餘額（派生 = amount − settled，>= 0）。"
                              },
                              "reason": {
                                "description": "掛帳成因：period_settlement 月結互抵 / advance_repayment 代墊償還 / refund_advance 退款代墊 / adjustment 手動調整。"
                              },
                              "originPeriod": {
                                "type": "string",
                                "description": "產生月份（YYYY-MM，Asia/Taipei）。"
                              },
                              "status": {
                                "description": "結清狀態：outstanding 未結 / partially_settled 部分結清 / settled 已結清。"
                              },
                              "note": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "備註；無則為 null。"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "建立時間。"
                              },
                              "updatedAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "最後更新時間。"
                              }
                            },
                            "required": [
                              "id",
                              "debtorAccountId",
                              "creditorAccountId",
                              "amountTwd",
                              "settledAmountTwd",
                              "outstandingTwd",
                              "reason",
                              "originPeriod",
                              "status",
                              "note",
                              "createdAt",
                              "updatedAt"
                            ]
                          },
                          "description": "本期相關掛帳（period_settlement，含結清進度）。"
                        },
                        "carriedForward": {
                          "type": "object",
                          "properties": {
                            "lines": {
                              "type": "array",
                              "items": {
                                "type": "object"
                              },
                              "description": "上期未結 period_settlement 殘額逐筆明細（已種入本期互抵基數）。"
                            },
                            "totalTwd": {
                              "type": "number",
                              "description": "結轉殘額小計（TWD 整數）。"
                            }
                          },
                          "required": [
                            "lines",
                            "totalTwd"
                          ],
                          "description": "跨期掛帳結轉基數（上期未結 period_settlement 殘額，已種入 matrix 淨額；此處供顯示明細 + 小計）。"
                        }
                      },
                      "required": [
                        "period",
                        "matrix",
                        "obligations",
                        "carriedForward"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "account_settlement.read",
        "x-module": "accounting"
      }
    },
    "/reconciliation/settlement/compute": {
      "post": {
        "operationId": "post_reconciliation_settlement_compute",
        "tags": [
          "reconciliation"
        ],
        "summary": "跑當期月結互抵派生 + upsert",
        "description": "POST /api/v1/reconciliation/settlement/compute — 跑當期月結互抵派生 + upsert\nperiod_settlement 掛帳（可重跑冪等，冪等護欄不回退已結額）。鏡像後台\n`computePeriodSettlementAction`：同 requirePermission（account_settlement.read）、\n同進階會計模組 fail-closed 閘、同 core fn `computePeriodSettlement(db, period)`。\n無 shell 端 writeAuditLog。SettlementError → 409 conflict。See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "period": {
                          "type": "string",
                          "description": "結算月份（YYYY-MM，Asia/Taipei）。"
                        },
                        "matrix": {
                          "type": "object",
                          "properties": {
                            "lines": {
                              "type": "array",
                              "items": {
                                "type": "object"
                              },
                              "description": "各帳戶對主結算帳戶（或其類別 final）的有向淨額；恆正、方向由 debtor/creditor。"
                            },
                            "unclassified": {
                              "type": "object",
                              "description": "未分類（未標費用類型）收款彙總，不進互抵，供 UI 提示補 tag。"
                            }
                          },
                          "required": [
                            "lines",
                            "unclassified"
                          ],
                          "description": "兩層互抵矩陣（各帳戶對主結算帳戶的有向淨額 + 未分類彙總）。"
                        },
                        "upserts": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "debtorAccountId": {
                                "type": "string",
                                "description": "欠款方（債務人）收款帳戶 ID。"
                              },
                              "creditorAccountId": {
                                "type": "string",
                                "description": "收款方（債權人）收款帳戶 ID。"
                              },
                              "derivedAmountTwd": {
                                "type": "number",
                                "description": "本次派生的目標淨額。"
                              },
                              "appliedAmountTwd": {
                                "type": "number",
                                "description": "實際落地的掛帳 amount_twd（受冪等護欄約束，不低於已 settled）。"
                              },
                              "obligationId": {
                                "type": "string",
                                "description": "對應的帳戶間掛帳 ID（本次 upsert 的目標列）。"
                              },
                              "action": {
                                "type": "string",
                                "enum": [
                                  "created",
                                  "updated",
                                  "floored_to_settled"
                                ],
                                "description": "本次動作：created 新建 / updated 更新 / floored_to_settled 派生低於已結被護欄下限鎖住。"
                              },
                              "adjustmentTwd": {
                                "type": "number",
                                "description": "派生目標低於已結額、被 floor 時的差額（保留為 adjustment 線索；> 0 表示有缺口）。"
                              },
                              "adjustmentObligationId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "floor 缺口另記的 adjustment 掛帳 id（action='floored_to_settled' 時非 null）。"
                              }
                            },
                            "required": [
                              "debtorAccountId",
                              "creditorAccountId",
                              "derivedAmountTwd",
                              "appliedAmountTwd",
                              "obligationId",
                              "action",
                              "adjustmentTwd",
                              "adjustmentObligationId"
                            ]
                          },
                          "description": "本次 run 對每條互抵列 upsert 的結果（含冪等護欄調整）。"
                        },
                        "deletedObligationIds": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "本次 run 刪除的失效派生掛帳 id（settled=0 且不在新派生）。"
                        }
                      },
                      "required": [
                        "period",
                        "matrix",
                        "upserts",
                        "deletedObligationIds"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "account_settlement.read",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "period": {
                    "type": "string",
                    "description": "要計算月結互抵的結算期（YYYY-MM），可重跑且冪等（不回退已結額）（格式限定）"
                  }
                },
                "required": [
                  "period"
                ]
              }
            }
          }
        }
      }
    },
    "/reconciliation/statement-imports": {
      "get": {
        "operationId": "get_reconciliation_statement_imports",
        "tags": [
          "reconciliation"
        ],
        "description": "銀行對帳單匯入（payment-accounts-reconciliation §3.3）的版本化 API。\n\nGET  /api/v1/reconciliation/statement-imports?account=<id>\n  逐帳戶的批次 + 行 + 進度彙總（鏡像後台對帳頁帳戶卡「對帳單」區的 getStatementView）。\n  讀路徑閘 bank_statement.read + 進階會計模組（比照 statement-template 下載 route）。\n\nPOST /api/v1/reconciliation/statement-imports\n  兩階段匯入的 commit（鏡像 commitStatementImportAction）：base64 上傳 → 重新解析同一檔\n  → parser errors > 0 一律 fail-closed 拒 → commitStatementImport（插批 + 行 + 自動配對，\n  同 tx，audit 帶 actorUserId）。寫入閘 bank_statement.manage + accounting 模組。",
        "parameters": [
          {
            "name": "account",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "收款帳戶 ID，回傳該帳戶的對帳單批次 / 行 / 進度彙總（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "imports": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "對帳單批次 ID。"
                              },
                              "periodStart": {
                                "type": "string",
                                "description": "批次期間起日（'YYYY-MM-DD'，含當日）。"
                              },
                              "periodEnd": {
                                "type": "string",
                                "description": "批次期間迄日（'YYYY-MM-DD'，含當日）。"
                              },
                              "filename": {
                                "type": "string",
                                "description": "匯入的檔名。"
                              },
                              "createdAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "匯入時間。"
                              },
                              "lineCount": {
                                "type": "number",
                                "description": "批內總行數。"
                              },
                              "autoCount": {
                                "type": "number",
                                "description": "自動配對的行數。"
                              },
                              "manualCount": {
                                "type": "number",
                                "description": "人工配對的行數。"
                              },
                              "unmatchedCount": {
                                "type": "number",
                                "description": "尚未配對的行數。"
                              },
                              "ignoredCount": {
                                "type": "number",
                                "description": "已略過（ignored）的行數。"
                              },
                              "excludedCount": {
                                "type": "number",
                                "description": "已解除配對（excluded）的行數。"
                              }
                            },
                            "required": [
                              "id",
                              "periodStart",
                              "periodEnd",
                              "filename",
                              "createdAt",
                              "lineCount",
                              "autoCount",
                              "manualCount",
                              "unmatchedCount",
                              "ignoredCount",
                              "excludedCount"
                            ]
                          },
                          "description": "該帳戶的對帳單批次清單（新到舊）。"
                        },
                        "lines": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "對帳單行 ID。"
                              },
                              "importId": {
                                "type": "string",
                                "description": "所屬對帳單批次 ID。"
                              },
                              "lineNo": {
                                "type": "number",
                                "description": "檔案內行號（1 起算）。"
                              },
                              "txnDate": {
                                "type": "string",
                                "description": "交易日期（'YYYY-MM-DD'）。"
                              },
                              "direction": {
                                "type": "string",
                                "enum": [
                                  "out",
                                  "in"
                                ],
                                "description": "現金流向：in 存入 / out 支出。"
                              },
                              "amountTwd": {
                                "type": "number",
                                "description": "金額（TWD 整數）。"
                              },
                              "memo": {
                                "type": "string",
                                "description": "摘要 / 備註文字。"
                              },
                              "status": {
                                "type": "string",
                                "description": "配對狀態：unmatched 未配 / auto 自動 / manual 人工 / ignored 略過 / excluded 已解除。"
                              },
                              "matchedSourceType": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "已配對來源種類（payment_transaction / payable / account_transfer）；未配為 null。"
                              },
                              "matchedSourceId": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "已配對來源 ID；未配為 null。"
                              },
                              "ignoredReason": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "略過原因；非 ignored 為 null。"
                              }
                            },
                            "required": [
                              "id",
                              "importId",
                              "lineNo",
                              "txnDate",
                              "direction",
                              "amountTwd",
                              "memo",
                              "status",
                              "matchedSourceType",
                              "matchedSourceId",
                              "ignoredReason"
                            ]
                          },
                          "description": "該帳戶所有對帳單行（跨批次）。"
                        },
                        "progress": {
                          "type": "object",
                          "properties": {
                            "total": {
                              "type": "number",
                              "description": "總行數。"
                            },
                            "matched": {
                              "type": "number",
                              "description": "已配對行數（auto + manual）。"
                            },
                            "unmatched": {
                              "type": "number",
                              "description": "未配對行數。"
                            },
                            "ignored": {
                              "type": "number",
                              "description": "已略過行數。"
                            },
                            "excluded": {
                              "type": "number",
                              "description": "已解除配對行數。"
                            }
                          },
                          "required": [
                            "total",
                            "matched",
                            "unmatched",
                            "ignored",
                            "excluded"
                          ],
                          "description": "配對進度彙總。"
                        }
                      },
                      "required": [
                        "imports",
                        "lines",
                        "progress"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "bank_statement.read",
        "x-module": "accounting"
      },
      "post": {
        "operationId": "post_reconciliation_statement_imports",
        "tags": [
          "reconciliation"
        ],
        "description": "銀行對帳單匯入（payment-accounts-reconciliation §3.3）的版本化 API。\n\nGET  /api/v1/reconciliation/statement-imports?account=<id>\n  逐帳戶的批次 + 行 + 進度彙總（鏡像後台對帳頁帳戶卡「對帳單」區的 getStatementView）。\n  讀路徑閘 bank_statement.read + 進階會計模組（比照 statement-template 下載 route）。\n\nPOST /api/v1/reconciliation/statement-imports\n  兩階段匯入的 commit（鏡像 commitStatementImportAction）：base64 上傳 → 重新解析同一檔\n  → parser errors > 0 一律 fail-closed 拒 → commitStatementImport（插批 + 行 + 自動配對，\n  同 tx，audit 帶 actorUserId）。寫入閘 bank_statement.manage + accounting 模組。",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "importId": {
                          "type": "string",
                          "description": "新建立的對帳單批次 ID。"
                        },
                        "autoMatched": {
                          "type": "number",
                          "description": "匯入後即自動配對成功的行數。"
                        },
                        "unmatched": {
                          "type": "number",
                          "description": "匯入後仍未配對的行數。"
                        }
                      },
                      "required": [
                        "importId",
                        "autoMatched",
                        "unmatched"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "bank_statement.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "receivingAccountId": {
                    "type": "string",
                    "description": "收款帳戶 ID（僅支援 TWD 的 bank / cash 帳戶）（min 1）"
                  },
                  "periodStart": {
                    "type": "string",
                    "description": "對帳單期間起日（含當日）（格式限定）"
                  },
                  "periodEnd": {
                    "type": "string",
                    "description": "對帳單期間迄日（含當日）（格式限定）"
                  },
                  "filename": {
                    "type": "string",
                    "description": "上傳檔名，副檔名須為 .xlsx 或 .csv（min 1）"
                  },
                  "contentBase64": {
                    "type": "string",
                    "description": "對帳單檔案內容的 base64 編碼字串（固定範本填好後另存）（min 1）"
                  }
                },
                "required": [
                  "receivingAccountId",
                  "periodStart",
                  "periodEnd",
                  "filename",
                  "contentBase64"
                ]
              }
            }
          }
        }
      }
    },
    "/reconciliation/statement-imports/{importId}": {
      "delete": {
        "operationId": "delete_reconciliation_statement_imports_importId_",
        "tags": [
          "reconciliation"
        ],
        "summary": "刪整批",
        "description": "DELETE /api/v1/reconciliation/statement-imports/:importId — 刪整批（鏡像\ndeleteImportAction）。批內存在任何人工痕跡（manual / ignored / excluded）即 core throw\nhas_manual_traces（→ 409）；純 auto / unmatched 可刪，cascade 釋放 auto 配對。寫入閘\nbank_statement.manage + accounting 模組；audit 帶 actorUserId。",
        "parameters": [
          {
            "name": "importId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "對帳單批次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否刪除整批成功（批內無人工痕跡才可刪）。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "bank_statement.manage",
        "x-module": "accounting"
      }
    },
    "/reconciliation/statement-imports/{importId}/auto-match": {
      "post": {
        "operationId": "post_reconciliation_statement_imports_importId_auto_match",
        "tags": [
          "reconciliation"
        ],
        "summary": "對該批",
        "description": "POST /api/v1/reconciliation/statement-imports/:importId/auto-match — 對該批（依帳戶）\n重跑自動配對（鏡像 runAutoMatchAction）。冪等，只碰該帳戶 status='unmatched' 行；已配 /\nexcluded / ignored 一律不動。寫入閘 bank_statement.manage + accounting 模組；audit 帶\nactorUserId。回本輪新配數 { matched }。",
        "parameters": [
          {
            "name": "importId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "對帳單批次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "matched": {
                          "type": "number",
                          "description": "本輪新增自動配對的行數。"
                        }
                      },
                      "required": [
                        "matched"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "bank_statement.manage",
        "x-module": "accounting"
      }
    },
    "/reconciliation/statement-imports/candidates": {
      "get": {
        "operationId": "get_reconciliation_statement_imports_candidates",
        "tags": [
          "reconciliation"
        ],
        "summary": "某帳戶內、未被",
        "description": "GET /api/v1/reconciliation/statement-imports/candidates?account=<id> — 某帳戶內、未被\nactive 配對的三源 ERP 候選（payment_transaction / payable / account_transfer 雙邊），\n人工配對時挑對象用（鏡像後台 listUnmatchedErpCandidates 供的 picker 資料源）。\n讀路徑閘 bank_statement.read + accounting 模組。",
        "parameters": [
          {
            "name": "account",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "收款帳戶 ID，回傳該帳戶未配對的 ERP 現金流水候選（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "sourceType": {
                            "description": "ERP 來源種類：payment_transaction 收款交易 / payable 出款 / account_transfer 帳戶移轉。"
                          },
                          "sourceId": {
                            "type": "string",
                            "description": "ERP 來源紀錄 ID。"
                          },
                          "date": {
                            "type": "string",
                            "description": "'YYYY-MM-DD'（Asia/Taipei 牆鐘日）。"
                          },
                          "direction": {
                            "type": "string",
                            "enum": [
                              "out",
                              "in"
                            ],
                            "description": "現金流向：in 進帳 / out 出帳。"
                          },
                          "amountTwd": {
                            "type": "number",
                            "description": "金額（TWD 整數）。"
                          },
                          "label": {
                            "type": "string",
                            "description": "顯示標籤（來源摘要，供人工配對時辨識）。"
                          }
                        },
                        "required": [
                          "sourceType",
                          "sourceId",
                          "date",
                          "direction",
                          "amountTwd",
                          "label"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "bank_statement.read",
        "x-module": "accounting"
      }
    },
    "/reconciliation/statement-imports/template": {
      "get": {
        "operationId": "get_reconciliation_statement_imports_template",
        "tags": [
          "reconciliation"
        ],
        "summary": "銀行對帳單匯入固定範本下載",
        "description": "GET /api/v1/reconciliation/statement-imports/template — 銀行對帳單匯入固定範本下載\n（鏡像後台 /admin/reconciliation/statement-template）。回 JSON `{ filename, contentBase64 }`，\nCLI 端 base64 解碼另存 .xlsx；固定中文表頭（日期 / 存入金額 / 支出金額 / 摘要 / 備註）+ 一列\n示例。讀路徑閘 bank_statement.read + accounting 模組。",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "filename": {
                          "type": "string",
                          "description": "建議另存的檔名（.xlsx，含日期戳）。"
                        },
                        "contentBase64": {
                          "type": "string",
                          "description": "範本 .xlsx 內容的 base64 編碼字串（CLI 端解碼另存）。"
                        }
                      },
                      "required": [
                        "filename",
                        "contentBase64"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "bank_statement.read",
        "x-module": "accounting"
      }
    },
    "/reconciliation/statement-imports/validate": {
      "post": {
        "operationId": "post_reconciliation_statement_imports_validate",
        "tags": [
          "reconciliation"
        ],
        "summary": "兩階段匯入的第一階段 dry-run",
        "description": "POST /api/v1/reconciliation/statement-imports/validate — 兩階段匯入的第一階段 dry-run\n預覽（鏡像 previewStatementImportAction）：base64 上傳 → 解析 + 期間重疊預檢 + 自動配對\n「預覽」，**完全不寫 DB**。parser 錯誤列 + 期間外行一併回填（依行號排序）供 dry-run 表顯示，\n但不在此擋（commit 端 errors > 0 才 fail-closed）。寫入權限 bank_statement.manage +\naccounting 模組（預覽屬匯入流程，比照後台以 manage 把關）。",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "accountId": {
                          "type": "string",
                          "description": "對帳的收款帳戶 ID。"
                        },
                        "periodStart": {
                          "type": "string",
                          "description": "對帳單期間起日（'YYYY-MM-DD'，含當日）。"
                        },
                        "periodEnd": {
                          "type": "string",
                          "description": "對帳單期間迄日（'YYYY-MM-DD'，含當日）。"
                        },
                        "filename": {
                          "type": "string",
                          "description": "上傳檔名。"
                        },
                        "lines": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "lineNo": {
                                "type": "number",
                                "description": "檔案內行號（1 起算）。"
                              },
                              "txnDate": {
                                "type": "string",
                                "description": "交易日期（'YYYY-MM-DD'）。"
                              },
                              "direction": {
                                "type": "string",
                                "enum": [
                                  "out",
                                  "in"
                                ],
                                "description": "現金流向：in 存入 / out 支出。"
                              },
                              "amountTwd": {
                                "type": "number",
                                "description": "金額（TWD 整數）。"
                              },
                              "memo": {
                                "type": "string",
                                "description": "摘要 / 備註文字。"
                              },
                              "willAuto": {
                                "type": "boolean",
                                "description": "若現在 commit，這行是否會被自動配對（同語意孤立邊）。"
                              }
                            },
                            "required": [
                              "lineNo",
                              "txnDate",
                              "direction",
                              "amountTwd",
                              "memo",
                              "willAuto"
                            ]
                          },
                          "description": "解析後的各行預覽（含「若 commit 是否會被自動配對」）。"
                        },
                        "parseErrors": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "lineNo": {
                                "type": "number",
                                "description": "出錯的對帳單行號（原始列，從 1 起算）。"
                              },
                              "message": {
                                "type": "string",
                                "description": "錯誤說明（解析失敗原因或期間外提示）。"
                              }
                            },
                            "required": [
                              "lineNo",
                              "message"
                            ]
                          },
                          "description": "解析錯誤 + 期間外的行（依行號排序；commit 端會 fail-closed 拒）。"
                        },
                        "willAutoCount": {
                          "type": "number",
                          "description": "若現在 commit，預計會被自動配對的行數。"
                        },
                        "willUnmatchedCount": {
                          "type": "number",
                          "description": "若現在 commit，預計仍未配對的行數。"
                        },
                        "periodOverlap": {
                          "type": "boolean",
                          "description": "宣告期間是否與既有批次重疊（commit 會被擋）。"
                        }
                      },
                      "required": [
                        "accountId",
                        "periodStart",
                        "periodEnd",
                        "filename",
                        "lines",
                        "parseErrors",
                        "willAutoCount",
                        "willUnmatchedCount",
                        "periodOverlap"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "bank_statement.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "receivingAccountId": {
                    "type": "string",
                    "description": "收款帳戶 ID（僅支援 TWD 的 bank / cash 帳戶）（min 1）"
                  },
                  "periodStart": {
                    "type": "string",
                    "description": "對帳單期間起日（含當日）（格式限定）"
                  },
                  "periodEnd": {
                    "type": "string",
                    "description": "對帳單期間迄日（含當日）（格式限定）"
                  },
                  "filename": {
                    "type": "string",
                    "description": "上傳檔名，副檔名須為 .xlsx 或 .csv（min 1）"
                  },
                  "contentBase64": {
                    "type": "string",
                    "description": "對帳單檔案內容的 base64 編碼字串（min 1）"
                  }
                },
                "required": [
                  "receivingAccountId",
                  "periodStart",
                  "periodEnd",
                  "filename",
                  "contentBase64"
                ]
              }
            }
          }
        }
      }
    },
    "/reconciliation/statement-lines/{lineId}/ignore": {
      "post": {
        "operationId": "post_reconciliation_statement_lines_lineId_ignore",
        "tags": [
          "reconciliation"
        ],
        "summary": "略過一條對帳單行 →",
        "description": "POST /api/v1/reconciliation/statement-lines/:lineId/ignore — 略過一條對帳單行 →\n'ignored'（鏡像 ignoreLineAction）。原因必填（手續費 / 利息等 ERP 不記的行）；已配對需先\n解除。寫入閘 bank_statement.manage + accounting 模組；audit 帶 actorUserId。",
        "parameters": [
          {
            "name": "lineId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "對帳單行 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否標記略過成功（狀態轉為 ignored）。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "bank_statement.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "description": "略過原因（必填；如「手續費」「利息」）（min 1）"
                  }
                },
                "required": [
                  "reason"
                ]
              }
            }
          }
        }
      }
    },
    "/reconciliation/statement-lines/{lineId}/match": {
      "post": {
        "operationId": "post_reconciliation_statement_lines_lineId_match",
        "tags": [
          "reconciliation"
        ],
        "summary": "人工配對一條對帳單行到指定",
        "description": "POST /api/v1/reconciliation/statement-lines/:lineId/match — 人工配對一條對帳單行到指定\nERP 來源（鏡像 manualMatchAction）。core 強制同帳戶 + 同金額 + 同方向，只能配 status ∈\n{unmatched, excluded}（已 auto / manual 需先 unmatch）。寫入閘 bank_statement.manage +\naccounting 模組；audit 帶 actorUserId。",
        "parameters": [
          {
            "name": "lineId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "對帳單行 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否人工配對成功（同帳戶 / 同金額 / 同方向）。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "bank_statement.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sourceType": {
                    "type": "string",
                    "description": "配對來源種類：payment_transaction / payable / account_transfer"
                  },
                  "sourceId": {
                    "type": "string",
                    "description": "配對來源 ID（該帳戶內未被配對的 ERP 候選）（min 1）"
                  }
                },
                "required": [
                  "sourceType",
                  "sourceId"
                ]
              }
            }
          }
        }
      }
    },
    "/reconciliation/statement-lines/{lineId}/unmatch": {
      "post": {
        "operationId": "post_reconciliation_statement_lines_lineId_unmatch",
        "tags": [
          "reconciliation"
        ],
        "summary": "解除配對 → 'excluded'",
        "description": "POST /api/v1/reconciliation/statement-lines/:lineId/unmatch — 解除配對 → 'excluded'\n（鏡像 unmatchAction）。只能解 status ∈ {auto, manual}；解除後不再被自動配，只可人工重配。\n寫入閘 bank_statement.manage + accounting 模組；audit 帶 actorUserId。",
        "parameters": [
          {
            "name": "lineId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "對帳單行 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否解除配對成功（狀態轉為 excluded）。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "bank_statement.manage",
        "x-module": "accounting"
      }
    },
    "/reconciliation/transfers": {
      "get": {
        "operationId": "get_reconciliation_transfers",
        "tags": [
          "reconciliation"
        ],
        "summary": "帳戶間移轉統一分類帳查詢",
        "description": "GET /api/v1/reconciliation/transfers — 帳戶間移轉統一分類帳查詢（補款 / 代墊 / 回填 /\n退款匯出 / 換匯 / 沖正），可依 kind / 帳戶 / 日期 / 月結 / 掛帳過濾。Tenant-wide；\n以 account_settlement.read 把關。寫入（登錄移轉）是後續 flow 批次（account_transfer.manage）。\nSee specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "移轉類型篩選（fx_conversion 換匯 / replenishment 補款 / advance 代墊 / backfill 回填 / refund_payout 退款匯出 / reversal 沖正）；省略則含全部"
            }
          },
          {
            "name": "account",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "帳戶 ID 篩選，回傳該帳戶為出帳或進帳方的移轉；省略則不限帳戶"
            }
          },
          {
            "name": "dateFrom",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "移轉日期起日（YYYY-MM-DD，含當日）；省略則不設下界"
            }
          },
          {
            "name": "dateTo",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "移轉日期迄日（YYYY-MM-DD，含當日）；省略則不設上界"
            }
          },
          {
            "name": "settlementPeriod",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "對應月結期間（YYYY-MM）篩選；省略則不限月結"
            }
          },
          {
            "name": "obligation",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "掛帳 ID 篩選，回傳沖減該筆掛帳的移轉；省略則不限掛帳"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "帳戶間移轉 ID。"
                          },
                          "kind": {
                            "description": "移轉類型：fx_conversion 換匯 / replenishment 補款 / advance 代墊 / backfill 回填 / refund_payout 退款匯出 / opening 期初 / reversal 沖正。"
                          },
                          "fromAccountId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "出帳帳戶 ID；期初等單邊移轉為 null。"
                          },
                          "toAccountId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "進帳帳戶 ID；單邊移轉為 null。"
                          },
                          "amountTwd": {
                            "type": "number",
                            "description": "移轉金額（TWD 整數）。"
                          },
                          "feeTwd": {
                            "type": "number",
                            "description": "手續費（TWD 整數）。"
                          },
                          "currency": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "外幣幣別（ISO 4217；純台幣移轉為 null）。"
                          },
                          "foreignAmount": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "外幣金額（整數；非外幣移轉為 null）。"
                          },
                          "feeForeign": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "外幣手續費（整數；無則為 null）。"
                          },
                          "grossRate": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "換匯牌價（numeric → 字串原值保精度；顯示/溯源用）。"
                          },
                          "settlementPeriod": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "對應月結期間（YYYY-MM）；未歸屬月結為 null。"
                          },
                          "obligationId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "沖減的帳戶間掛帳 ID；未沖減掛帳為 null。"
                          },
                          "reversesTransferId": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "被本筆沖正的原移轉 ID（kind='reversal' 時非 null）。"
                          },
                          "occurredAt": {
                            "type": "string",
                            "description": "移轉日期（'YYYY-MM-DD'，date 欄）。"
                          },
                          "note": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "備註；無則為 null。"
                          },
                          "createdByUserId": {
                            "type": "string",
                            "description": "登錄人 user ID。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          }
                        },
                        "required": [
                          "id",
                          "kind",
                          "fromAccountId",
                          "toAccountId",
                          "amountTwd",
                          "feeTwd",
                          "currency",
                          "foreignAmount",
                          "feeForeign",
                          "grossRate",
                          "settlementPeriod",
                          "obligationId",
                          "reversesTransferId",
                          "occurredAt",
                          "note",
                          "createdByUserId",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "account_settlement.read"
      },
      "post": {
        "operationId": "post_reconciliation_transfers",
        "tags": [
          "reconciliation"
        ],
        "description": "GET /api/v1/reconciliation/transfers — 帳戶間移轉統一分類帳查詢（補款 / 代墊 / 回填 /\n退款匯出 / 換匯 / 沖正），可依 kind / 帳戶 / 日期 / 月結 / 掛帳過濾。Tenant-wide；\n以 account_settlement.read 把關。寫入（登錄移轉）是後續 flow 批次（account_transfer.manage）。\nSee specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否登錄成功（移轉 + 沖減掛帳的原子交易皆完成）。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "account_transfer.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "description": "移轉類型：fx_conversion 換匯、replenishment 補款、advance 代墊、backfill 回填、refund_payout 退款匯出、reversal 沖正（前處理正規化（省略則補預設 / null））"
                  },
                  "fromAccountId": {
                    "type": "string",
                    "description": "出帳（轉出）帳戶 ID；與進帳帳戶至少填一個，null 表示無出帳方（min 1 · 前處理正規化）"
                  },
                  "toAccountId": {
                    "type": "string",
                    "description": "進帳（轉入）帳戶 ID；與出帳帳戶至少填一個，null 表示無進帳方（min 1 · 前處理正規化）"
                  },
                  "amountTwd": {
                    "type": "number",
                    "description": "移轉台幣淨額（整數，不可為負）；沖減掛帳時須大於 0（前處理正規化（省略則補預設 / null））"
                  },
                  "feeTwd": {
                    "type": "number",
                    "description": "此筆移轉產生的手續費（台幣整數，不可為負）（前處理正規化（省略則補預設 / null））"
                  },
                  "occurredAt": {
                    "type": "string",
                    "description": "移轉發生日期（YYYY-MM-DD）（格式限定 · 前處理正規化）"
                  },
                  "settlementPeriod": {
                    "type": "string",
                    "description": "對應月結期間（YYYY-MM），標記此移轉沖減哪一期互抵；換匯不掛單一月結，傳 null（格式限定 · 前處理正規化）"
                  },
                  "currency": {
                    "type": "string",
                    "description": "換匯外幣幣別（ISO 4217 三碼）；非換匯傳 null（格式限定 · 前處理正規化）"
                  },
                  "foreignAmount": {
                    "type": "number",
                    "description": "換匯外幣金額（整數最小單位，須大於 0）；非換匯傳 null（前處理正規化（省略則補預設 / null））"
                  },
                  "grossRate": {
                    "type": "string",
                    "description": "換匯牌價（正數，最多 6 位小數，以字串表達避免精度遺失）；非換匯傳 null（格式限定 · 前處理正規化）"
                  },
                  "obligationId": {
                    "type": "string",
                    "description": "選填沖減的掛帳 ID（aob_ 開頭）；換匯不沖減掛帳須傳 null（格式限定 · 前處理正規化）"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/reports/monthly": {
      "get": {
        "operationId": "get_reports_monthly",
        "tags": [
          "reports"
        ],
        "summary": "tenant monthly",
        "description": "GET /api/v1/reports/monthly?year=<YYYY>&month=<1-12> — tenant monthly\nfinancial summary (the /admin/reports surface over HTTP): overview KPIs\n(collected/refunded/net cash, order counts, new customers) + by-trip sales\nranking + by-provider breakdown, derived from the seven-layer money ledger.\n\nNOTE on contract semantics (mirror of core's header note, document for API\nconsumers): all sums are TOUR-scoped only (lodging revenue is invisible);\n`totalRevenue` is COLLECTED CASH (payment_transactions inbound within month),\nNOT accrual-recognised revenue; month boundaries are Asia/Taipei wall-clock;\norders counted by created_at, cancelled by updated_at, cash by occurred_at.\n\nTenant-wide (no owner-scope filter — getMonthlyReport sums all tour cash),\ngated on `order.read` per the back-office page. CSV/PDF export is a net-new\ncapability not yet in core; this endpoint returns JSON only.",
        "parameters": [
          {
            "name": "year",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number",
              "description": "報表年份（西元四位數），月界以台北時區計（max 2100 · min 2000）"
            }
          },
          {
            "name": "month",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number",
              "description": "報表月份，1 至 12（max 12 · min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "year": {
                          "type": "number",
                          "description": "報表年份（西元四位數）。"
                        },
                        "month": {
                          "type": "number",
                          "description": "報表月份（1-12，月界以 Asia/Taipei 計）。"
                        },
                        "totalOrders": {
                          "type": "number",
                          "description": "本月建立的 tour 訂單數（依 created_at 計）。"
                        },
                        "paidOrders": {
                          "type": "number",
                          "description": "本月有實收現金的 tour 訂單數（月內有 inbound 交易）。"
                        },
                        "cancelledOrders": {
                          "type": "number",
                          "description": "本月取消的 tour 訂單數（依 updated_at 計）。"
                        },
                        "totalRevenue": {
                          "type": "number",
                          "description": "collected_cash：本月實收現金 = SUM(payment_transactions in) within month。"
                        },
                        "refundedAmount": {
                          "type": "number",
                          "description": "refunded_cash：本月退還現金 = SUM(payment_transactions out, refund/chargeback) within month。"
                        },
                        "netCash": {
                          "type": "number",
                          "description": "net_cash：本月淨現金 = SUM(in:+amount, out:-amount) - SUM(fee) within month。"
                        },
                        "newCustomers": {
                          "type": "number",
                          "description": "本月新註冊會員數（排除 staff 角色）。"
                        },
                        "byTrip": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "tripId": {
                                "type": "string",
                                "description": "行程 ID。"
                              },
                              "tripTitle": {
                                "type": "string",
                                "description": "團名。"
                              },
                              "orderCount": {
                                "type": "number",
                                "description": "該行程本月有實收現金的訂單數。"
                              },
                              "revenue": {
                                "type": "number",
                                "description": "collected_cash by trip：本月實收現金（tour-scoped）。"
                              }
                            },
                            "required": [
                              "tripId",
                              "tripTitle",
                              "orderCount",
                              "revenue"
                            ]
                          },
                          "description": "依行程銷售排行（前 10 名，按本月實收現金）。"
                        },
                        "byProvider": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "provider": {
                                "type": "string",
                                "description": "金流商代碼（如 ecpay / test）。"
                              },
                              "orderCount": {
                                "type": "number",
                                "description": "該金流商本月有實收現金的訂單數。"
                              },
                              "amount": {
                                "type": "number",
                                "description": "collected_cash by provider：本月實收現金（tour-scoped）。"
                              }
                            },
                            "required": [
                              "provider",
                              "orderCount",
                              "amount"
                            ]
                          },
                          "description": "依金流商分組的本月實收現金。"
                        },
                        "dailyRevenue": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "day": {
                                "type": "string",
                                "description": "日期（YYYY-MM-DD，Asia/Taipei 日界）。"
                              },
                              "amount": {
                                "type": "number",
                                "description": "當日實收現金（tour-scoped，整數 TWD）。"
                              }
                            },
                            "required": [
                              "day",
                              "amount"
                            ]
                          },
                          "description": "collected_cash by day：本月逐日實收現金（tour-scoped，Asia/Taipei 日界）， 整月零填滿（無入帳的日子 amount=0）。Σ amount === totalRevenue，與 KPI 對帳。"
                        }
                      },
                      "required": [
                        "year",
                        "month",
                        "totalOrders",
                        "paidOrders",
                        "cancelledOrders",
                        "totalRevenue",
                        "refundedAmount",
                        "netCash",
                        "newCustomers",
                        "byTrip",
                        "byProvider",
                        "dailyRevenue"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "order.read"
      }
    },
    "/roles": {
      "get": {
        "operationId": "get_roles",
        "tags": [
          "roles"
        ],
        "summary": "list all roles",
        "description": "GET /api/v1/roles — list all roles (builtin + custom) with permission +\nmember counts (the /admin/roles matrix index over HTTP). Tenant-wide (no\nowner scope); gated on role.manage like the back-office page. Optional\n`?system=true|false` filters builtin vs custom client-side; listRoles itself\ntakes no filter so the narrowing is applied here. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "system",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ],
              "description": "是否只列內建角色：true 僅內建、false 僅自訂，省略則全部"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "角色 ID（內建角色為其代碼）。"
                          },
                          "name": {
                            "type": "string",
                            "description": "角色代碼（小寫英數與底線，建立後不可改；即帳號綁定的角色值）。"
                          },
                          "label": {
                            "type": "string",
                            "description": "角色顯示名稱。"
                          },
                          "isSystem": {
                            "type": "boolean",
                            "description": "是否為系統內建角色（內建角色不可修改或刪除）。"
                          },
                          "permissionCount": {
                            "type": "number",
                            "description": "該角色目前擁有的 (resource, action) 數量。"
                          },
                          "memberCount": {
                            "type": "number",
                            "description": "持有此角色的使用者人數。"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "label",
                          "isSystem",
                          "permissionCount",
                          "memberCount"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage"
      },
      "post": {
        "operationId": "post_roles",
        "tags": [
          "roles"
        ],
        "description": "GET /api/v1/roles — list all roles (builtin + custom) with permission +\nmember counts (the /admin/roles matrix index over HTTP). Tenant-wide (no\nowner scope); gated on role.manage like the back-office page. Optional\n`?system=true|false` filters builtin vs custom client-side; listRoles itself\ntakes no filter so the narrowing is applied here. See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立的角色 ID。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "角色代碼，小寫英數與底線、2–32 字且須以字母開頭，建立後不可改"
                  },
                  "label": {
                    "type": "string",
                    "description": "角色顯示名稱，呈現於後台角色清單"
                  },
                  "permissions": {
                    "type": "array",
                    "items": {},
                    "description": "此角色授予的權限清單，每筆為一組資源與動作"
                  }
                },
                "required": [
                  "name",
                  "label"
                ]
              }
            }
          }
        }
      }
    },
    "/roles/{id}": {
      "get": {
        "operationId": "get_roles_id_",
        "tags": [
          "roles"
        ],
        "summary": "one role + its full",
        "description": "GET /api/v1/roles/{id} — one role + its full (resource, action) permission\nmatrix. Builtin roles return CODE-truth grants; custom roles read\nrole_permissions. Tenant-wide; gated on role.manage. Missing → 404.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "角色 ID（內建角色為其代碼）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "角色 ID（內建角色為其代碼）。"
                        },
                        "name": {
                          "type": "string",
                          "description": "角色代碼（小寫英數與底線，建立後不可改；即帳號綁定的角色值）。"
                        },
                        "label": {
                          "type": "string",
                          "description": "角色顯示名稱。"
                        },
                        "isSystem": {
                          "type": "boolean",
                          "description": "是否為系統內建角色（內建角色不可修改或刪除）。"
                        },
                        "permissions": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "resource": {
                                "type": "string",
                                "description": "權限資源代碼，例如 order、member。"
                              },
                              "action": {
                                "type": "string",
                                "description": "權限動作代碼，例如 read、update。"
                              }
                            },
                            "required": [
                              "resource",
                              "action"
                            ]
                          },
                          "description": "此角色授予的完整 (resource, action) 權限清單。"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "label",
                        "isSystem",
                        "permissions"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage"
      },
      "patch": {
        "operationId": "patch_roles_id_",
        "tags": [
          "roles"
        ],
        "description": "GET /api/v1/roles/{id} — one role + its full (resource, action) permission\nmatrix. Builtin roles return CODE-truth grants; custom roles read\nrole_permissions. Tenant-wide; gated on role.manage. Missing → 404.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "欲更新的角色 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功更新角色。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "label": {
                    "type": "string",
                    "description": "角色顯示名稱，呈現於後台角色清單"
                  },
                  "permissions": {
                    "type": "array",
                    "items": {},
                    "description": "完整取代後的權限清單，會整批覆寫此角色現有權限"
                  }
                },
                "required": [
                  "label"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_roles_id_",
        "tags": [
          "roles"
        ],
        "description": "GET /api/v1/roles/{id} — one role + its full (resource, action) permission\nmatrix. Builtin roles return CODE-truth grants; custom roles read\nrole_permissions. Tenant-wide; gated on role.manage. Missing → 404.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "角色 ID（內建角色為其代碼）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功刪除角色。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage"
      }
    },
    "/roles/catalog": {
      "get": {
        "operationId": "get_roles_catalog",
        "tags": [
          "roles"
        ],
        "summary": "the code-defined permission catalog: every legal",
        "description": "GET /api/v1/roles/catalog — the code-defined permission catalog: every legal\n(resource, action) pair the role matrix can grant. Static CODE truth\n(CATALOG_RESOURCES); no DB read. Gated on role.manage like the matrix editor.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "resource": {
                            "type": "string",
                            "description": "權限資源代碼，例如 order、member。"
                          },
                          "actions": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "此資源可授予的動作代碼清單，例如 read、update。"
                          }
                        },
                        "required": [
                          "resource",
                          "actions"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage"
      }
    },
    "/rooms/{roomId}/travelers": {
      "post": {
        "operationId": "post_rooms_roomId_travelers",
        "tags": [
          "rooms"
        ],
        "summary": "指派旅客進房",
        "description": "POST /api/v1/rooms/{roomId}/travelers — 指派旅客進房（race-safe 容量檢查）。同核心\nop + core 內建 audit，鏡像後台 `assignTravelerToRoomAction`；gated departure.update。\n房滿 / 跨梯次 / 找不到 → 409。",
        "parameters": [
          {
            "name": "roomId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "目標房間 ID，旅客將被指派入住此房（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "指派入房成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure.update",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "travelerId": {
                    "type": "string",
                    "description": "欲指派的旅客 ID，須與房間屬於同一梯次（min 1）"
                  }
                },
                "required": [
                  "travelerId"
                ]
              }
            }
          }
        }
      }
    },
    "/rooms/travelers/{travelerId}": {
      "delete": {
        "operationId": "delete_rooms_travelers_travelerId_",
        "tags": [
          "rooms"
        ],
        "summary": "把旅客移出房間",
        "description": "DELETE /api/v1/rooms/travelers/{travelerId} — 把旅客移出房間。同核心 op + core\n內建 audit，鏡像後台 `removeTravelerFromRoomAction`；gated departure.update。\n找不到旅客 → 404。",
        "parameters": [
          {
            "name": "travelerId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "欲移出房間的旅客 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "移出房間成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure.update"
      }
    },
    "/settings": {
      "get": {
        "operationId": "get_settings",
        "tags": [
          "settings"
        ],
        "summary": "the tenant_settings singleton",
        "description": "GET /api/v1/settings — the tenant_settings singleton (company profile,\nassignment mode, SEO defaults, ledger fee rates, sending-domain identity,\nmasked ECPay merchant metadata, …). ECPay credentials are NEVER returned in\nplaintext — getTenantSettings exposes only the masked form.\n\nGated on `role.manage` (admin), NOT receiving_account.manage: the\n/admin/settings page entry-gates on receiving_account.manage but then\nconditionally renders the admin-sensitive tabs (company / payment / API / SEO)\nONLY when `isAdmin` (role.manage) and does not leak their props to an\naccountant. Returning the whole DTO under receiving_account.manage would hand\nan accountant data the page deliberately withholds — a permission-parity\nbreak. Accountants use the granular receiving-accounts / expense-categories\nroutes instead. (codex review HIGH-1) See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "設定列 ID（單例，恆為 'singleton'）。"
                        },
                        "companyName": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "公司全名，顯示於發票、合約與對外信件抬頭；null = 未設定。"
                        },
                        "companyPhone": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "公司聯絡電話，顯示於對外文件；null = 未設定。"
                        },
                        "taxId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "公司統一編號（8 位數字），用於開立發票；null = 未設定。"
                        },
                        "companyAddress": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "公司登記地址，顯示於對外文件；null = 未設定。"
                        },
                        "logoUrl": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "公司 Logo 圖片網址，用於後台與對外頁面品牌呈現；null = 未設定。"
                        },
                        "siteTagline": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "公開站標語（SEO／首頁）；null = 未設定。"
                        },
                        "seoDefaultDescription": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "公開站預設 SEO meta description；null = 未設定。"
                        },
                        "ogImageUrl": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "社群分享預設 Open Graph 圖片網址；null = 未設定。"
                        },
                        "emailReplyTo": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "系統寄信時的回覆收件信箱；null = 未設定。"
                        },
                        "assignmentMode": {
                          "type": "string",
                          "description": "S5: 'auto_round_robin' | 'auto_customer_choice' | 'manual_review'"
                        },
                        "defaultAssigneeUserId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "S5: fallback assignee when round-robin finds no active sales, etc."
                        },
                        "allowSalesClaim": {
                          "type": "boolean",
                          "description": "order-assignment §6：業務自派搶單開關（per-tenant opt-in，預設 false）。"
                        },
                        "passportExpiryWarningDays": {
                          "type": "number",
                          "description": "護照效期提醒天數（document-expiry §4.1；NOT NULL DEFAULT 180）。"
                        },
                        "groupCodePattern": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "團號 token 樣板（如 '{YY}{region}{airline?}{MMDD}{seq}'）。NULL = 內建預設。"
                        },
                        "groupCodeSeqStyle": {
                          "type": "string",
                          "description": "序號樣式：'alpha' | 'alpha_no_io' | 'numeric'（NOT NULL DEFAULT 'alpha'）。"
                        },
                        "groupCodeSeqWidth": {
                          "type": "number",
                          "description": "numeric 序號補零寬度（NOT NULL DEFAULT 2；alpha 樣式忽略）。"
                        },
                        "ecpayFeeBps": {
                          "type": "number",
                          "description": "預估綠界手續費率（270 = 2.70%）。NOT NULL DEFAULT 270。"
                        },
                        "fongshouFeeBps": {
                          "type": "number",
                          "description": "預估豐收款手續費率（50 = 0.50%）。NOT NULL DEFAULT 50。"
                        },
                        "profitTaxBps": {
                          "type": "number",
                          "description": "預估發票 / 營所稅率（500 = 5.00%）。NOT NULL DEFAULT 500。"
                        },
                        "salesCommissionBps": {
                          "type": "number",
                          "description": "業務抽成率（1000 = 10.00%）。NOT NULL DEFAULT 1000。"
                        },
                        "monthlyTopBonusBps": {
                          "type": "number",
                          "description": "月度第一名加碼率（500 = 5.00%）。NOT NULL DEFAULT 500。"
                        },
                        "ecpayMerchantId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "ECPay 特店 ID（明文，顯示用）。null = 未綁定租戶憑證（走 env 過渡）。"
                        },
                        "ecpaySecretsMask": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "ECPay HashKey/HashIV 的遮罩碼（`****` + 末 4）。DTO **只暴露 mask**， 整包 EncryptedField（含密文）永不出 repo —— 顯示用零 KMS 呼叫。"
                        },
                        "travelinvoiceMerchantId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "代收轉付 travelinvoice 特店 ID（明文，顯示用）。null = 未綁定租戶憑證（fail-closed）。"
                        },
                        "travelinvoiceSecretsMask": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "travelinvoice HashKey/HashIV 的遮罩碼（`****` + 末 4）。DTO **只暴露 mask**， 整包 EncryptedField（含密文）永不出 repo —— 顯示用零 KMS 呼叫。"
                        },
                        "sendingDomain": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "自有寄件 domain 快照；server 派生（enableSendingDomain），非自由輸入。"
                        },
                        "resendDomainId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "寄件服務商（Resend）的 domain 識別碼；null = 未設定自有寄件網域。"
                        },
                        "sendingDomainStatus": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "自有寄件網域的驗證狀態（如 pending／verified）；null = 未設定。"
                        },
                        "senderLocalPart": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "寄件人 local-part，未填視為 'info'。"
                        },
                        "updatedAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "設定最後更新時間。"
                        }
                      },
                      "required": [
                        "id",
                        "companyName",
                        "companyPhone",
                        "taxId",
                        "companyAddress",
                        "logoUrl",
                        "siteTagline",
                        "seoDefaultDescription",
                        "ogImageUrl",
                        "emailReplyTo",
                        "assignmentMode",
                        "defaultAssigneeUserId",
                        "allowSalesClaim",
                        "passportExpiryWarningDays",
                        "groupCodePattern",
                        "groupCodeSeqStyle",
                        "groupCodeSeqWidth",
                        "ecpayFeeBps",
                        "fongshouFeeBps",
                        "profitTaxBps",
                        "salesCommissionBps",
                        "monthlyTopBonusBps",
                        "ecpayMerchantId",
                        "ecpaySecretsMask",
                        "travelinvoiceMerchantId",
                        "travelinvoiceSecretsMask",
                        "sendingDomain",
                        "resendDomainId",
                        "sendingDomainStatus",
                        "senderLocalPart",
                        "updatedAt"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage"
      },
      "patch": {
        "operationId": "patch_settings",
        "tags": [
          "settings"
        ],
        "description": "GET /api/v1/settings — the tenant_settings singleton (company profile,\nassignment mode, SEO defaults, ledger fee rates, sending-domain identity,\nmasked ECPay merchant metadata, …). ECPay credentials are NEVER returned in\nplaintext — getTenantSettings exposes only the masked form.\n\nGated on `role.manage` (admin), NOT receiving_account.manage: the\n/admin/settings page entry-gates on receiving_account.manage but then\nconditionally renders the admin-sensitive tabs (company / payment / API / SEO)\nONLY when `isAdmin` (role.manage) and does not leak their props to an\naccountant. Returning the whole DTO under receiving_account.manage would hand\nan accountant data the page deliberately withholds — a permission-parity\nbreak. Accountants use the granular receiving-accounts / expense-categories\nroutes instead. (codex review HIGH-1) See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功更新租戶設定。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "companyName": {
                    "type": "string",
                    "description": "公司全名，顯示於發票、合約與對外信件抬頭；傳 null 或空字串清除（max 200）"
                  },
                  "companyPhone": {
                    "type": "string",
                    "description": "公司聯絡電話，顯示於對外文件；傳 null 或空字串清除（max 40）"
                  },
                  "taxId": {
                    "description": "公司統一編號（8 位數字），用於開立發票；傳 null 或空字串清除"
                  },
                  "companyAddress": {
                    "type": "string",
                    "description": "公司登記地址，顯示於對外文件；傳 null 或空字串清除（max 500）"
                  },
                  "logoUrl": {
                    "description": "公司 Logo 圖片網址（http/https），用於後台與對外頁面品牌呈現；傳 null 或空字串清除"
                  },
                  "emailReplyTo": {
                    "description": "系統寄信時的回覆收件信箱，客戶回信會寄到此處；傳 null 或空字串清除"
                  },
                  "senderLocalPart": {
                    "description": "寄件人信箱的帳號部分（@ 前段），與寄件網域組成完整寄件地址；傳 null 或空字串清除"
                  },
                  "passportExpiryWarningDays": {
                    "type": "number",
                    "description": "護照到期前提早幾天提醒（1 至 3650 天），用於行前護照效期預警（max 3650 · min 1）"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/settings/assignable-staff": {
      "get": {
        "operationId": "get_settings_assignable_staff",
        "tags": [
          "settings"
        ],
        "summary": "the staff pool eligible to be an",
        "description": "GET /api/v1/settings/assignable-staff — the staff pool eligible to be an\norder assignee (for the assignment-mode / default-assignee config on\n/admin/settings). See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "userId": {
                            "type": "string",
                            "description": "員工的使用者 ID（作為指派對象）。"
                          },
                          "name": {
                            "type": "string",
                            "description": "員工顯示姓名。"
                          },
                          "email": {
                            "type": "string",
                            "description": "員工登入 Email。"
                          },
                          "role": {
                            "type": "string",
                            "description": "員工角色代碼（sales／admin 等可指派角色）。"
                          },
                          "thisMonthAssigned": {
                            "type": "number",
                            "description": "本月（Asia/Taipei）已指派給此員工的訂單數（供輪派負載參考）。"
                          }
                        },
                        "required": [
                          "userId",
                          "name",
                          "email",
                          "role",
                          "thisMonthAssigned"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage"
      }
    },
    "/settings/assignment": {
      "patch": {
        "operationId": "patch_settings_assignment",
        "tags": [
          "settings"
        ],
        "summary": "S5 order-assignment mode + default",
        "description": "PATCH /api/v1/settings/assignment — S5 order-assignment mode + default\nassignee. Mirrors `updateAssignmentSettingsAction` (gated role.manage, same\n`updateAssignmentSettings` core op + same `tenant_settings.assignment_mode.change`\naudit with before/after). See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功更新訂單指派模式設定。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "assignmentMode": {
                    "type": "string",
                    "enum": [
                      "auto_round_robin",
                      "auto_customer_choice",
                      "auto_by_destination",
                      "manual_review"
                    ],
                    "description": "訂單指派模式：auto_round_robin 輪流自動指派、auto_customer_choice 依客戶選擇指派、auto_by_destination 依目的地地區碼對應規則指派、manual_review 進待審由人工指派"
                  },
                  "defaultAssigneeUserId": {
                    "type": "string",
                    "description": "預設承辦人員的使用者 ID，自動指派找不到對象時的兜底承辦人；空字串表示不設預設"
                  },
                  "allowSalesClaim": {
                    "type": "boolean",
                    "description": "是否開放業務自派搶單（從待派發池自行搶單）；未提供則不變更"
                  }
                },
                "required": [
                  "assignmentMode"
                ]
              }
            }
          }
        }
      }
    },
    "/settings/ecpay-credentials": {
      "put": {
        "operationId": "put_settings_ecpay_credentials",
        "tags": [
          "settings"
        ],
        "description": "PUT/DELETE /api/v1/settings/ecpay-credentials — per-tenant ECPay credentials\n(spec §5.4). Write-only: HashKey/HashIV are KMS-encrypted on write and NEVER\nreturned. Mirrors `updateEcpayCredentialsAction` (PUT) and\n`clearEcpayCredentialsAction` (DELETE): gated role.manage, same core ops, same\n`tenant_settings.update` audit. The all-or-nothing guard (no partial update)\nis enforced by the required schema fields here, matching the action shell.\nSee specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功儲存 ECPay 憑證（HashKey/HashIV 已 KMS 加密，永不回傳）。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "merchantId": {
                    "type": "string",
                    "description": "綠界 ECPay 特店編號（MerchantID），用於金流請款與簽章（max 20 · min 1）"
                  },
                  "hashKey": {
                    "type": "string",
                    "description": "綠界 ECPay HashKey，CheckMacValue 簽章用密鑰；寫入後即 KMS 加密儲存且永不回傳（max 100 · min 1）"
                  },
                  "hashIv": {
                    "type": "string",
                    "description": "綠界 ECPay HashIV，CheckMacValue 簽章用初始向量；寫入後即 KMS 加密儲存且永不回傳（max 100 · min 1）"
                  }
                },
                "required": [
                  "merchantId",
                  "hashKey",
                  "hashIv"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_settings_ecpay_credentials",
        "tags": [
          "settings"
        ],
        "description": "PUT/DELETE /api/v1/settings/ecpay-credentials — per-tenant ECPay credentials\n(spec §5.4). Write-only: HashKey/HashIV are KMS-encrypted on write and NEVER\nreturned. Mirrors `updateEcpayCredentialsAction` (PUT) and\n`clearEcpayCredentialsAction` (DELETE): gated role.manage, same core ops, same\n`tenant_settings.update` audit. The all-or-nothing guard (no partial update)\nis enforced by the required schema fields here, matching the action shell.\nSee specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功清除 ECPay 憑證。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage"
      }
    },
    "/settings/expense-categories": {
      "get": {
        "operationId": "get_settings_expense_categories",
        "tags": [
          "settings"
        ],
        "summary": "公司營業費用類別目錄",
        "description": "GET /api/v1/settings/expense-categories — 公司營業費用類別目錄 (opex / tax /\nplatform_fee / special). `--active-only` filters to live categories.\nMirrors the /admin/settings operating-expense category config. See\nspecs/tenant-cli.md.",
        "parameters": [
          {
            "name": "activeOnly",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "是否只回傳啟用中的費用類別（true/false）；省略則含停用"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "費用類別 ID。"
                          },
                          "code": {
                            "type": "string",
                            "description": "科目代碼（租戶內唯一穩定識別，如 rent / salary_admin / tax_vat）。"
                          },
                          "displayName": {
                            "type": "string",
                            "description": "顯示名（如 房租 / 行政薪資 / 營業稅）。"
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "opex",
                              "tax",
                              "platform_fee",
                              "special"
                            ],
                            "description": "費用大類：opex 營業費用 / tax 稅 / platform_fee 平台手續費 / special 特殊損益（損益表據此 roll-up）。"
                          },
                          "isActive": {
                            "type": "boolean",
                            "description": "是否啟用（停用不刪，既有費用列仍引用得到）。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          }
                        },
                        "required": [
                          "id",
                          "code",
                          "displayName",
                          "kind",
                          "isActive",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "operating_expense.read",
        "x-module": "accounting"
      },
      "post": {
        "operationId": "post_settings_expense_categories",
        "tags": [
          "settings"
        ],
        "description": "GET /api/v1/settings/expense-categories — 公司營業費用類別目錄 (opex / tax /\nplatform_fee / special). `--active-only` filters to live categories.\nMirrors the /admin/settings operating-expense category config. See\nspecs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立的費用類別 ID。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "operating_expense.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "費用類別代碼（小寫英數與底線），建立後不可變更，作為類別的穩定識別（格式限定 · max 40 · min 1）"
                  },
                  "displayName": {
                    "type": "string",
                    "description": "費用類別顯示名稱，呈現於後台費用登錄與報表（max 100 · min 1）"
                  },
                  "kind": {
                    "type": "string",
                    "description": "費用類別種類：opex 營業費用、tax 稅務、platform_fee 平台手續費、special 特殊，影響損益表歸類"
                  }
                },
                "required": [
                  "code",
                  "displayName",
                  "kind"
                ]
              }
            }
          }
        }
      }
    },
    "/settings/expense-categories/{id}": {
      "patch": {
        "operationId": "patch_settings_expense_categories_id_",
        "tags": [
          "settings"
        ],
        "summary": "更新費用類別的顯示名 / kind +",
        "description": "PATCH /api/v1/settings/expense-categories/{id} — 更新費用類別的顯示名 / kind +\n啟用狀態。鏡像 `updateExpenseCategorySettingsAction`：code 不可改；顯示名 / kind 走\n`updateExpenseCategory`、啟用切換走 `setExpenseCategoryActive`（兩 core op 各自寫\naudit），同權限 `operating_expense.manage`。先改內容再切狀態，與後台一致。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "費用類別 ID（路徑參數），指定要更新的類別（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功更新費用類別。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "operating_expense.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "displayName": {
                    "type": "string",
                    "description": "費用類別顯示名稱，呈現於後台費用登錄與報表（max 100 · min 1）"
                  },
                  "kind": {
                    "type": "string",
                    "description": "費用類別種類：opex 營業費用、tax 稅務、platform_fee 平台手續費、special 特殊，影響損益表歸類"
                  },
                  "isActive": {
                    "type": "boolean",
                    "description": "是否啟用此費用類別；false 為停用（停用而非刪除）"
                  }
                },
                "required": [
                  "displayName",
                  "kind",
                  "isActive"
                ]
              }
            }
          }
        }
      }
    },
    "/settings/expense-categories/{id}/active": {
      "patch": {
        "operationId": "patch_settings_expense_categories_id_active",
        "tags": [
          "settings"
        ],
        "summary": "toggle a費用類別",
        "description": "PATCH /api/v1/settings/expense-categories/{id}/active — toggle a費用類別\nactive/inactive (disable, not delete). Mirrors\n`setExpenseCategoryActiveSettingsAction`: gated operating_expense.manage, same\n`setExpenseCategoryActive(db, id, isActive, actorUserId)` core op. The core\nwrites its own `expense_category.set_active` audit (no shell replication).\nresult.reason → HttpError. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "費用類別 ID（路徑參數），指定要切換啟用狀態的類別（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功切換費用類別的啟用狀態。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "operating_expense.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "isActive": {
                    "type": "boolean",
                    "description": "目標啟用狀態：true 啟用、false 停用（停用而非刪除）"
                  }
                },
                "required": [
                  "isActive"
                ]
              }
            }
          }
        }
      }
    },
    "/settings/fee-category-routes": {
      "get": {
        "operationId": "get_settings_fee_category_routes",
        "tags": [
          "settings"
        ],
        "summary": "fee-category → final receiving",
        "description": "GET /api/v1/settings/fee-category-routes — fee-category → final receiving\naccount routing table (each手續費類別 settles into which帳戶). Mirrors the\n/admin/settings reconciliation routing config. See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "路由設定 ID。"
                          },
                          "feeCategory": {
                            "type": "string",
                            "description": "費用類型代碼（租戶自定唯一鍵，如 tour_fee／lodging／equipment）。"
                          },
                          "displayName": {
                            "type": "string",
                            "description": "費用類型顯示名。"
                          },
                          "finalAccountId": {
                            "type": "string",
                            "description": "此費用類型最終結算進的收款帳戶 ID。"
                          },
                          "finalAccountName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "final 帳戶顯示名（JOIN receiving_accounts；帳戶被刪則 null，但 FK restrict 一般不會）。"
                          },
                          "finalAccountCode": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "final 帳戶代號。"
                          },
                          "isActive": {
                            "type": "boolean",
                            "description": "此路由是否啟用。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          }
                        },
                        "required": [
                          "id",
                          "feeCategory",
                          "displayName",
                          "finalAccountId",
                          "finalAccountName",
                          "finalAccountCode",
                          "isActive",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "receiving_account.manage",
        "x-module": "accounting"
      },
      "put": {
        "operationId": "put_settings_fee_category_routes",
        "tags": [
          "settings"
        ],
        "description": "GET /api/v1/settings/fee-category-routes — fee-category → final receiving\naccount routing table (each手續費類別 settles into which帳戶). Mirrors the\n/admin/settings reconciliation routing config. See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立或更新的費用類型路由 ID。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "receiving_account.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "feeCategory": {
                    "type": "string",
                    "description": "費用類型代碼（小寫英數與底線），此 upsert 的唯一鍵；決定該手續費類型最終結算到哪個帳戶（格式限定 · max 40 · min 1）"
                  },
                  "displayName": {
                    "type": "string",
                    "description": "費用類型路由的顯示名稱，呈現於對帳設定（max 100 · min 1）"
                  },
                  "finalAccountId": {
                    "type": "string",
                    "description": "此費用類型最終結算進的收款帳戶 ID（min 1）"
                  },
                  "isActive": {
                    "type": "boolean",
                    "description": "是否啟用此費用類型路由；省略則維持預設啟用"
                  }
                },
                "required": [
                  "feeCategory",
                  "displayName",
                  "finalAccountId"
                ]
              }
            }
          }
        }
      }
    },
    "/settings/fee-category-routes/{id}/active": {
      "patch": {
        "operationId": "patch_settings_fee_category_routes_id_active",
        "tags": [
          "settings"
        ],
        "summary": "toggle a fee-category",
        "description": "PATCH /api/v1/settings/fee-category-routes/{id}/active — toggle a fee-category\nroute active/inactive (disable, not delete). Mirrors\n`setFeeCategoryRouteActiveSettingsAction`: gated receiving_account.manage, same\n`setFeeCategoryRouteActive` core op + same `fee_category_route.set_active`\naudit. Route-not-found → 404. The {id} segment is the route id (not the\nfeeCategory key) — distinct path from the upsert PUT to avoid sibling\ndynamic-segment collision. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "費用類型路由 ID（路徑參數，非 feeCategory 代碼），指定要切換啟用狀態的路由（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功切換費用類型路由的啟用狀態。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "receiving_account.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "isActive": {
                    "type": "boolean",
                    "description": "目標啟用狀態：true 啟用、false 停用（停用而非刪除）"
                  }
                },
                "required": [
                  "isActive"
                ]
              }
            }
          }
        }
      }
    },
    "/settings/ledger-fees": {
      "patch": {
        "operationId": "patch_settings_ledger_fees",
        "tags": [
          "settings"
        ],
        "summary": "internal/external-ledger profit estimate",
        "description": "PATCH /api/v1/settings/ledger-fees — internal/external-ledger profit estimate\nfee rates (ecpayFeeBps / fongshouFeeBps / profitTaxBps, basis points 0..10000).\nMirrors `updateLedgerFeeRatesAction` (gated role.manage, same\n`updateTenantSettings` core op + same `ledger.fee_rates.update` audit with\nbefore/after values). The core `assertBps` hard-gate is the backstop; the zod\nhere gives a friendly error. Omitted/empty field → unchanged. See\nspecs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功更新內外帳淨利試算的預估費率。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ecpayFeeBps": {
                    "description": "綠界 ECPay 金流手續費率，單位 basis points（0..10000，10000＝100%），用於內外帳淨利試算；留空不變更"
                  },
                  "fongshouFeeBps": {
                    "description": "豐收金流手續費率，單位 basis points（0..10000，10000＝100%），用於內外帳淨利試算；留空不變更"
                  },
                  "profitTaxBps": {
                    "description": "淨利稅率，單位 basis points（0..10000，10000＝100%），用於內外帳淨利試算；留空不變更"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/settings/modules": {
      "get": {
        "operationId": "get_settings_modules",
        "tags": [
          "settings"
        ],
        "summary": "the tenant's enabled plan modules",
        "description": "GET /api/v1/settings/modules — the tenant's enabled plan modules (climbing /\noverseas / lodging / accounting / lottery). Read-only by design:\nprovisioning is platform-CLI only, there is no tenant mutation path. Derived\nfrom the `x-tenant-modules` request header (set by proxy). See\nspecs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "climbing": {
                          "type": "boolean",
                          "description": "是否啟用登山團功能模組。"
                        },
                        "overseas": {
                          "type": "boolean",
                          "description": "是否啟用海外／出國團功能模組。"
                        },
                        "lodging": {
                          "type": "boolean",
                          "description": "是否啟用訂房子系統模組。"
                        },
                        "accounting": {
                          "type": "boolean",
                          "description": "是否啟用進階會計子系統模組。"
                        },
                        "lottery": {
                          "type": "boolean",
                          "description": "是否啟用抽籤子系統模組。"
                        }
                      },
                      "required": [
                        "climbing",
                        "overseas",
                        "lodging",
                        "accounting",
                        "lottery"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage"
      }
    },
    "/settings/receiving-accounts": {
      "get": {
        "operationId": "get_settings_receiving_accounts",
        "tags": [
          "settings"
        ],
        "summary": "the收款帳戶目錄",
        "description": "GET /api/v1/settings/receiving-accounts — the收款帳戶目錄 (bank / cash /\ngateway accounts) the /admin/settings 付款帳戶 tab maintains. `--active-only`\nfilters to live accounts. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "activeOnly",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "是否只回傳啟用中的收款帳戶（true/false）；省略則含停用"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "收款帳戶 ID。"
                          },
                          "code": {
                            "type": "string",
                            "description": "帳戶代碼（租戶內唯一穩定識別）。"
                          },
                          "displayName": {
                            "type": "string",
                            "description": "帳戶顯示名。"
                          },
                          "kind": {
                            "description": "帳戶類型：bank 銀行 / cash 現金 / gateway 金流閘道。"
                          },
                          "bankName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "銀行名稱；現金／閘道帳戶為 null。"
                          },
                          "accountNo": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "銀行帳號；現金／閘道帳戶為 null。"
                          },
                          "canReceive": {
                            "type": "boolean",
                            "description": "可收款（幾乎都 true）。"
                          },
                          "canRemit": {
                            "type": "boolean",
                            "description": "可對外匯款（ATM / 匯出退款 / 補款匯出）。荒野只有永豐。"
                          },
                          "canChargeback": {
                            "type": "boolean",
                            "description": "可刷退（退回原信用卡）。荒野只有綠界（gateway）。"
                          },
                          "isDeprecated": {
                            "type": "boolean",
                            "description": "廢帳戶：仍可零星收款，但其收款需由他帳戶代墊歸集。荒野＝RU 台銀 / 登山社。"
                          },
                          "isSettlementMaster": {
                            "type": "boolean",
                            "description": "主結算帳戶：所有資金最終向它彙整。每租戶恰一個（partial unique index）。荒野＝永豐。"
                          },
                          "currency": {
                            "type": "string",
                            "description": "帳戶幣別（ISO 4217；既有帳戶皆 'TWD'，外幣帳戶如 IDR / USD）。"
                          },
                          "isActive": {
                            "type": "boolean",
                            "description": "此帳戶是否啟用。"
                          },
                          "displayOrder": {
                            "type": "number",
                            "description": "後台清單排序序位（小者在前）。"
                          },
                          "usedCount": {
                            "type": "number",
                            "description": "被多少 payment_transactions 引用（UI 鎖頭 / 「使用中 N」）。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          }
                        },
                        "required": [
                          "id",
                          "code",
                          "displayName",
                          "kind",
                          "bankName",
                          "accountNo",
                          "canReceive",
                          "canRemit",
                          "canChargeback",
                          "isDeprecated",
                          "isSettlementMaster",
                          "currency",
                          "isActive",
                          "displayOrder",
                          "usedCount",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "receiving_account.manage",
        "x-module": "accounting"
      },
      "post": {
        "operationId": "post_settings_receiving_accounts",
        "tags": [
          "settings"
        ],
        "description": "GET /api/v1/settings/receiving-accounts — the收款帳戶目錄 (bank / cash /\ngateway accounts) the /admin/settings 付款帳戶 tab maintains. `--active-only`\nfilters to live accounts. See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立的收款帳戶 ID。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "receiving_account.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "收款帳戶代號，建立後不可變更，作為帳戶的穩定識別（max 40 · min 1）"
                  },
                  "displayName": {
                    "type": "string",
                    "description": "收款帳戶顯示名稱，呈現於收款與對帳介面（max 100 · min 1）"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "bank",
                      "cash",
                      "gateway"
                    ],
                    "description": "帳戶種類：bank 銀行帳戶、cash 現金、gateway 金流閘道"
                  },
                  "bankName": {
                    "type": "string",
                    "description": "銀行名稱（bank 類別適用）；空字串清除（max 100）"
                  },
                  "accountNo": {
                    "type": "string",
                    "description": "銀行帳號（bank 類別適用）；空字串清除（max 50）"
                  },
                  "currency": {
                    "description": "帳戶幣別，ISO 4217 三碼（如 TWD / JPY / IDR）；空字串預設 TWD，非 TWD 即為外幣池"
                  },
                  "displayOrder": {
                    "type": "number",
                    "description": "排序權重（0..9999），數字越小越前面；預設 0（max 9999 · min 0）"
                  },
                  "isActive": {
                    "type": "boolean",
                    "description": "是否啟用此帳戶；省略維持預設"
                  },
                  "canReceive": {
                    "type": "boolean",
                    "description": "是否可作為收款（進帳）帳戶"
                  },
                  "canRemit": {
                    "type": "boolean",
                    "description": "是否可作為出款（匯出）帳戶"
                  },
                  "canChargeback": {
                    "type": "boolean",
                    "description": "是否可作為退款 / 退刷帳戶"
                  },
                  "isDeprecated": {
                    "type": "boolean",
                    "description": "是否標記為已淘汰（保留歷史紀錄但不再新用）"
                  },
                  "isSettlementMaster": {
                    "type": "boolean",
                    "description": "是否為主結算帳戶；每租戶僅能有一個，月結互抵以此為彙整中心"
                  }
                },
                "required": [
                  "code",
                  "displayName",
                  "kind"
                ]
              }
            }
          }
        }
      }
    },
    "/settings/receiving-accounts/{id}": {
      "patch": {
        "operationId": "patch_settings_receiving_accounts_id_",
        "tags": [
          "settings"
        ],
        "summary": "update a收款帳戶",
        "description": "PATCH /api/v1/settings/receiving-accounts/{id} — update a收款帳戶\n(account-settlement §2.1; code is immutable). Mirrors\n`updateReceivingAccountSettingsAction`: gated receiving_account.manage, same\n`updateReceivingAccount` core op + same `receiving_account.update` audit.\nSettlement-master conflict / required-master → 409; account-not-found → 404.\nSee specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "收款帳戶 ID（路徑參數），指定要更新的帳戶（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功更新收款帳戶。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "receiving_account.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "displayName": {
                    "type": "string",
                    "description": "收款帳戶顯示名稱，呈現於收款與對帳介面（max 100 · min 1）"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "bank",
                      "cash",
                      "gateway"
                    ],
                    "description": "帳戶種類：bank 銀行帳戶、cash 現金、gateway 金流閘道"
                  },
                  "bankName": {
                    "type": "string",
                    "description": "銀行名稱（bank 類別適用）；空字串清除（max 100）"
                  },
                  "accountNo": {
                    "type": "string",
                    "description": "銀行帳號（bank 類別適用）；空字串清除（max 50）"
                  },
                  "currency": {
                    "description": "帳戶幣別，ISO 4217 三碼（如 TWD / JPY / IDR）；空字串預設 TWD，非 TWD 即為外幣池"
                  },
                  "displayOrder": {
                    "type": "number",
                    "description": "排序權重（0..9999），數字越小越前面（max 9999 · min 0）"
                  },
                  "isActive": {
                    "type": "boolean",
                    "description": "是否啟用此帳戶；省略維持原值"
                  },
                  "canReceive": {
                    "type": "boolean",
                    "description": "是否可作為收款（進帳）帳戶"
                  },
                  "canRemit": {
                    "type": "boolean",
                    "description": "是否可作為出款（匯出）帳戶"
                  },
                  "canChargeback": {
                    "type": "boolean",
                    "description": "是否可作為退款 / 退刷帳戶"
                  },
                  "isDeprecated": {
                    "type": "boolean",
                    "description": "是否標記為已淘汰（保留歷史紀錄但不再新用）"
                  },
                  "isSettlementMaster": {
                    "type": "boolean",
                    "description": "是否為主結算帳戶；每租戶僅能有一個，月結互抵以此為彙整中心"
                  }
                },
                "required": [
                  "displayName",
                  "kind",
                  "displayOrder"
                ]
              }
            }
          }
        }
      }
    },
    "/settings/sending-domain": {
      "get": {
        "operationId": "get_settings_sending_domain",
        "tags": [
          "settings"
        ],
        "summary": "the tenant's custom email sending-domain",
        "description": "GET /api/v1/settings/sending-domain — the tenant's custom email sending-domain\nstatus. Stored identity (domain / status / sender local-part) comes from\ntenant_settings; live DNS records come from Resend via getSendingDomainDetails\n(only when a domain is configured). Mirrors the /admin/settings 寄件網域 tab.\nSee specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "sendingDomain": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "自有寄件網域；未設定時為 null。"
                        },
                        "resendDomainId": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "寄件服務商（Resend）的網域識別碼；未設定時為 null。"
                        },
                        "sendingDomainStatus": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "網域驗證狀態（如 pending／verified）；未設定時為 null。"
                        },
                        "senderLocalPart": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "寄件人信箱的帳號部分（@ 前段）；未填視為 info。"
                        },
                        "records": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "record": {
                                "type": "string",
                                "description": "DNS 記錄用途分類（如 DKIM／SPF 等，來自 Resend）。"
                              },
                              "name": {
                                "type": "string",
                                "description": "記錄主機名（需在網域 DNS 新增的 host）。"
                              },
                              "type": {
                                "type": "string",
                                "description": "記錄類型（如 TXT／MX／CNAME）。"
                              },
                              "value": {
                                "type": "string",
                                "description": "記錄值（需填入 DNS 的內容）。"
                              },
                              "ttl": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "存活時間（TTL）；未指定時省略。"
                              },
                              "status": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "此筆記錄的驗證狀態（如 pending／verified）；未指定時省略。"
                              },
                              "priority": {
                                "type": [
                                  "number",
                                  "null"
                                ],
                                "description": "MX 記錄優先權；非 MX 記錄省略。"
                              }
                            },
                            "required": [
                              "record",
                              "name",
                              "type",
                              "value"
                            ]
                          },
                          "description": "待設定的 DNS 記錄清單（SPF／DKIM 等）；Resend 不可達或未設定時為空陣列。"
                        }
                      },
                      "required": [
                        "sendingDomain",
                        "resendDomainId",
                        "sendingDomainStatus",
                        "senderLocalPart",
                        "records"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage"
      }
    },
    "/settings/sending-domain/disable": {
      "post": {
        "operationId": "post_settings_sending_domain_disable",
        "tags": [
          "settings"
        ],
        "summary": "tear down the tenant's custom",
        "description": "POST /api/v1/settings/sending-domain/disable — tear down the tenant's custom\nsending domain. Mirrors `disableSendingDomainAction`: gated role.manage, same\n`disableSendingDomain` core op + same `tenant_settings.sending_domain.disable`\naudit. See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功停用自有寄件網域。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage"
      }
    },
    "/settings/sending-domain/enable": {
      "post": {
        "operationId": "post_settings_sending_domain_enable",
        "tags": [
          "settings"
        ],
        "summary": "provision the tenant's custom",
        "description": "POST /api/v1/settings/sending-domain/enable — provision the tenant's custom\nsending domain (domain derived from the bound site domain; no input). Mirrors\n`enableSendingDomainAction`: gated role.manage, same `enableSendingDomain` core\nop + same `tenant_settings.sending_domain.enable` audit. See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功啟用自有寄件網域。"
                        },
                        "domain": {
                          "type": "string",
                          "description": "啟用的寄件網域（由綁定的站台網域派生）。"
                        }
                      },
                      "required": [
                        "ok",
                        "domain"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage"
      }
    },
    "/settings/sending-domain/verify": {
      "post": {
        "operationId": "post_settings_sending_domain_verify",
        "tags": [
          "settings"
        ],
        "summary": "re-sync DNS verification status",
        "description": "POST /api/v1/settings/sending-domain/verify — re-sync DNS verification status\nfrom Resend. Mirrors `verifySendingDomainAction`: gated role.manage, same\n`syncSendingDomainStatus` core op + same `tenant_settings.sending_domain.verify`\naudit. See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功觸發驗證狀態同步。"
                        },
                        "status": {
                          "type": "string",
                          "description": "從 Resend 同步回來的最新網域驗證狀態（如 pending／verified）。"
                        }
                      },
                      "required": [
                        "ok",
                        "status"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage"
      }
    },
    "/settings/seo": {
      "patch": {
        "operationId": "patch_settings_seo",
        "tags": [
          "settings"
        ],
        "summary": "SEO defaults subset of tenant_settings",
        "description": "PATCH /api/v1/settings/seo — SEO defaults subset of tenant_settings\n(siteTagline / seoDefaultDescription / ogImageUrl). Mirrors\n`updateSeoSettingsAction` (gated role.manage, same `updateTenantSettings`\ncore op + same `tenant_settings.update` audit). Empty string clears the\ncolumn (matching the action's `|| null`). See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功更新公開站 SEO 設定。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "siteTagline": {
                    "type": "string",
                    "description": "網站標語，顯示於公開站標題與品牌呈現；空字串清除（max 120）"
                  },
                  "seoDefaultDescription": {
                    "type": "string",
                    "description": "SEO 預設頁面描述（meta description），未個別設定的頁面套用此值；空字串清除（max 300）"
                  },
                  "ogImageUrl": {
                    "description": "社群分享預設縮圖（Open Graph image）網址（http/https）；空字串清除"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/staff": {
      "get": {
        "operationId": "get_staff",
        "tags": [
          "staff"
        ],
        "summary": "list every staffer in the tenant DB",
        "description": "GET /api/v1/staff — list every staffer in the tenant DB (the /admin/staff\nlisting over HTTP). A staffer is a tenant-DB `user` row whose role is a staff\nrole (admin/sales/op/accountant); identity is the userId. Tenant-wide, no\nowner-scope. Gated on `role.manage` — the same chokepoint the back-office\nstaff page enforces. See specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "userId": {
                            "type": "string",
                            "description": "員工的使用者 ID。"
                          },
                          "email": {
                            "type": "string",
                            "description": "員工登入 Email（帳號識別）。"
                          },
                          "name": {
                            "type": "string",
                            "description": "員工顯示姓名。"
                          },
                          "role": {
                            "type": "string",
                            "description": "員工角色代碼（admin／sales／op／accountant）。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "帳號建立時間。"
                          },
                          "banned": {
                            "type": "boolean",
                            "description": "Account frozen via ban (離職 / 停權)."
                          },
                          "twoFactorEnabled": {
                            "type": "boolean",
                            "description": "是否已完成 TOTP 兩步驟驗證註冊。"
                          },
                          "emailVerified": {
                            "type": "boolean",
                            "description": "Email 是否已驗證（可視為「受邀者至少完成過一次登入」）。"
                          },
                          "pending": {
                            "type": "boolean",
                            "description": "派生的「邀請待完成」狀態：帳號已建立，但受邀者尚未驗證 Email 也未註冊 2FA（未完成首次登入）。"
                          }
                        },
                        "required": [
                          "userId",
                          "email",
                          "name",
                          "role",
                          "createdAt",
                          "banned",
                          "twoFactorEnabled",
                          "emailVerified",
                          "pending"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage"
      }
    },
    "/staff/{userId}": {
      "delete": {
        "operationId": "delete_staff_userId_",
        "tags": [
          "staff"
        ],
        "summary": "remove a staffer",
        "description": "DELETE /api/v1/staff/{userId} — remove a staffer (demote to customer; the\nuser row is kept). Same core op + audit as the back office `removeStaffAction`;\ngated on `role.manage`. Refuses the last-admin self-demote (→ 409).",
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "欲移除員工身分的使用者 ID（將降為一般顧客）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功移除員工身分（降為一般顧客）。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage"
      }
    },
    "/staff/{userId}/role": {
      "patch": {
        "operationId": "patch_staff_userId_role",
        "tags": [
          "staff"
        ],
        "summary": "change a staffer's role",
        "description": "PATCH /api/v1/staff/{userId}/role — change a staffer's role. Same core op +\naudit as the back office `updateStaffRoleAction`; gated on `role.manage`.\nRefuses the last-admin self-demote (→ 409) exactly like the action.",
        "parameters": [
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "欲變更角色的員工使用者 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "是否成功變更員工角色。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "role": {
                    "type": "string",
                    "description": "變更後的員工角色（admin／sales／op／accountant），決定權限範圍"
                  }
                },
                "required": [
                  "role"
                ]
              }
            }
          }
        }
      }
    },
    "/staff/invite": {
      "post": {
        "operationId": "post_staff_invite",
        "tags": [
          "staff"
        ],
        "summary": "建立一個新員工帳號",
        "description": "POST /api/v1/staff/invite — 建立一個新員工帳號（指定角色）。鏡像後台\n`inviteStaffAction`：同核心 op `inviteStaffByEmail`（建帳號 + 設角色）+ 一次性暫時\n密碼 + best-effort staff.invite 稽核，gated `role.manage`（admin-only）。\n\n⚠ 回應內含一次性明文暫時密碼 `tempPassword`（與後台一次性對話框同等信任：HTTPS +\nbearer）；僅此一次回傳，CLI 顯示後請立即轉交並要求員工首次登入改密。",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "userId": {
                          "type": "string",
                          "description": "新建立員工的使用者 ID。"
                        },
                        "tempPassword": {
                          "type": "string",
                          "description": "一次性明文暫時密碼，僅此次回傳（請立即轉交並要求員工首次登入改密）。"
                        },
                        "email": {
                          "type": "string",
                          "description": "新員工的登入 Email。"
                        },
                        "role": {
                          "type": "string",
                          "description": "指派的員工角色（admin／sales／op／accountant）。"
                        }
                      },
                      "required": [
                        "userId",
                        "tempPassword",
                        "email",
                        "role"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "role.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "受邀員工的登入 Email，作為帳號識別（max 120）"
                  },
                  "name": {
                    "type": "string",
                    "description": "員工顯示姓名（max 100 · min 1）"
                  },
                  "role": {
                    "type": "string",
                    "description": "指派的員工角色（admin／sales／op／accountant），決定權限範圍（min 1）"
                  }
                },
                "required": [
                  "email",
                  "name",
                  "role"
                ]
              }
            }
          }
        }
      }
    },
    "/suppliers": {
      "get": {
        "operationId": "get_suppliers",
        "tags": [
          "suppliers"
        ],
        "summary": "廠商目錄列表",
        "description": "GET /api/v1/suppliers — 廠商目錄列表（出款對象主檔，含遮罩收款資料）。\nstatus: active | inactive | all（預設 active）；q 名稱/類別模糊搜尋。tenant-wide。",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "inactive",
                "all"
              ],
              "description": "依狀態篩選（active 啟用 / inactive 停用 / all 全部，預設 active）"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "關鍵字搜尋（廠商名稱或類別）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "廠商 ID。"
                          },
                          "name": {
                            "type": "string",
                            "description": "廠商名稱。"
                          },
                          "categoryHint": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "慣用類別提示（租戶自定，非硬枚舉）。"
                          },
                          "payeeAccountName": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "收款人戶名（批次轉帳檔欄 (1)）。"
                          },
                          "payeeBankCode": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "收款銀行代號（批次轉帳檔欄 (3)）。"
                          },
                          "payeeAccountNumber": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "收款帳號（批次轉帳檔欄 (2)，遮罩回傳）。"
                          },
                          "status": {
                            "description": "狀態：active 啟用 / inactive 停用（停用不刪）。"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "建立時間。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "categoryHint",
                          "payeeAccountName",
                          "payeeBankCode",
                          "payeeAccountNumber",
                          "status",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "supplier.read",
        "x-module": "accounting"
      },
      "post": {
        "operationId": "post_suppliers",
        "tags": [
          "suppliers"
        ],
        "description": "GET /api/v1/suppliers — 廠商目錄列表（出款對象主檔，含遮罩收款資料）。\nstatus: active | inactive | all（預設 active）；q 名稱/類別模糊搜尋。tenant-wide。",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：廠商已新增。"
                        },
                        "id": {
                          "type": "string",
                          "description": "新建立廠商的 ID（sup_ 前綴）。"
                        }
                      },
                      "required": [
                        "ok",
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "supplier.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "廠商名稱（出款對象顯示名）（max 120 · min 1）"
                  },
                  "categoryHint": {
                    "type": "string",
                    "description": "類別提示（如住宿、交通、餐飲），供分類與搜尋（max 60）"
                  },
                  "payeeAccountName": {
                    "type": "string",
                    "description": "收款戶名（須與銀行帳戶登記名一致）（max 65）"
                  },
                  "payeeBankCode": {
                    "type": "string",
                    "description": "銀行代號（3~7 碼數字，台銀通用四欄轉帳檔用）（格式限定）"
                  },
                  "payeeAccountNumber": {
                    "type": "string",
                    "description": "收款銀行帳號（純數字，write-only 寫入後僅回遮罩）（格式限定 · max 20）"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/suppliers/{id}": {
      "get": {
        "operationId": "get_suppliers_id_",
        "tags": [
          "suppliers"
        ],
        "summary": "單一廠商主檔",
        "description": "GET /api/v1/suppliers/{id} — 單一廠商主檔（含遮罩收款銀行三欄）。\n查無 → 404。tenant-wide，無 owner-scope。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "廠商 id（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "廠商 ID。"
                        },
                        "name": {
                          "type": "string",
                          "description": "廠商名稱。"
                        },
                        "categoryHint": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "慣用類別提示（租戶自定，非硬枚舉）。"
                        },
                        "payeeAccountName": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "收款人戶名（批次轉帳檔欄 (1)）。"
                        },
                        "payeeBankCode": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "收款銀行代號（批次轉帳檔欄 (3)）。"
                        },
                        "payeeAccountNumber": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "收款帳號（批次轉帳檔欄 (2)，遮罩回傳）。"
                        },
                        "status": {
                          "description": "狀態：active 啟用 / inactive 停用（停用不刪）。"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "建立時間。"
                        },
                        "updatedAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "最後更新時間。"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "categoryHint",
                        "payeeAccountName",
                        "payeeBankCode",
                        "payeeAccountNumber",
                        "status",
                        "createdAt",
                        "updatedAt"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "supplier.read"
      },
      "patch": {
        "operationId": "patch_suppliers_id_",
        "tags": [
          "suppliers"
        ],
        "description": "GET /api/v1/suppliers/{id} — 單一廠商主檔（含遮罩收款銀行三欄）。\n查無 → 404。tenant-wide，無 owner-scope。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "廠商 id（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "固定為 true：廠商資料已更新。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "supplier.manage",
        "x-module": "accounting",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "廠商名稱（出款對象顯示名）（max 120 · min 1）"
                  },
                  "categoryHint": {
                    "type": "string",
                    "description": "類別提示（如住宿、交通、餐飲），供分類與搜尋（max 60）"
                  },
                  "payeeAccountName": {
                    "type": "string",
                    "description": "收款戶名（須與銀行帳戶登記名一致）（max 65）"
                  },
                  "payeeBankCode": {
                    "type": "string",
                    "description": "銀行代號（3~7 碼數字，台銀通用四欄轉帳檔用）（格式限定）"
                  },
                  "payeeAccountNumber": {
                    "type": "string",
                    "description": "收款銀行帳號（純數字，write-only 寫入後僅回遮罩）（格式限定 · max 20）"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/trips": {
      "get": {
        "operationId": "get_trips",
        "tags": [
          "trips"
        ],
        "description": "/api/v1/trips — admin trip catalog.\n  GET  : index (the /admin/trips table over HTTP). Optional status / free-text\n         / group-code filters, identical to the back office. Tenant-wide.\n  POST : create a trip — same core op + audit as the back office\n         `createTripAction`; gated `trip.manage`.\nSee specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依行程狀態篩選（draft 草稿／published 上架／archived 封存）"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "自由文字搜尋（行程標題／代稱／目的地）"
            }
          },
          {
            "name": "groupCode",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依團號篩選，列出含該團號梯次的行程"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "行程 id（trip_ 前綴）。"
                          },
                          "slug": {
                            "type": "string",
                            "description": "行程網址 slug。"
                          },
                          "title": {
                            "type": "string",
                            "description": "行程標題。"
                          },
                          "destination": {
                            "type": "string",
                            "description": "目的地名稱。"
                          },
                          "durationDays": {
                            "type": "number",
                            "description": "天數。"
                          },
                          "priceFromTwd": {
                            "type": "number",
                            "description": "「NT$ X 起」起價（TWD 整數）。"
                          },
                          "status": {
                            "description": "上架狀態：draft 草稿 / published 已上架 / archived 封存。"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "最後更新時間。"
                          },
                          "isClimbing": {
                            "type": "boolean",
                            "description": "是否登山團（行程層模組旗標）。"
                          },
                          "isOverseas": {
                            "type": "boolean",
                            "description": "是否海外團（行程層模組旗標）。"
                          },
                          "activeDepartureCount": {
                            "type": "number",
                            "description": "Count of departures with status='selling'."
                          },
                          "nextDepartureDate": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Earliest selling departure_date, ISO date string, or null."
                          },
                          "representativeGroupCode": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "代表團號（group-code §8.2）：最新一筆有團號的梯次；無則 null（UI 顯示 —）。"
                          }
                        },
                        "required": [
                          "id",
                          "slug",
                          "title",
                          "destination",
                          "durationDays",
                          "priceFromTwd",
                          "status",
                          "updatedAt",
                          "isClimbing",
                          "isOverseas",
                          "activeDepartureCount",
                          "nextDepartureDate",
                          "representativeGroupCode"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "trip.read"
      },
      "post": {
        "operationId": "post_trips",
        "tags": [
          "trips"
        ],
        "summary": "same core op + audit as the back office",
        "description": "/api/v1/trips — admin trip catalog.\n  GET  : index (the /admin/trips table over HTTP). Optional status / free-text\n         / group-code filters, identical to the back office. Tenant-wide.\n  POST : create a trip — same core op + audit as the back office\n         `createTripAction`; gated `trip.manage`.\nSee specs/tenant-cli.md.",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立行程的 id（trip_ 前綴）。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "trip.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "slug": {
                    "type": "string",
                    "description": "行程網址代稱（slug），用於前台路徑與後台識別，只能小寫英數與連字號（格式限定）"
                  },
                  "title": {
                    "type": "string",
                    "description": "行程標題，顯示於前台與訂單（max 200 · min 1）"
                  },
                  "summary": {
                    "type": "string",
                    "description": "行程摘要，前台列表卡片用的一句話簡介（max 500）"
                  },
                  "contentMdx": {
                    "type": "string",
                    "description": "行程詳細內容（MDX 格式），前台行程頁主文（max 50000）"
                  },
                  "destination": {
                    "type": "string",
                    "description": "目的地名稱（max 100 · min 1）"
                  },
                  "durationDays": {
                    "type": "number",
                    "description": "行程天數（max 60 · min 1）"
                  },
                  "priceFromTwd": {
                    "type": "number",
                    "description": "起價（新台幣），前台「OOO 元起」顯示用（max 10000000 · min 0）"
                  },
                  "directPriceTwd": {
                    "type": "number",
                    "description": "直客定價（新台幣），留空（null）則退回起價繼承"
                  },
                  "agencyPriceTwd": {
                    "type": "number",
                    "description": "同業定價（新台幣），留空（null）則退回直客／起價繼承"
                  },
                  "depositMode": {
                    "type": "string",
                    "enum": [
                      "none",
                      "fixed",
                      "percent"
                    ],
                    "description": "訂金計算方式（none 不收／fixed 固定金額／percent 百分比）"
                  },
                  "depositAmountTwd": {
                    "type": "number",
                    "description": "訂金固定金額（新台幣），depositMode 為 fixed 時生效"
                  },
                  "depositPercent": {
                    "type": "number",
                    "description": "訂金百分比（1–100），depositMode 為 percent 時生效"
                  },
                  "balanceDueDaysBeforeDeparture": {
                    "type": "number",
                    "description": "尾款應繳截止日（出發前幾天）"
                  },
                  "feeInclusions": {
                    "type": "array",
                    "items": {},
                    "description": "費用包含項目清單，每項含勾選狀態（ok）與說明文字（text）（max 30）"
                  },
                  "isClimbing": {
                    "type": "boolean",
                    "description": "是否為登山團（啟用登山相關模組欄位）"
                  },
                  "isOverseas": {
                    "type": "boolean",
                    "description": "是否為海外團"
                  },
                  "gradeScore": {
                    "type": "number",
                    "description": "登山難度評分（0–100），null 表示未評級（max 100 · min 0）"
                  },
                  "requiresAlpineExperience": {
                    "type": "boolean",
                    "description": "是否需具備高山經驗"
                  },
                  "gradeLabel": {
                    "type": "string",
                    "description": "難度等級標籤文字（max 50）"
                  },
                  "confirmGroupMultiple": {
                    "type": "number",
                    "description": "成團人數倍數（如國內高山團為 7 的倍數），null 表示不限（max 1000 · min 1）"
                  },
                  "restrictedQuotaEnabled": {
                    "type": "boolean",
                    "description": "是否啟用每人使用次數限制"
                  },
                  "quotaPerPersonLimit": {
                    "type": "number",
                    "description": "每人於限制窗內可使用次數上限，null 表示不限（max 1000 · min 1）"
                  },
                  "quotaWindow": {
                    "type": "string",
                    "description": "次數限制的計算窗口（max 50）"
                  },
                  "waitlistEnabled": {
                    "type": "boolean",
                    "description": "是否開放候補"
                  },
                  "coverImageUrl": {
                    "type": "string",
                    "description": "行程封面圖網址（http／https）（max 500）"
                  },
                  "seoTitle": {
                    "type": "string",
                    "description": "SEO 標題，覆寫前台頁面 title（max 200）"
                  },
                  "seoDescription": {
                    "type": "string",
                    "description": "SEO 描述，覆寫前台 meta description（max 500）"
                  },
                  "ogImageUrl": {
                    "type": "string",
                    "description": "Open Graph 社群分享圖網址（http／https）（max 500）"
                  },
                  "status": {
                    "type": "string",
                    "description": "行程狀態（draft 草稿／published 上架／archived 封存）"
                  },
                  "pnlRegionId": {
                    "type": "string",
                    "description": "損益分區 id（pnl_regions），null 表示未指派、退回系統派生（max 60）"
                  }
                },
                "required": [
                  "slug",
                  "title",
                  "destination",
                  "durationDays",
                  "priceFromTwd"
                ]
              }
            }
          }
        }
      }
    },
    "/trips/{id}": {
      "get": {
        "operationId": "get_trips_id_",
        "tags": [
          "trips"
        ],
        "summary": "full admin trip detail",
        "description": "GET /api/v1/trips/{id} — full admin trip detail (header + departures + group\ncodes + cost-template binding). Tenant-wide; missing → 404.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "行程 ID（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "object",
                          "properties": {
                            "length": {
                              "type": "number",
                              "description": "Returns the length of a String object."
                            }
                          },
                          "required": [
                            "length"
                          ],
                          "description": "行程 id（trip_ 前綴）。"
                        },
                        "slug": {
                          "type": "string",
                          "description": "行程網址 slug（公開站路徑）。"
                        },
                        "title": {
                          "type": "string",
                          "description": "行程標題。"
                        },
                        "summary": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "一句話摘要；null = 未設。"
                        },
                        "contentMdx": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "行程內文（MDX 原始碼）；null = 未設。"
                        },
                        "destination": {
                          "type": "string",
                          "description": "目的地名稱。"
                        },
                        "durationDays": {
                          "type": "number",
                          "description": "天數。"
                        },
                        "priceFromTwd": {
                          "type": "number",
                          "description": "「NT$ X 起」起價（TWD 整數）。"
                        },
                        "coverImageUrl": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "封面圖 URL；null = 未設。"
                        },
                        "status": {
                          "description": "上架狀態：draft 草稿 / published 已上架 / archived 封存。"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "建立時間。"
                        },
                        "updatedAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "最後更新時間。"
                        },
                        "isClimbing": {
                          "type": "boolean",
                          "description": "是否登山團（行程層模組旗標）。"
                        },
                        "isOverseas": {
                          "type": "boolean",
                          "description": "是否海外團（行程層模組旗標）。"
                        },
                        "gradeScore": {
                          "type": [
                            "number",
                            "null"
                          ],
                          "description": "難度評鑑分數（climbing-screening §3.1）；null = 未評級。"
                        },
                        "requiresAlpineExperience": {
                          "type": "boolean",
                          "description": "是否要求具備高山經驗（報名審核用）。"
                        },
                        "gradeLabel": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "難度標籤（如「B＋」）；null = 未設。"
                        },
                        "feeInclusions": {
                          "type": [
                            "array",
                            "null"
                          ],
                          "items": {},
                          "description": "團費包含/不包含（前台費用區唯一來源）；null = 未設。"
                        },
                        "seoTitle": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "SEO 標題覆寫；null = 沿用 title。"
                        },
                        "seoDescription": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "SEO 描述；null = 未設。"
                        },
                        "ogImageUrl": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Open Graph 分享圖 URL；null = 未設。"
                        },
                        "images": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "圖片資源 id（timg_ 前綴）。"
                              },
                              "url": {
                                "type": "string",
                                "description": "圖片公開 URL。"
                              },
                              "caption": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "圖說文字；null = 無。"
                              },
                              "displayOrder": {
                                "type": "number",
                                "description": "在行程相簿中的排序（由小到大）。"
                              }
                            },
                            "required": [
                              "id",
                              "url",
                              "caption",
                              "displayOrder"
                            ]
                          },
                          "description": "行程相簿圖片（依 displayOrder 排序）。"
                        },
                        "departures": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "梯次 id（dep_ 前綴）。"
                              },
                              "tripId": {
                                "type": "string",
                                "description": "所屬行程 id（trip_ 前綴）。"
                              },
                              "departureDate": {
                                "type": "string",
                                "description": "出發日（ISO 'YYYY-MM-DD'）。"
                              },
                              "returnDate": {
                                "type": "string",
                                "description": "回程日（ISO 'YYYY-MM-DD'）。"
                              },
                              "priceTwd": {
                                "type": "number",
                                "description": "售價（TWD 整數，未稅牌價）。"
                              },
                              "capacity": {
                                "type": "number",
                                "description": "名額上限（人數）。"
                              },
                              "bookedCount": {
                                "type": "number",
                                "description": "已成團佔用名額（人數）。"
                              },
                              "status": {
                                "description": "梯次狀態：selling 販售中 / closed 關閉 / cancelled 取消 / completed 已結團。"
                              },
                              "notes": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "內部備註；null = 無。"
                              },
                              "allocationMode": {
                                "type": "string",
                                "enum": [
                                  "fcfs",
                                  "lottery"
                                ],
                                "description": "抽籤分配模式（lottery-integration §2.1）：fcfs=先到先得 / lottery=抽籤制。"
                              },
                              "agencyPriceTwd": {
                                "type": [
                                  "number",
                                  "null"
                                ],
                                "description": "同業價（TWD 整數）；admin-only，公開站不映射。"
                              },
                              "depositMode": {
                                "anyOf": [
                                  {},
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "訂金規則模式：none 免訂金 / fixed 定額 / percent 比例；admin-only。"
                              },
                              "depositAmountTwd": {
                                "type": [
                                  "number",
                                  "null"
                                ],
                                "description": "訂金定額（TWD 整數，depositMode=fixed 時適用）；admin-only。"
                              },
                              "depositPercent": {
                                "type": [
                                  "number",
                                  "null"
                                ],
                                "description": "訂金比例（百分比，depositMode=percent 時適用）；admin-only。"
                              },
                              "groupCode": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "團號（group-code §3.3）；admin-only，公開站不映射。"
                              },
                              "regionCode": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "地區代碼（團號組成）；admin-only。"
                              },
                              "airlineCode": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "航空公司代碼（團號組成）；admin-only。"
                              },
                              "promoActive": {
                                "type": [
                                  "boolean",
                                  "null"
                                ],
                                "description": "梯次促銷是否啟用（trip-pricing）；admin-only。"
                              },
                              "promoPriceTwd": {
                                "type": [
                                  "number",
                                  "null"
                                ],
                                "description": "促銷覆寫售價（TWD 整數）；admin-only。"
                              },
                              "promoAgencyPriceTwd": {
                                "type": [
                                  "number",
                                  "null"
                                ],
                                "description": "促銷覆寫同業價（TWD 整數）；admin-only。"
                              }
                            },
                            "required": [
                              "id",
                              "tripId",
                              "departureDate",
                              "returnDate",
                              "priceTwd",
                              "capacity",
                              "bookedCount",
                              "status",
                              "notes",
                              "allocationMode"
                            ]
                          },
                          "description": "Active (selling, future) departures only on the public side; all on admin."
                        }
                      },
                      "required": [
                        "id",
                        "slug",
                        "title",
                        "summary",
                        "contentMdx",
                        "destination",
                        "durationDays",
                        "priceFromTwd",
                        "coverImageUrl",
                        "status",
                        "createdAt",
                        "updatedAt",
                        "isClimbing",
                        "isOverseas",
                        "gradeScore",
                        "requiresAlpineExperience",
                        "gradeLabel",
                        "feeInclusions",
                        "seoTitle",
                        "seoDescription",
                        "ogImageUrl",
                        "images",
                        "departures"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "trip.read"
      },
      "patch": {
        "operationId": "patch_trips_id_",
        "tags": [
          "trips"
        ],
        "description": "GET /api/v1/trips/{id} — full admin trip detail (header + departures + group\ncodes + cost-template binding). Tenant-wide; missing → 404.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "行程 ID（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "trip.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "slug": {
                    "type": "string",
                    "description": "行程網址代稱（slug），用於前台路徑與後台識別，只能小寫英數與連字號（格式限定）"
                  },
                  "title": {
                    "type": "string",
                    "description": "行程標題，顯示於前台與訂單（max 200 · min 1）"
                  },
                  "summary": {
                    "type": "string",
                    "description": "行程摘要，前台列表卡片用的一句話簡介（max 500）"
                  },
                  "contentMdx": {
                    "type": "string",
                    "description": "行程詳細內容（MDX 格式），前台行程頁主文（max 50000）"
                  },
                  "destination": {
                    "type": "string",
                    "description": "目的地名稱（max 100 · min 1）"
                  },
                  "durationDays": {
                    "type": "number",
                    "description": "行程天數（max 60 · min 1）"
                  },
                  "priceFromTwd": {
                    "type": "number",
                    "description": "起價（新台幣），前台「OOO 元起」顯示用（max 10000000 · min 0）"
                  },
                  "directPriceTwd": {
                    "type": "number",
                    "description": "直客定價（新台幣），留空（null）則退回起價繼承"
                  },
                  "agencyPriceTwd": {
                    "type": "number",
                    "description": "同業定價（新台幣），留空（null）則退回直客／起價繼承"
                  },
                  "depositMode": {
                    "type": "string",
                    "enum": [
                      "none",
                      "fixed",
                      "percent"
                    ],
                    "description": "訂金計算方式（none 不收／fixed 固定金額／percent 百分比）"
                  },
                  "depositAmountTwd": {
                    "type": "number",
                    "description": "訂金固定金額（新台幣），depositMode 為 fixed 時生效"
                  },
                  "depositPercent": {
                    "type": "number",
                    "description": "訂金百分比（1–100），depositMode 為 percent 時生效"
                  },
                  "balanceDueDaysBeforeDeparture": {
                    "type": "number",
                    "description": "尾款應繳截止日（出發前幾天）"
                  },
                  "feeInclusions": {
                    "type": "array",
                    "items": {},
                    "description": "費用包含項目清單，每項含勾選狀態（ok）與說明文字（text）（max 30）"
                  },
                  "isClimbing": {
                    "type": "boolean",
                    "description": "是否為登山團（啟用登山相關模組欄位）"
                  },
                  "isOverseas": {
                    "type": "boolean",
                    "description": "是否為海外團"
                  },
                  "gradeScore": {
                    "type": "number",
                    "description": "登山難度評分（0–100），null 表示未評級（max 100 · min 0）"
                  },
                  "requiresAlpineExperience": {
                    "type": "boolean",
                    "description": "是否需具備高山經驗"
                  },
                  "gradeLabel": {
                    "type": "string",
                    "description": "難度等級標籤文字（max 50）"
                  },
                  "confirmGroupMultiple": {
                    "type": "number",
                    "description": "成團人數倍數（如國內高山團為 7 的倍數），null 表示不限（max 1000 · min 1）"
                  },
                  "restrictedQuotaEnabled": {
                    "type": "boolean",
                    "description": "是否啟用每人使用次數限制"
                  },
                  "quotaPerPersonLimit": {
                    "type": "number",
                    "description": "每人於限制窗內可使用次數上限，null 表示不限（max 1000 · min 1）"
                  },
                  "quotaWindow": {
                    "type": "string",
                    "description": "次數限制的計算窗口（max 50）"
                  },
                  "waitlistEnabled": {
                    "type": "boolean",
                    "description": "是否開放候補"
                  },
                  "coverImageUrl": {
                    "type": "string",
                    "description": "行程封面圖網址（http／https）（max 500）"
                  },
                  "seoTitle": {
                    "type": "string",
                    "description": "SEO 標題，覆寫前台頁面 title（max 200）"
                  },
                  "seoDescription": {
                    "type": "string",
                    "description": "SEO 描述，覆寫前台 meta description（max 500）"
                  },
                  "ogImageUrl": {
                    "type": "string",
                    "description": "Open Graph 社群分享圖網址（http／https）（max 500）"
                  },
                  "status": {
                    "type": "string",
                    "description": "行程狀態（draft 草稿／published 上架／archived 封存）"
                  },
                  "pnlRegionId": {
                    "type": "string",
                    "description": "損益分區 id（pnl_regions），null 表示未指派、退回系統派生（max 60）"
                  }
                },
                "required": [
                  "slug",
                  "title",
                  "destination",
                  "durationDays",
                  "priceFromTwd"
                ]
              }
            }
          }
        }
      }
    },
    "/trips/{id}/cost-template": {
      "put": {
        "operationId": "put_trips_id_cost_template",
        "tags": [
          "trips"
        ],
        "summary": "bind / unbind a trip's cost templates",
        "description": "PUT /api/v1/trips/{id}/cost-template — bind / unbind a trip's cost templates\n(cost-template §2.3 / §4.2, 多範本疊加). Same core op as `setTripCostTemplateAction`;\ngated `cost_template.manage` (admin / accountant — NOT sales, even though\nsales has trip.manage). Send `templateIds: []` (集合，依序疊加) to replace the whole\nbinding set; `[]` or omitted = unbind all. `templateId`（單一，含 null）保留向後相容。\nAudit is written INSIDE setTripCostTemplates, so no shell replication here.\nCostTemplateError → 409 (handled by mapError).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "行程 ID（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "cost_template.manage",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "templateIds": {
                    "type": "array",
                    "items": {},
                    "description": "要綁定的成本範本 ID 陣列（依序疊加）；[] 或省略表示解除全部綁定"
                  },
                  "templateId": {
                    "type": "string",
                    "description": "（向後相容，單一）要綁定的成本範本 ID；null 表示解綁（min 1）"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/trips/{id}/departures": {
      "post": {
        "operationId": "post_trips_id_departures",
        "tags": [
          "trips"
        ],
        "summary": "add a departure to a trip",
        "description": "POST /api/v1/trips/{id}/departures — add a departure to a trip (the `{id}`\npath segment is the tripId; reuses the existing [id] segment to avoid a\nsibling dynamic-name collision). Same core op + shell audit as the back\noffice `addDepartureAction`; gated `trip.manage`. Reuses the transport-neutral\nDepartureInputSchema. The return-before-departure cross-field check is\nreplicated as a 409. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "行程 ID（路徑參數），新梯次所屬的行程（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "新建立梯次的 id（dep_ 前綴）。"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "trip.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "departureDate": {
                    "type": "string",
                    "description": "出發日期（YYYY-MM-DD）"
                  },
                  "returnDate": {
                    "type": "string",
                    "description": "回程日期（YYYY-MM-DD），須晚於出發日"
                  },
                  "priceTwd": {
                    "type": "number",
                    "description": "梯次直客售價（新台幣）（max 10000000 · min 0）"
                  },
                  "capacity": {
                    "type": "number",
                    "description": "梯次總名額（座位上限）（max 200 · min 1）"
                  },
                  "agencyPriceTwd": {
                    "type": "number",
                    "description": "梯次同業售價（新台幣）（max 10000000 · min 0）"
                  },
                  "depositMode": {
                    "type": "string",
                    "enum": [
                      "none",
                      "fixed",
                      "percent"
                    ],
                    "description": "訂金計算方式（none 不收／fixed 固定金額／percent 百分比）"
                  },
                  "depositAmountTwd": {
                    "type": "number",
                    "description": "訂金固定金額（新台幣），depositMode 為 fixed 時生效（max 10000000 · min 0）"
                  },
                  "depositPercent": {
                    "type": "number",
                    "description": "訂金百分比（1–100），depositMode 為 percent 時生效（max 100 · min 1）"
                  },
                  "status": {
                    "type": "string",
                    "description": "梯次狀態（selling 銷售中／closed 關閉／cancelled 取消／completed 完成）"
                  },
                  "regionCode": {
                    "type": "string",
                    "description": "團號地區來源碼（2–3 碼大寫英數），用於產生團號，可不指定（格式限定）"
                  },
                  "airlineCode": {
                    "type": "string",
                    "description": "團號航空來源碼（2–3 碼大寫英數），用於產生團號，可不指定（格式限定）"
                  }
                },
                "required": [
                  "departureDate",
                  "returnDate",
                  "priceTwd",
                  "capacity"
                ]
              }
            }
          }
        }
      }
    },
    "/trips/{id}/departures/{depId}/lodging": {
      "post": {
        "operationId": "post_trips_id_departures_depId_lodging",
        "tags": [
          "trips"
        ],
        "summary": "為某梯次預留自家旅宿配套",
        "description": "POST /api/v1/trips/{id}/departures/{depId}/lodging — 為某梯次預留自家旅宿配套\n（整塊預留 + 派生 departure_rooms）。鏡像後台 `setDepartureLodgingAction`：同核心 op\n`setDepartureLodging`，同權限 `trip.manage` + 訂房模組閘，同 trip-scope IDOR 邊界\n（departureId 須屬於 tripId，否則 404）。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "行程 ID（路徑參數），梯次所屬的行程（min 1）"
            }
          },
          {
            "name": "depId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（路徑參數），要預留旅宿的梯次（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "trip.manage",
        "x-module": "lodging",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "propertyId": {
                    "type": "string",
                    "description": "自家旅宿物件 ID（min 1）"
                  },
                  "roomTypeId": {
                    "type": "string",
                    "description": "該旅宿的房型 ID（min 1）"
                  },
                  "checkIn": {
                    "type": "string",
                    "description": "入住日（YYYY-MM-DD）（格式限定）"
                  },
                  "checkOut": {
                    "type": "string",
                    "description": "退房日（YYYY-MM-DD），須晚於入住日（格式限定）"
                  },
                  "blockUnits": {
                    "type": "number",
                    "description": "整塊預留的房間間數"
                  }
                },
                "required": [
                  "propertyId",
                  "roomTypeId",
                  "checkIn",
                  "checkOut",
                  "blockUnits"
                ]
              }
            }
          }
        }
      }
    },
    "/trips/{id}/lodging/{dlId}": {
      "delete": {
        "operationId": "delete_trips_id_lodging_dlId_",
        "tags": [
          "trips"
        ],
        "summary": "釋回某梯次的自家旅宿配套預留",
        "description": "DELETE /api/v1/trips/{id}/lodging/{dlId} — 釋回某梯次的自家旅宿配套預留（釋回 block\n庫存 + 刪派生 departure_rooms；手 key 房不動）。鏡像後台 `releaseDepartureLodgingAction`：\n同核心 op `releaseDepartureLodging`，同權限 `trip.manage` + 訂房模組閘，同 trip-scope\nIDOR 邊界（該 block 須屬於 tripId 底下的梯次，否則 404）。idempotent。",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "行程 ID（路徑參數），預留所屬的行程（min 1）"
            }
          },
          {
            "name": "dlId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次旅宿配套預留 ID（路徑參數），要釋回的預留（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "trip.manage",
        "x-module": "lodging"
      }
    },
    "/trips/cost-templates": {
      "get": {
        "operationId": "get_trips_cost_templates",
        "tags": [
          "trips"
        ],
        "summary": "active cost templates for",
        "description": "GET /api/v1/trips/cost-templates?status=active — active cost templates for\ntrip binding (the combobox options on the trip cost-template field).\nTenant-wide; gated on cost_template.read. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "成本範本狀態篩選；目前僅回傳啟用中（active）範本"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "成本範本 id（ct_ 前綴）。"
                          },
                          "name": {
                            "type": "string",
                            "description": "成本範本名稱。"
                          }
                        },
                        "required": [
                          "id",
                          "name"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "cost_template.read"
      }
    },
    "/trips/departures": {
      "get": {
        "operationId": "get_trips_departures",
        "tags": [
          "trips"
        ],
        "summary": "group-code lookup over HTTP.",
        "description": "GET /api/v1/trips/departures — group-code lookup over HTTP.\n  ?groupCode=<code>        → exact match → single departure (or 404)\n  ?groupCodePrefix=<prefix> → prefix match → list of departures\nExactly one of the two is required. Tenant-wide (no owner scope).",
        "parameters": [
          {
            "name": "groupCode",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "完整團號，精確比對單一梯次（min 1）"
            }
          },
          {
            "name": "groupCodePrefix",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "團號前綴，前綴比對列出多個梯次（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {}
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "trip.read"
      }
    },
    "/trips/departures/{departureId}": {
      "patch": {
        "operationId": "patch_trips_departures_departureId_",
        "tags": [
          "trips"
        ],
        "summary": "per-row pricing / deposit /",
        "description": "PATCH /api/v1/trips/departures/{departureId} — per-row pricing / deposit /\npromo edit of an existing departure (no date/capacity/status). Same core op +\nshell audit as `updateDepartureAction`; gated `trip.manage`. Reuses the\ntransport-neutral DepartureEditSchema; null = clear (inherit), omitted skips.\nThe action coalesces blanks to null when calling updateDeparture — replicated\nexactly here. See specs/tenant-cli.md.",
        "parameters": [
          {
            "name": "departureId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "trip.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "priceTwd": {
                    "type": "number",
                    "description": "梯次直客售價（新台幣）（max 10000000 · min 0）"
                  },
                  "agencyPriceTwd": {
                    "type": "number",
                    "description": "梯次同業售價（新台幣），留空則退回常規定價鏈（max 10000000 · min 0）"
                  },
                  "depositMode": {
                    "type": "string",
                    "enum": [
                      "none",
                      "fixed",
                      "percent"
                    ],
                    "description": "訂金計算方式（none 不收／fixed 固定金額／percent 百分比）"
                  },
                  "depositAmountTwd": {
                    "type": "number",
                    "description": "訂金固定金額（新台幣），depositMode 為 fixed 時生效（max 10000000 · min 0）"
                  },
                  "depositPercent": {
                    "type": "number",
                    "description": "訂金百分比（1–100），depositMode 為 percent 時生效（max 100 · min 1）"
                  },
                  "promoActive": {
                    "type": "boolean",
                    "description": "是否啟用梯次促銷覆寫價"
                  },
                  "promoPriceTwd": {
                    "type": "number",
                    "description": "直客促銷價（新台幣），啟用促銷時必填，null 表示清空（max 10000000 · min 1）"
                  },
                  "promoAgencyPriceTwd": {
                    "type": "number",
                    "description": "同業促銷價（新台幣），null 表示同業退回常規鏈（max 10000000 · min 1）"
                  }
                },
                "required": [
                  "priceTwd"
                ]
              }
            }
          }
        }
      }
    },
    "/trips/departures/{departureId}/group-code": {
      "post": {
        "operationId": "post_trips_departures_departureId_group_code",
        "tags": [
          "trips"
        ],
        "summary": "manual group-code",
        "description": "POST /api/v1/trips/departures/{departureId}/group-code — manual group-code\noverride (group-code §4.4). Same core op + shell audit as\n`overrideDepartureGroupCodeAction`; gated `departure.update` (線控 manages\n梯次, sales does not). Reuses OverrideGroupCodeSchema (loose format check +\nuppercase normalise). GroupCodeConflictError → 409 (handled by mapError).",
        "parameters": [
          {
            "name": "departureId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "要覆寫團號的梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        },
                        "groupCode": {
                          "type": "string",
                          "description": "設定後的團號。"
                        }
                      },
                      "required": [
                        "ok",
                        "groupCode"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure.update",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "groupCode": {
                    "type": "string",
                    "description": "完整團號，格式為 YY+地區+航空+MMDD+序號（如 26EGTK1010A，自動轉大寫）"
                  }
                },
                "required": [
                  "groupCode"
                ]
              }
            }
          }
        }
      }
    },
    "/trips/departures/{departureId}/group-code/generate": {
      "post": {
        "operationId": "post_trips_departures_departureId_group_code_generate",
        "tags": [
          "trips"
        ],
        "summary": "auto",
        "description": "POST /api/v1/trips/departures/{departureId}/group-code/generate — auto\ngroup-code generation (group-code §4.1). Same core op + shell audit as\n`generateDepartureGroupCodeAction`; gated `departure.update`. Reuses\nGenerateGroupCodeSchema (region/airline source codes + departure date).\nGroupCodeConflictError → 409 (handled by mapError).",
        "parameters": [
          {
            "name": "departureId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "要產生團號的梯次 ID（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "groupCode": {
                          "type": "string",
                          "description": "自動產生的團號。"
                        }
                      },
                      "required": [
                        "groupCode"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "departure.update",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "regionCode": {
                    "type": "string",
                    "description": "地區碼，2–3 碼大寫英數（自動轉大寫）"
                  },
                  "airlineCode": {
                    "type": "string",
                    "description": "航空碼（選填），2–3 碼大寫英數；國內團留空省略航空段"
                  },
                  "departureDate": {
                    "type": "string",
                    "description": "出發日期（ISO 格式 YYYY-MM-DD，取 MMDD 組成團號）"
                  }
                },
                "required": [
                  "regionCode",
                  "departureDate"
                ]
              }
            }
          }
        }
      }
    },
    "/trips/departures/{departureId}/status": {
      "post": {
        "operationId": "post_trips_departures_departureId_status",
        "tags": [
          "trips"
        ],
        "summary": "change a departure's",
        "description": "POST /api/v1/trips/departures/{departureId}/status — change a departure's\nlifecycle status (selling/closed/cancelled/completed). Same core op + shell\naudit as `setDepartureStatusAction`; gated `trip.manage`. Invalid status →\n422 (the back office silently no-ops; the API surfaces the validation error).",
        "parameters": [
          {
            "name": "departureId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "梯次 ID（路徑參數）（min 1）"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "description": "操作成功旗標，恆為 true。"
                        }
                      },
                      "required": [
                        "ok"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "trip.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "description": "目標梯次狀態（selling 銷售中／closed 關閉／cancelled 取消／completed 完成）"
                  }
                },
                "required": [
                  "status"
                ]
              }
            }
          }
        }
      }
    },
    "/trips/export": {
      "get": {
        "operationId": "get_trips_export",
        "tags": [
          "trips"
        ],
        "summary": "匯出行程",
        "description": "GET /api/v1/trips/export — 匯出行程（同 /api/v1/trips 的 filter）。listAdminTrips 本即回全列\n（無分頁），故直接重用、無需逐頁。gated trip.read。",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依行程狀態篩選（draft 草稿／published 上架／archived 封存）"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "自由文字搜尋（行程標題／代稱／目的地）"
            }
          },
          {
            "name": "groupCode",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "依團號篩選，匯出含該團號梯次的行程"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "行程 id（trip_ 前綴）。"
                              },
                              "slug": {
                                "type": "string",
                                "description": "行程網址 slug。"
                              },
                              "title": {
                                "type": "string",
                                "description": "行程標題。"
                              },
                              "destination": {
                                "type": "string",
                                "description": "目的地名稱。"
                              },
                              "durationDays": {
                                "type": "number",
                                "description": "天數。"
                              },
                              "priceFromTwd": {
                                "type": "number",
                                "description": "「NT$ X 起」起價（TWD 整數）。"
                              },
                              "status": {
                                "description": "上架狀態：draft 草稿 / published 已上架 / archived 封存。"
                              },
                              "updatedAt": {
                                "type": "string",
                                "format": "date-time",
                                "description": "最後更新時間。"
                              },
                              "isClimbing": {
                                "type": "boolean",
                                "description": "是否登山團（行程層模組旗標）。"
                              },
                              "isOverseas": {
                                "type": "boolean",
                                "description": "是否海外團（行程層模組旗標）。"
                              },
                              "activeDepartureCount": {
                                "type": "number",
                                "description": "Count of departures with status='selling'."
                              },
                              "nextDepartureDate": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "Earliest selling departure_date, ISO date string, or null."
                              },
                              "representativeGroupCode": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "代表團號（group-code §8.2）：最新一筆有團號的梯次；無則 null（UI 顯示 —）。"
                              }
                            },
                            "required": [
                              "id",
                              "slug",
                              "title",
                              "destination",
                              "durationDays",
                              "priceFromTwd",
                              "status",
                              "updatedAt",
                              "isClimbing",
                              "isOverseas",
                              "activeDepartureCount",
                              "nextDepartureDate",
                              "representativeGroupCode"
                            ]
                          },
                          "description": "匯出的行程列（套用相同 filter，無分頁）。"
                        },
                        "total": {
                          "type": "number",
                          "description": "匯出總筆數。"
                        },
                        "truncated": {
                          "type": "boolean",
                          "description": "是否因上限被截斷（此端點回全列，恆為 false）。"
                        }
                      },
                      "required": [
                        "rows",
                        "total",
                        "truncated"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "trip.read"
      }
    },
    "/trips/import": {
      "post": {
        "operationId": "post_trips_import",
        "tags": [
          "trips"
        ],
        "summary": "行程批次匯入 commit：上傳檔",
        "description": "POST /api/v1/trips/import — 行程批次匯入 commit：上傳檔（base64）→ 重新解析同一檔（避免\ndry-run 後 TOCTOU）→ 就有效列建檔（每行程一交易、部分失敗隔離）。鏡像後台\n`commitImportAction`：同核心 op parseAndValidate + commitImport + 同上傳限制 + 真實模組\n授權（commit 端不放寬 module gate，防繞過）。gated trip.manage。\n\n上傳格式：JSON `{ filename, contentBase64 }`。",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "filename": {
                          "type": "string",
                          "description": "已匯入的檔名。"
                        },
                        "result": {
                          "type": "object",
                          "properties": {
                            "importBatchId": {
                              "type": "string",
                              "description": "本次匯入批次 id（imp_ 前綴），供稽核追溯。"
                            },
                            "createdTripCount": {
                              "type": "number",
                              "description": "新建行程數。"
                            },
                            "createdDepartureCount": {
                              "type": "number",
                              "description": "新建梯次數。"
                            },
                            "skippedCount": {
                              "type": "number",
                              "description": "略過列數（重複／無需匯入）。"
                            },
                            "errorCount": {
                              "type": "number",
                              "description": "失敗列數。"
                            },
                            "results": {
                              "type": "array",
                              "items": {
                                "type": "object"
                              },
                              "description": "逐列匯入結果。"
                            }
                          },
                          "required": [
                            "importBatchId",
                            "createdTripCount",
                            "createdDepartureCount",
                            "skippedCount",
                            "errorCount",
                            "results"
                          ],
                          "description": "匯入結果（建檔筆數與逐列結果）。"
                        }
                      },
                      "required": [
                        "filename",
                        "result"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "trip.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "filename": {
                    "type": "string",
                    "description": "上傳檔名，副檔名須為 .xlsx 或 .csv（min 1）"
                  },
                  "contentBase64": {
                    "type": "string",
                    "description": "檔案內容的 base64 編碼字串（上限 5 MB）（min 1）"
                  }
                },
                "required": [
                  "filename",
                  "contentBase64"
                ]
              }
            }
          }
        }
      }
    },
    "/trips/import/validate": {
      "post": {
        "operationId": "post_trips_import_validate",
        "tags": [
          "trips"
        ],
        "summary": "行程批次匯入 dry-run：上傳檔",
        "description": "POST /api/v1/trips/import/validate — 行程批次匯入 dry-run：上傳檔（base64）→ 解析 + 逐列\n驗證 → 預覽，**不寫任何資料**。鏡像後台 `parseImportAction`：同核心 op parseAndValidate +\n同上傳限制（validateImportUpload）+ 真實模組授權（getTenantModules 餵入驗證，未授權卻匯入\nis_climbing/is_overseas=true → 該列 error）。gated trip.manage。\n\n上傳格式：JSON `{ filename, contentBase64 }`（檔內容 base64）。",
        "responses": {
          "200": {
            "description": "成功（{ ok: true, data }）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "filename": {
                          "type": "string",
                          "description": "已驗證的檔名。"
                        },
                        "result": {
                          "type": "object",
                          "properties": {
                            "rows": {
                              "type": "array",
                              "items": {
                                "type": "object"
                              },
                              "description": "逐列預覽結果。"
                            },
                            "summary": {
                              "type": "object",
                              "description": "各狀態列數彙總。"
                            },
                            "fileError": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "整檔層級的致命錯誤（如超列上限、空檔、無法解析），非空時 rows 為空。"
                            }
                          },
                          "required": [
                            "rows",
                            "summary",
                            "fileError"
                          ],
                          "description": "試算（dry-run）結果（逐列預覽 + 彙總，不寫入）。"
                        }
                      },
                      "required": [
                        "filename",
                        "result"
                      ]
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗（{ ok: false, error }；錯誤碼見文件）",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "unauthorized",
                            "forbidden",
                            "module_disabled",
                            "not_found",
                            "conflict",
                            "invariant",
                            "validation",
                            "internal"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "issues": {
                          "type": "array",
                          "items": {},
                          "description": "422 validation 才有"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-permission": "trip.manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "filename": {
                    "type": "string",
                    "description": "上傳檔名，副檔名須為 .xlsx 或 .csv（min 1）"
                  },
                  "contentBase64": {
                    "type": "string",
                    "description": "檔案內容的 base64 編碼字串（上限 5 MB）（min 1）"
                  }
                },
                "required": [
                  "filename",
                  "contentBase64"
                ]
              }
            }
          }
        }
      }
    }
  }
}