diff --git a/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/check.jsonl b/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/check.jsonl new file mode 100644 index 00000000..9dd3234a --- /dev/null +++ b/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/check.jsonl @@ -0,0 +1 @@ +{"_example": "Fill with {\"file\": \"\", \"reason\": \"\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."} diff --git a/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/design.md b/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/design.md new file mode 100644 index 00000000..aa94daa5 --- /dev/null +++ b/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/design.md @@ -0,0 +1,47 @@ +# 报销付款批次改进部署:技术设计 + +## 1. Release boundary + +本任务只发布已提交代码,不新增产品行为。目标来源为完成任务后的 `main` HEAD;应用代码核心提交为 `d440011`,部署任务启动记录会在发布前一并提交并推送。部署从 Git archive 的已验证提交构建,不从脏工作区同步。 + +## 2. Controlled deployment path + +```text +clean local main + -> commit/start deployment task + -> push origin/main + -> resolve existing controlled SSH identities without echo + -> deploy-existing aggregate preflight + -> deploy.sh with SYNC_ENV=0 + existing data contract + -> runtime/build/smoke checks + -> forced-command backup contract refresh + -> public read-only verification +``` + +- 部署身份和 refresh 身份必须来自本机既有 SSH 配置,分别通过普通 `true` 与固定 `probe` 行为识别;不把候选值写入任务、日志或聊天。 +- `deploy-existing.sh` 是唯一发布入口。它读取 root-owned systemd unit 中的六项 allowlist 合同,内部调用 `deploy.sh` 并固定 `DEPLOY_DATA_MODE=existing`、`SYNC_ENV=0`。 +- 若无法唯一解析两个身份,停止并向用户请求本机配置指引;不猜测远端地址。 + +## 3. Data and compatibility + +- 无 schema 或 migration 变化;部署脚本仍执行标准迁移状态检查,但预期零新增迁移。 +- 生产 `.env`、PGDATA、附件存储和备份合同原样保留。 +- 旧客户端/服务端兼容由原功能任务验证;本任务不拆分前后端发布。 + +## 4. Verification contract + +- 部署脚本必须确认远端运行 build、公开 `/ready` 和前端短 SHA。 +- 公网额外执行无凭据基础 smoke 和资源文案扫描;专用测试凭据存在时才执行登录态 smoke。 +- 本轮不在生产创建合成报销或回单。关键业务交互继续引用已通过的本地 19 项合成 E2E,公网只证明目标 build 和前端合同已发布。 + +## 5. Failure and rollback + +- 推送、来源、预检失败:尚未发布,修复后重试。 +- 构建或应用 readiness 失败:按部署脚本失败阶段处理,必要时使用同一入口发布上一已知提交。 +- 应用已成功、refresh 失败:不重跑应用发布,只修复并重跑 forced-command refresh。 +- 回滚不更改数据库结构、生产 `.env`、PGDATA 或附件存储。 + +## 6. Security boundary + +- 任务记录只保存提交、PASS/FAIL/SKIP 摘要,不保存 SSH target、用户名、远端绝对路径、真实账号、回单、银行信息或原始响应。 +- 所有公网检查只读;不调用回单在线预览,以免对真实材料产生访问审计或暴露敏感文件。 diff --git a/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/implement.jsonl b/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/implement.jsonl new file mode 100644 index 00000000..9dd3234a --- /dev/null +++ b/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/implement.jsonl @@ -0,0 +1 @@ +{"_example": "Fill with {\"file\": \"\", \"reason\": \"\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."} diff --git a/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/implement.md b/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/implement.md new file mode 100644 index 00000000..093711c2 --- /dev/null +++ b/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/implement.md @@ -0,0 +1,40 @@ +# 报销付款批次改进部署:实施计划 + +## 1. Activation and publication + +- [ ] 用户批准本计划后启动 Trellis task。 +- [ ] 提交任务启动记录,确认工作区干净,将 `main` 推送到 `origin/main`。 +- [ ] 记录明确发布提交并确认无 schema、migration、配置键或部署脚本变化。 + +## 2. Preflight + +- [ ] 运行环境合同、Trellis 治理、敏感信息和 Git 来源检查。 +- [ ] 从本机 SSH 配置无回显解析唯一部署身份与 refresh forced-command 身份。 +- [ ] 运行 `check-existing-deployment.sh`,要求 13/13 聚合合同全部 PASS。 + +## 3. Deployment + +- [ ] 使用 `DEPLOY_SERVER`、`DEPLOY_REFRESH_SERVER` 调用 `deploy-existing.sh`。 +- [ ] 确认 `SYNC_ENV=0`、existing data contract、无生产 `.env` 覆盖、无新增 migration。 +- [ ] 确认应用发布和备份合同 refresh 均通过;若部分成功,按设计中的失败分类停止。 + +## 4. Public read-only verification + +- [ ] 验证公网 `/ready`、运行时 build SHA 和前端短 SHA命中发布提交。 +- [ ] 运行基础公网 smoke、外部依赖/功能开关检查和公开资源扫描。 +- [ ] 仅在专用 `LIVE_SMOKE_*` 凭据已配置时运行登录态 smoke;否则记录明确 SKIP。 +- [ ] 扫描公开前端资源确认本轮关键文案/入口合同已发布,不读取真实回单或银行资料。 + +## 5. Closeout + +- [ ] 将脱敏部署结果写回本任务,不新建平行报告。 +- [ ] 运行 task validate、Trellis 治理、敏感信息和 `git diff --check`。 +- [ ] 使用中文提交结果记录并引用 `reimbursement-payment-batch-deployment`。 +- [ ] 归档任务并仅在全部公网门禁通过后告知用户可以测试。 + +## Rollback points + +- 发布前:任何来源或预检失败均停止,不改变远端。 +- 发布中:应用未健康时使用既有入口回退上一已发布提交。 +- 发布后:仅备份合同 refresh 失败时不重复部署应用,单独恢复合同。 +- 全程不修改生产 `.env`、数据库结构、PGDATA、附件存储或真实业务数据。 diff --git a/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/prd.md b/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/prd.md new file mode 100644 index 00000000..19022464 --- /dev/null +++ b/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/prd.md @@ -0,0 +1,70 @@ +# 报销付款批次改进部署 + +## Goal + +将 `reimbursement-small-team-form-validation` 已完成并本地验证的报销详情、付款批次费用明细和银行回单在线预览改进,安全发布到既有公网 OA,并用只读、脱敏证据确认活动版本和关键页面合同生效。 + +## Background and confirmed facts + +- 功能提交为 `d440011`,任务归档提交为 `3659d38`;当前 `main` 工作区干净,但相对 `origin/main` 领先 2 个提交,部署前必须先发布到上游。 +- 本轮应用改动不包含 Prisma schema、migration、生产环境键或部署脚本变化。 +- 本地已完成 Prisma、Node 语法、前端 typecheck/build、19 项 PC/移动 Playwright、Trellis/文档/敏感信息门禁;后端聚焦测试唯一失败是既有 BIFF8 本机依赖缺口,与本轮代码无关。 +- 既有生产部署使用 `deploy/trialrun/deploy-existing.sh`,固定 `SYNC_ENV=0`,从受控 systemd unit 读取部署合同;不得覆盖生产 `.env` 或从 Docker 标签猜测目录。 +- 当前进程环境未直接注入两个部署 SSH target;执行阶段从本机受控 SSH 配置探测既有部署身份和 forced-command refresh 身份,探测过程不回显目标、账号或路径。 +- 用户已授权本次公网部署,但未授权真实报销、审批、付款、银行、ERP、企业微信或生产配置写入。 + +## Scope + +- 将已验证的 `main` 提交推送到现有上游并通过既有来源校验。 +- 运行既有部署聚合预检,使用 `deploy-existing.sh` 发布到现有公网环境。 +- 验证活动 build、`/ready`、公开前端资源、基础 smoke、外部依赖和功能开关。 +- 记录脱敏部署结果、可解释 SKIP、回滚边界和 Trellis 收尾证据。 + +## Requirements + +### R1 发布来源与预检 + +- 部署候选必须是干净、已提交并包含在 `origin/main` 的明确提交;部署前先推送本任务的启动记录和既有功能提交。 +- 使用既有聚合预检,要求部署身份、六项合同、仓库、环境文件、数据目录、运行实例、build、存储/PGDATA 挂载、备份 build、refresh 身份和 forced-command 全部通过。 +- 环境合同、来源校验或远端聚合预检任一失败即停止,不使用 unpublished override,不绕过备份合同。 + +### R2 受控发布 + +- 仅使用 `deploy-existing.sh` 发布,保持 `SYNC_ENV=0` 和既有数据目录;不执行数据库重置、不修改 migration、不覆盖生产 `.env`。 +- 发布过程中允许既有部署脚本执行构建、容器更新、已提交 migration 检查、运行时 smoke 和备份合同刷新;本轮预期无待执行 migration。 +- 不创建或修改真实报销、付款批次、回单或银行数据,不执行真实付款。 + +### R3 公网只读验收 + +- 公网 `/ready`、运行时 build SHA 和前端公开短 SHA 必须与发布提交一致。 +- 运行既有基础公网 smoke、外部依赖/功能开关检查和前端资源扫描;有专用 `LIVE_SMOKE_*` 凭据时才运行登录态 smoke,缺失时记录为明确 SKIP,不读取或输出真实账号密码。 +- 对本轮功能只做无业务写入的验证:确认公开 bundle 包含新文案/入口合同,服务端路由已随目标 build 发布;不得用真实回单或真实付款数据制造验证样本。 + +### R4 结果与回滚 + +- 记录发布提交、部署合同总结果、`/ready`、公网 smoke、登录态 smoke 是否执行及任何可解释 SKIP。 +- 若应用发布成功但备份合同 refresh 失败,按“已部署但合同刷新失败”处理,不重复发布应用;先恢复合同。 +- 应用或 readiness 失败时,使用既有部署入口回滚到上一个已发布提交,不修改数据库结构或生产环境文件。 + +## Acceptance Criteria + +- [ ] AC1:候选提交已推送到 `origin/main`,工作区干净,来源和部署前聚合体检通过。 +- [ ] AC2:`deploy-existing.sh` 完整通过,生产 `.env` 未同步或覆盖,数据库无新增 migration,未发生真实业务或付款写入。 +- [ ] AC3:公网 `/ready`、运行时 build 与前端短 SHA 均命中本次发布提交。 +- [ ] AC4:基础公网 smoke、部署运行时 smoke、外部依赖/功能开关和前端资源扫描通过;登录态 smoke 按凭据实际状态记录 PASS 或明确 SKIP。 +- [ ] AC5:公开资源可确认差旅事由去重、付款批次费用明细/小计和“下载需说明用途”等新前端合同已发布,不暴露真实回单、账号或存储资料。 +- [ ] AC6:任务记录、Trellis 治理、敏感信息检查和 `git diff --check` 通过;只在全部部署与公网门禁通过后告知用户可以测试。 + +## Out of Scope + +- 修改本轮功能代码、数据库模型、migration、生产环境变量或部署脚本。 +- 真实报销提交、审批、付款批次操作、回单上传/预览、完整银行账号查看或真实付款。 +- 企业微信写入、ERP、银行直连、生产数据库重置或人工修复真实业务数据。 +- 为部署缺口启用 unpublished override、跳过聚合预检或弱化附件权限/审计。 + +## Test Plan + +- Local/preflight:环境合同、任务校验、Trellis 治理、敏感信息、`git diff --check`、Git 来源/上游包含关系和既有部署 13 项聚合合同。 +- Deploy:`deploy-existing.sh` 内置的构建、Compose、migration 状态、运行时 smoke、活动 build、公开 build 和备份合同 refresh。 +- Public:`/ready`、基础无凭据 Playwright/readiness、外部依赖与功能开关检查、前端资源关键文案扫描;登录态 smoke 仅在专用凭据存在时运行。 +- Negative/rollback:来源、预检或 readiness 任一失败即停止;应用已发布但 refresh 失败时不重复部署应用。 diff --git a/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/task.json b/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/task.json new file mode 100644 index 00000000..26012fc6 --- /dev/null +++ b/.trellis/tasks/08-05-reimbursement-payment-batch-deployment/task.json @@ -0,0 +1,30 @@ +{ + "id": "reimbursement-payment-batch-deployment", + "name": "reimbursement-payment-batch-deployment", + "title": "报销付款批次改进部署", + "description": "将已完成并验证的报销、付款批次和银行回单改进发布到既有公网环境,并完成受控只读验收。", + "status": "in_progress", + "dev_type": "deployment", + "scope": "deploy/trialrun、公网只读 smoke、Trellis 部署证据", + "package": null, + "priority": "P2", + "creator": "shunli", + "assignee": "shunli", + "createdAt": "2026-08-05", + "completedAt": null, + "branch": null, + "base_branch": "main", + "worktree_path": null, + "commit": null, + "pr_url": null, + "subtasks": [], + "children": [], + "parent": null, + "relatedFiles": [ + ".trellis/tasks/archive/2026-08/08-04-reimbursement-small-team-form-validation", + "deploy/trialrun/deploy-existing.sh", + ".trellis/spec/hyb-oa/deployment-trialrun.md" + ], + "notes": "", + "meta": {} +} \ No newline at end of file