From 09b955d0ac6ed931e421057f93ceb056f34eb873 Mon Sep 17 00:00:00 2001 From: tangweijie <877588133@qq.com> Date: Tue, 24 Mar 2026 12:04:39 +0800 Subject: [PATCH] docs: finalize 010 bank transfer config --- Makefile | 14 +- .../00_Management/01_Project_Progress.md | 9 + .../design/00_Management/03_Task_Checklist.md | 26 +++ .../02_Detailed_Design/12_REV_Detailed.md | 26 ++- .../03_Interface_Design.md | 39 ++++ .../03_Technical_Design/04_Security_Design.md | 7 + .../05_Deployment_Design.md | 7 + infra/docker/bank-transfer-test/.gitignore | 8 + infra/docker/bank-transfer-test/README.md | 97 ++++++++ infra/docker/bank-transfer-test/compose.yaml | 40 ++++ .../bank-transfer-test/ftp-data/.gitkeep | 0 .../bank-transfer-test/sftp-data/.gitkeep | 0 infra/docker/bank-transfer-test/tmp/.gitkeep | 0 scripts/README.md | 2 + scripts/run-bank-transfer-smoke.sh | 66 ++++++ .../backend-validation.md | 85 +++++++ specs/010-bank-transfer-config/baseline.md | 31 +++ .../checklists/requirements.md | 37 +++ .../bank-transfer-config-contract.md | 100 +++++++++ .../bank-transfer-resolution-contract.md | 91 ++++++++ specs/010-bank-transfer-config/data-model.md | 173 +++++++++++++++ .../docs-validation.md | 22 ++ .../010-bank-transfer-config/final-verdict.md | 32 +++ specs/010-bank-transfer-config/plan.md | 157 +++++++++++++ specs/010-bank-transfer-config/quickstart.md | 139 ++++++++++++ specs/010-bank-transfer-config/research.md | 93 ++++++++ specs/010-bank-transfer-config/spec.md | 187 ++++++++++++++++ specs/010-bank-transfer-config/tasks.md | 210 ++++++++++++++++++ 28 files changed, 1694 insertions(+), 4 deletions(-) create mode 100644 infra/docker/bank-transfer-test/.gitignore create mode 100644 infra/docker/bank-transfer-test/README.md create mode 100644 infra/docker/bank-transfer-test/compose.yaml create mode 100644 infra/docker/bank-transfer-test/ftp-data/.gitkeep create mode 100644 infra/docker/bank-transfer-test/sftp-data/.gitkeep create mode 100644 infra/docker/bank-transfer-test/tmp/.gitkeep create mode 100755 scripts/run-bank-transfer-smoke.sh create mode 100644 specs/010-bank-transfer-config/backend-validation.md create mode 100644 specs/010-bank-transfer-config/baseline.md create mode 100644 specs/010-bank-transfer-config/checklists/requirements.md create mode 100644 specs/010-bank-transfer-config/contracts/bank-transfer-config-contract.md create mode 100644 specs/010-bank-transfer-config/contracts/bank-transfer-resolution-contract.md create mode 100644 specs/010-bank-transfer-config/data-model.md create mode 100644 specs/010-bank-transfer-config/docs-validation.md create mode 100644 specs/010-bank-transfer-config/final-verdict.md create mode 100644 specs/010-bank-transfer-config/plan.md create mode 100644 specs/010-bank-transfer-config/quickstart.md create mode 100644 specs/010-bank-transfer-config/research.md create mode 100644 specs/010-bank-transfer-config/spec.md create mode 100644 specs/010-bank-transfer-config/tasks.md diff --git a/Makefile b/Makefile index c813119..c5af537 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # 福建水务营收系统概要设计文档 Makefile # Version: 1.0 -.PHONY: help init create validate export clean install-deps check-links check-mermaid validate-mermaid count-mermaid check-mermaid-file merge-docs check-ai-governance archive-tag-index ai-audit-diff +.PHONY: help init create validate export clean install-deps check-links check-mermaid validate-mermaid count-mermaid check-mermaid-file merge-docs check-ai-governance archive-tag-index ai-audit-diff smoke-sftp smoke-ftp # 默认目标 help: @@ -23,6 +23,8 @@ help: @echo " check-ai-governance 检查AI文档治理基线" @echo " archive-tag-index 生成 Archive 标签索引" @echo " ai-audit-diff 生成 AI 抽检差异清单" + @echo " smoke-sftp 调用 Java smoke CLI 连接 Docker SFTP 容器" + @echo " smoke-ftp 调用 Java smoke CLI 连接 Docker FTP 容器" @echo " count-mermaid 统计mermaid图表数量" @echo " check-mermaid-file 检测指定文件中的mermaid图表 (使用 FILE=文件名)" @echo " merge-docs 合并所有文档" @@ -48,6 +50,8 @@ help: @echo " make check-ai-governance # 检查AI文档治理基线" @echo " make archive-tag-index # 生成 Archive 标签索引" @echo " make ai-audit-diff # 生成 AI 抽检差异清单" + @echo " make smoke-sftp # 运行 Docker SFTP smoke" + @echo " make smoke-ftp # 运行 Docker FTP smoke" @echo " make check-mermaid-file FILE=新-概要设计说明书.md" @echo " make export-word # 导出Word文档" @echo " make export-pdf # 导出PDF文档" @@ -136,6 +140,14 @@ ai-audit-diff: @echo "生成 AI 抽检差异清单..." @./scripts/ai-weekly-audit-diff.sh +smoke-sftp: + @echo "运行 Docker SFTP smoke..." + @./scripts/run-bank-transfer-smoke.sh sftp + +smoke-ftp: + @echo "运行 Docker FTP smoke..." + @./scripts/run-bank-transfer-smoke.sh ftp + # 检测所有markdown文件中的mermaid图表 check-mermaid: @echo "检测所有markdown文件中的mermaid图表..." diff --git a/docs/design/00_Management/01_Project_Progress.md b/docs/design/00_Management/01_Project_Progress.md index 6739553..17e827a 100644 --- a/docs/design/00_Management/01_Project_Progress.md +++ b/docs/design/00_Management/01_Project_Progress.md @@ -128,6 +128,8 @@ | 2026-03-18 | REV-005 SC-005 日志追溯矩阵补齐 | 1)基于 `InvoiceServiceImpl.java` 梳理发票申请、查询/补偿、结果回写、客户侧查询/下载/推送、作废、红冲等关键动作的统一日志写入点;2)确认上述动作均通过 `recordInvoiceOperatLog` 归一写入,并由 `OperatLogService.createOperatLog` 承接操作人、客户与日志内容上下文;3)在 `specs/002-rev005-invoice-flow/verification.md` 回写“关键动作 ↔ 日志写入点”矩阵,将 SC-005 收敛为“实现态证据已补齐、运行态样本待抽查”。 | 用户继续推进 REV-005,一期验收优先补齐 SC-005 的可引用验证证据,避免日志完整率仍停留在笼统结论。 | 正面影响,REV-005 已具备可直接引用的实现态日志追溯矩阵,申请、查询补偿、回写、客户侧查询/下载/推送、作废、红冲等关键动作均可定位到统一日志写入点;后续主要补充测试环境样本抽查即可收口运行态证据。 | | 2026-03-18 | REV-005 `biz_invoice` DDL 来源核实 | 1)在 `backend/sql`、`docs/design/04_Appendix/Archive/03_Design_Docs/数据库设计.md`、`sql/lhc_数据库设计.md`、`docs/guides/BACKEND_TABLE_MAPPING.md` 范围内交叉检索 `biz_invoice`、作废/红冲新增字段与迁移脚本;2)确认仓库内未找到与当前 `InvoiceDO.java` 对应的 `biz_invoice` 物理 DDL / migration;3)确认 Archive 与 `sql/lhc_数据库设计.md` 中同名 `biz_invoice` 更偏“开票配置表”,不能直接作为 REV-005 发票主记录表的落库依据;4)将该结论回写到 REV-005 验证与管理台账。 | 用户继续要求沿 REV-005 把 US4 剩余风险查清,不停留在“表结构待补”泛化表述。 | 正面影响,REV-005 当前已明确“接口/DO/文档承接口径已完成,但物理落库证据仍未在仓库内闭环”;后续若推进提测或联调,可直接把 DDL 缺口作为明确风险跟踪,避免误判作废/红冲字段已正式落库。 | | 2026-03-18 | REV-005 验证文档补强实现态证据 | 1)在 `specs/002-rev005-invoice-flow/verification.md` 为 `SC-001 ~ SC-004` 补充基于 `InvoiceController.java`、`InvoiceServiceImpl.java` 与各请求 VO 的实现态证据,明确申请入口、必填字段、同步处理边界、回写联动、客户侧消费约束与幂等/拦截规则;2)在 `SC-005` 与 `T055` 模板补记 `biz_invoice` 物理 DDL / migration 持续跟踪结论,避免日志抽样与物理落库风险脱节;3)保持 `T055`、`T060 ~ T063` 仍为“待真实联调样本回填”,不虚构量化结果。 | 用户要求直接继续 REV-005,并在未取得真实联调样本前,先把可防御的实现态证据落入正式验证文档。 | 正面影响,REV-005 当前验证记录已从“只有模板和待补口径”提升为“模板 + 代码证据 + 明确缺口”并存;后续联调回填时可直接引用实现态依据解释统计口径、拦截分类与日志追溯边界。 | +| 2026-03-23 | SYS-009 银行代扣六条银行入口实现态闭环回写 | 1)复核 `water-backend/sw-business-bank` 中 `BankWithholdingController.java`、`BankWithholdingServiceImpl.java`、`TransactionMapper.java` 与相关 DTO/DO/Mapper,确认 `customerCheck`、`sendDisc`、`sendDiscCheck`、`cancelDisc`、`backDisc`、`backDiscCheck` 六条银行入口均已补齐 controller/service 实现;2)同步更新 `specs/007-sys009-design-align/final-verdict.md` 与 `contracts/sys009-status-verdicts.md`,将 `BankWithholding` 从“签约/解约已实现、其余部分实现”修正为“六条银行入口已形成最小实现态闭环”;3)保留运行态风险说明,明确真实银行回盘文件解析、SFTP/文件通道联调与样本补证仍待后续验证。 | 用户要求继续完成 `BankWithholding` 六条银行入口,不留 TODO/null,并在实现后回写正式 verdict。 | 正面影响,`SYS-009` 正式结论与 backend 当前代码证据重新对齐,后续评审可区分“实现态已闭环”与“运行态联调证据待补”,避免继续将已完成入口误判为仅部分实现。 | +| 2026-03-20 | SYS-009 设计整合与实现边界收敛 | 1)基于 `specs/007-sys009-design-align/` 的规格、计划、研究与契约,将 `/Users/tangweijie/github/water-bank-api-doc` 中 `SYS-009` 银行侧设计回写到 `12_REV_Detailed.md`、`03_Interface_Design.md`、`01_Database_Design.md`、`03_Summary_Design.md`;2)将 `PayCeb`、`BankWithholding`、`BankCollection` 与 `bk_*` 表族的当前成熟度统一收敛为“已实现 / 部分实现 / 文档先行”三类口径,避免继续把送盘、回盘、对账、结算写成已闭环能力;3)完成四份主文档单文件校验并通过。 | 用户要求把外部 `SYS-009` 设计整合进正式文档,并与当前 backend 实现现状对齐,形成可评审口径。 | 正面影响,仓内正式主文档已成为 `SYS-009` 的单一评审入口;银行实时收费、签解约、批次/回盘/对账/结算的设计边界与实现成熟度不再混写,后续开发与验收可直接引用统一口径。 | | 2026-03-17 | REV-005 作废与红冲二期最小入口落地(US4) | 1)更新 `spec.md`、`plan.md`、`tasks.md`,将 US4 从“边界预留”升级为当前二期实现范围;2)更新 `12_REV_Detailed.md`、`03_Interface_Design.md`,明确后台作废/红冲入口、状态边界与客户侧消费约束;3)在 `InvoiceController.java`、`InvoiceService.java`、`InvoiceServiceImpl.java` 中将作废/红冲入口升级为专门请求 VO,并补齐原因/备注、原发票代码/号码校验与日志留痕;4)扩展 `InvoiceDO.java` 承接作废原因/备注、红冲原因/备注、原发票代码/号码与触发来源字段,并在 service 中回写最小上下文;5)更新 `01_Database_Design.md` 中 REV-005 发票承接口径,补充作废/红冲原因、备注、原票关联与查询补偿上下文;6)执行 `make validate-file FILE=docs/design/03_Technical_Design/01_Database_Design.md` 与 `mvn -f backend/sw-business/sw-business-server/pom.xml -DskipTests compile` 并通过。 | 用户持续要求“继续推进 REV-005”,在一期闭环收口后继续落地 US4 二期最小能力入口,避免作废/红冲长期停留在文档预留状态。 | 正面影响,REV-005 已从“一期正常开票闭环”进一步扩展到“二期作废/红冲最小入口可评审、可编译验证”的状态;当前已补齐专门 VO 接线、原票引用校验、DO 字段承接与数据库承接口径,后续主要剩余 Mapper/表结构层面的正式持久化落地。 || 2026-03-17 | REV-005 结果回写与客户侧电子发票消费闭环(US3) | 1)更新 `12_REV_Detailed.md`、`01_Database_Design.md`、`03_Interface_Design.md`,补齐结果回写、账单关联、客户侧查询/下载/推送电子发票规则;2)扩展 `InvoiceController.java`、`InvoiceServiceImpl.java`、`InvoiceMapper.java` 与相关 VO/DO,落地客户归属校验、`SUCCESS + fileUrl` 消费前置校验、账单开票状态联动、推送状态回写;3)执行 `make validate-file FILE=docs/design/03_Technical_Design/01_Database_Design.md`、`make validate-file FILE=docs/design/03_Technical_Design/03_Interface_Design.md` 及 `mvn -f backend/sw-business/sw-business-server/pom.xml -DskipTests compile` 验证通过。 | 用户要求沿 `/speckit.implement` 持续推进 REV-005 US3,不中断实现链路,直接完成结果回写、账单关联与客户侧电子票消费闭环。 | 正面影响,REV-005 已形成“回写落账 + 账单状态联动 + 客户侧查询/下载/推送 + 最小编译验证”闭环,后续可继续衔接作废、红冲与更多电子发票渠道扩展。 | | 2026-03-16 | REV-005 后台发票申请与校验闭环(US1) | 1)在 `backend/sw-business/sw-business-server/src/main/java/cn/com/emsoft/sw/business/controller/admin/invoice/InvoiceController.java` 增加后台发票申请入口;2)在 `service/invoice/InvoiceServiceImpl.java` 实现客户、客户开票信息、账单与税率校验,确保仅已收费未开票账单允许申请;3)补齐 `applicationNo` 或 `custId + chargeIds` 幂等控制、申请单号生成与申请记录落库;4)执行 `mvn -f backend/sw-business/pom.xml -pl sw-business-server -am -DskipTests compile` 最小编译验证并通过。 | 用户要求继续推进 REV-005 implement,优先完成后台发票申请、开票校验与 US1 收尾,不中断当前实现链路。 | 正面影响,REV-005 已形成“后台申请入口 + 关键校验 + 幂等受理 + 最小编译验证”闭环,后续可在此基础上继续推进 SYS-008 调用、开票结果回写、账单状态联动与电子发票推送下载能力。 | | 2026-03-12 | OMX 任务路由样例落地 | 1)新增 `docs/design/00_Management/17_OMX_Task_Routing_Examples.md`,给出 `REV-004`、`REV-003` 与正式文档修订三类任务的 leader / explorer / executor / verifier 分工模板;2)补充各 lane 的提示词模板、推荐执行顺序与不建议的并行方式;3)更新 `00_Management/README.md` 收录该文档入口。 | 用户希望在治理层之外,再拿到针对当前项目可以直接复用的多 Agent 分工模板,而不是只看抽象原则。 | 正面影响,OMX 从“有规则”变成“可直接照着分工执行”;后续在 `REV-004`、`REV-003` 等闭环中可直接套用 lane 拆分,减少 leader 临时编排成本。 | @@ -341,3 +343,10 @@ - 完成 `REV-006` 当前轮次治理文档二次对齐:在 `15_SYS002_Requirement_Breakdown.md` 明确 `SYS002-REQ-011` 继续维持“未见实现”判断,并补记 `specs/006-reminder-event-design/` 工件基线与后续研发切入建议。 - 同步回写 `03_Task_Checklist.md` 与本进度文档,补充本轮 implement 阶段的治理动作、验证动作与台账一致性说明,避免将文档收口误写为 backend 已实现。 + +### 2026-03-24 更新 + +- 完成 `010-bank-transfer-config` implement 阶段收口,统一 `12_REV_Detailed.md`、`03_Interface_Design.md`、`04_Security_Design.md`、`05_Deployment_Design.md` 与 `specs/010-bank-transfer-config/` 工件口径。 +- `sw-business-bank` 已新增 `FILE_TRANSFER_CONFIG` 配置类型、统一文件传输解析器、`SFTP/FTP` 双协议解析能力,以及 `send/back/reconcile` 审计字段承接;已落库批次回盘目录继续沿用批次固化结果。 +- 已完成 backend 最小验证:`mvn -f ../water-backend/sw-business-bank/pom.xml -pl sw-business-bank-server -am -DskipTests compile` 通过;`mvn ... -Dtest=BankTransferPathResolverTest,BankWithholdingTransferConfigTest -Dsurefire.failIfNoSpecifiedTests=false test` 通过,共 9 个定向测试全部通过。 +- 当前剩余 deferred 继续限定为真实银行 `SFTP/FTP` 联调、生产凭据与白名单开通、`BankCollection` 托收链路对等改造,以及运行态样本补证,不将其误写为已闭环能力。 diff --git a/docs/design/00_Management/03_Task_Checklist.md b/docs/design/00_Management/03_Task_Checklist.md index 1d3fc37..655d609 100644 --- a/docs/design/00_Management/03_Task_Checklist.md +++ b/docs/design/00_Management/03_Task_Checklist.md @@ -138,6 +138,32 @@ ## ✅ 最新完成任务 (持续更新) +### 📋 010-bank-transfer-config 银行文件传输配置能力 + +- [x] **完成 `010-bank-transfer-config` 文档与 backend 闭环实现** ✅ (2026-03-24) + - [x] 已更新 `12_REV_Detailed.md`、`03_Interface_Design.md`、`04_Security_Design.md`、`05_Deployment_Design.md`,明确 `REV-008` 文件传输配置边界、解析优先级、安全约束与部署职责 ✅ + - [x] 已补齐 `specs/010-bank-transfer-config/` 的 `data-model.md`、合同、quickstart、baseline、validation、final-verdict` 等工件,形成单一规格闭环 ✅ + - [x] `sw-business-bank` 已新增 `FILE_TRANSFER_CONFIG`、统一路径解析器、send/back/reconcile 审计字段承接与 2 组定向测试类 ✅ + - [x] 已完成 `mvn -f ../water-backend/sw-business-bank/pom.xml -pl sw-business-bank-server -am -DskipTests compile` 与 `mvn ... -Dtest=BankTransferPathResolverTest,BankWithholdingTransferConfigTest -Dsurefire.failIfNoSpecifiedTests=false test` 最小验证 ✅ + +### 📋 SYS-009 银行代扣闭环实现态回写 + +- [x] **完成 SYS-009 `BankWithholding` 六条银行入口实现态闭环回写** ✅ (2026-03-23) + - [x] 已复核 `BankWithholdingController.java` 与 `BankWithholdingServiceImpl.java`,确认 `customerCheck`、`sendDisc`、`sendDiscCheck`、`cancelDisc`、`backDisc`、`backDiscCheck` 不再保留 TODO/null 路径 ✅ + - [x] 已复核 `TransactionMapper.java`,确认代扣交易审计语义统一使用 `WITHHOLDING` ✅ + - [x] 已更新 `specs/007-sys009-design-align/final-verdict.md` 与 `contracts/sys009-status-verdicts.md`,同步六条银行入口 verdict 为“已实现” ✅ + - [x] 已记录最小验证结论:`mvn ... -DskipTests compile` 与 `mvn ... test` 均通过(当前模块输出 `No tests to run`)✅ + - [x] 已保留剩余风险说明:真实银行回盘文件解析、SFTP/文件通道联调与运行态样本仍待后续补证 ✅ + +### 📋 SYS-009 设计整合与实现对齐 + +- [x] **完成 SYS-009 正式设计整合与实现边界收敛** ✅ (2026-03-20) + - [x] 已更新 `12_REV_Detailed.md`,补充 `REV-003`、`REV-008` 的实现边界与成熟度说明 ✅ + - [x] 已更新 `03_Interface_Design.md`,补充签约、解约、状态查询、取消送盘、回盘状态与当前状态约束 ✅ + - [x] 已更新 `01_Database_Design.md`,明确 `bk_*` 表族对象齐备但业务编排未闭环的边界 ✅ + - [x] 已更新 `03_Summary_Design.md`,将 `SYS-009` 收敛为“已落地能力 + 后续完善项”口径 ✅ + - [x] 已完成四份主文档 `make validate-file` 单文件校验并通过 ✅ + ### 📋 OMX 任务路由样例 - [x] **完成 OMX 任务路由样例落地** ✅ (2026-03-12) diff --git a/docs/design/02_Detailed_Design/12_REV_Detailed.md b/docs/design/02_Detailed_Design/12_REV_Detailed.md index 75da96c..0b120f2 100644 --- a/docs/design/02_Detailed_Design/12_REV_Detailed.md +++ b/docs/design/02_Detailed_Design/12_REV_Detailed.md @@ -246,6 +246,7 @@ flowchart TD 2. 收费记录必须保留渠道、流水号、网点、操作员、终端信息。 3. 线上支付必须以回调或查询确认结果为准,不得以发起状态直接记账。 4. 支付能力由 `SYS-009` 提供,SYS-002 负责账单核销与业务状态回写。 +5. 当前实现侧已确认 `PayCeb` 的欠费查询、缴费处理基础闭环可用,但代理收费对账仍为预留能力;正式文档不得将实时收费对账写成已闭环能力。 ### 核心数据 @@ -623,6 +624,11 @@ flowchart TD 2. 实时收费场景由渠道交易流水驱动账单核销,批量代扣场景由签约关系与批次处理驱动。 3. 对账结果区分一致、长款、短款、失败待处理等状态,支持差异追踪与人工补偿。 4. 国密报文、批量文件、标准 API 等技术细节由 `SYS-009` 承载,SYS-002 保留业务规则与状态协同。 +5. 当前 backend 已确认 `BankWithholding` 六条银行入口(客户状态查询、送盘、送盘状态查询、取消送盘、回盘、回盘状态查询)已形成最小实现态闭环;`BankCollection` 平行链路、对账与结算协同仍以“部分实现或文档先行”表述,不得统一写成已闭环能力。 +6. 银行代扣文件传输配置按“默认规则 + 银行通道覆盖 + 租户覆盖 + 租户-银行通道覆盖”建模,命中优先级固定为 `TENANT_CHANNEL > TENANT > CHANNEL > DEFAULT`。 +7. 目录字段至少区分 `send/back/reconcile/archive/localTemp` 五类阶段;上层覆盖未完整定义时按字段级回退,不允许生成空路径。 +8. 路径模板仅允许 `{tenantId}`、`{companyId}`、`{channelCode}`、`{yyyyMMdd}`、`{yyyyMM}`、`{batchNo}`、`{fileName}` 七个固定变量;命中未声明变量或缺少变量取值时立即阻断文件动作。 +9. `BankWithholding` 在送盘创建时固化 `sendProtocol/sendDir/sendFilePath` 与 `backProtocol/backDir`,配置切换仅影响新发起文件动作,已落库批次继续沿用原解析结果。 ### 核心数据 @@ -636,6 +642,12 @@ flowchart TD - `bk_transaction`、`bk_transaction_callback`、`bk_transaction_exception`:交易、回调、异常。 - `biz_collection`、`biz_withholding`:代收/代扣业务主对象。 +#### 文件传输配置与审计补充 + +- 环境默认规则通过 Spring profile + Nacos 承接,不在仓库样例中写入真实密码、私钥或证书。 +- `bk_channel_api_config` 使用专用 `apiType=FILE_TRANSFER_CONFIG` 承接文件传输覆盖配置,`extParams` 记录作用域、业务类型、协议、连接引用和五类目录字段。 +- `bk_withholding_batch` 固化送盘/回盘目录与协议,`bk_reconcile_batch` 固化对账阶段最终 `protocol/dir/filePath/fileName`,用于审计与问题回放。 + ### 迁移补充(旧系统承接) #### 银行托收 @@ -650,16 +662,24 @@ flowchart TD - 当前建议以 `bk_transaction*` 作为主承接对象,并补充按结算日期、银行/渠道、收费结果、差异状态查询和导出能力说明。 - 对旧“实时收费汇总/日志/明细”对象,P0 阶段先按历史只读查询口径保留,不误写为当前已落地的独立主模型。 +#### 当前实现对齐说明 + +- `PayCeb` 路径已具备欠费查询、缴费处理、流水唯一性校验和交易日志留痕,可作为实时收费基础闭环的实现证据。 +- `BankWithholding` 路径已具备签约、解约、客户状态查询、送盘、送盘状态查询、取消送盘、回盘、回盘状态查询及对应交易留痕的实现证据,可作为代扣最小实现态闭环依据。 +- `BankCollection` 路径当前仍仅能确认签约、解约与协议/交易日志处理具备实现证据。 +- 对账、结算、真实银行文件解析、SFTP/文件通道联调和运行态样本补证当前仍未闭环,正式文档应继续保留为后续完善项。 + ### 接口映射 - `IF-REV-011`:代扣批次、对账与结算协同入口。 - `IF-EXT-001`:银行代扣批次下发与回盘协同。 +- `IF-EXT-003`:银行实时收费查询、缴费与结果确认协同。 ### 落地边界 -- **已落地**:渠道、路由、交易、回调、异常、签约、批次、对账、结算等主链路对象。 -- **部分落地**:部分统计类、汇总类对象可能在渠道报表或外部结算文件层体现。 -- **文档先行**:不将未明确扫描到的扩展银行台账写成已实现独立表。 +- **已落地**:渠道、路由、交易、回调、异常、代扣/托收签约、解约,以及 `BankWithholding` 的客户状态查询、送盘、送盘状态查询、取消送盘、回盘、回盘状态查询和对应日志留痕等主对象已具备明确实现证据。 +- **部分落地**:`BankCollection` 批次、明细、送盘、回盘、状态查询、差异台账和后台资源管理入口已具备对象或骨架,但不等同于银行协同闭环全部完成;`BankWithholding` 的真实文件解析、异常补偿和运行态联调证据仍待补齐。 +- **文档先行**:夜间批量代扣调度、完整对账处理、结算确认、扩展银行台账等内容不得在当前阶段写成已完成能力。 diff --git a/docs/design/03_Technical_Design/03_Interface_Design.md b/docs/design/03_Technical_Design/03_Interface_Design.md index 93d723f..45d9790 100644 --- a/docs/design/03_Technical_Design/03_Interface_Design.md +++ b/docs/design/03_Technical_Design/03_Interface_Design.md @@ -150,6 +150,13 @@ retrieval_priority: P0 关键报文信息包括:客户号、签约号、扣款金额、账期、渠道编码、批次号等。 +边界约束: +- 当前正式设计包含代扣送盘、回盘与对账的目标边界;其中 `BankWithholding` 已具备送盘、送盘状态查询、取消送盘等六条银行入口的最小实现态闭环证据。 +- 正式文档可将 `BankWithholding` 六条银行入口写为“已实现”,但需同时注明真实银行文件解析、SFTP/文件通道联调与运行态样本仍待补证。 +- 涉及批量文件交互时,正式口径保留 `HTTP/REST/SFTP` 与文件命名、批次号约束,不下沉到特定银行私有报文字段。 +- 运行时文件传输配置统一由解析器输出 `protocol/resolvedDir/resolvedPath/fileName/sourceScope`;优先级固定为 `TENANT_CHANNEL > TENANT > CHANNEL > DEFAULT`,高优先级仅覆盖部分字段时按字段级回退。 +- 命中协议缺少 `host/port/username/credentialRef`、阶段目录为空或模板变量非法时,接口必须立即返回配置错误,不得回退到错误租户或错误通道。 + ### IF-EXT-002 银行代扣回盘接收接口 | 项目 | 说明 | @@ -162,6 +169,10 @@ retrieval_priority: P0 | 业务说明 | 接收代扣成功、失败、退票等结果并回写业务状态 | | 核心数据支撑 | `bk_withholding_batch`、`bk_withholding_item`、`bk_transaction`、`bk_transaction_exception` | +边界约束: +- 回盘处理、回盘状态查询、差异核对和结算确认属于同一能力簇;其中 `BankWithholding` 的回盘与回盘状态查询已具备最小实现态闭环证据,但完整差异核对、异常补偿和结算确认仍属后续完善项。 +- 当前正式文档允许保留回盘文件名、批次号、回盘日期、结果状态等正式字段约束,但不得把未落地的真实文件解析、异常补偿和结算闭环写成既成事实。 + ### IF-EXT-003 银行实时收费接口 | 项目 | 说明 | @@ -174,6 +185,25 @@ retrieval_priority: P0 | 业务说明 | 支撑柜台、网银、手机银行实时查询应收并完成缴费 | | 核心数据支撑 | `biz_charge`、`biz_charge_detail`、`bk_transaction`、`bk_transaction_callback` | +边界约束: +- 当前 backend 已确认欠费查询与缴费处理具备实现证据,可作为正式文档中的已落地基础能力。 +- 代理收费对账、汇总对账和当日未对账红冲等扩展能力当前仍未形成完整实现闭环,正式文档须标注为后续完善项。 + +### 银行签约、状态查询与批次控制扩展接口 + +| 接口动作 | 推荐归属 | 当前代码路径 | 当前状态 | 正式口径 | +|---------|----------|-------------|----------|----------| +| 代扣签约 | REV-008 / SYS-009 | `BankWithholdingController#signing` | 已实现 | 可作为正式接口能力写入 | +| 代扣解约 | REV-008 / SYS-009 | `BankWithholdingController#termination` | 已实现 | 可作为正式接口能力写入 | +| 托收签约 | REV-008 / SYS-009 | `BankCollectionController#signing` | 已实现 | 可作为正式接口能力写入 | +| 托收解约 | REV-008 / SYS-009 | `BankCollectionController#termination` | 已实现 | 可作为正式接口能力写入 | +| 客户状态查询 | REV-008 / SYS-009 | `BankWithholdingController#customerCheck` / `BankCollectionController#customerCheck` | 代扣已实现;托收部分实现 | 代扣可作为正式接口能力写入;托收仅保留正式契约边界与结果状态 | +| 送盘 | REV-008 / SYS-009 | `BankWithholdingController#sendDisc` / `BankCollectionController#sendDisc` | 代扣已实现;托收部分实现 | 代扣可作为正式接口能力写入;托收仅保留正式契约边界与批次发送语义 | +| 送盘状态查询 | REV-008 / SYS-009 | `BankWithholdingController#sendDiscCheck` / `BankCollectionController#sendDiscCheck` | 代扣已实现;托收部分实现 | 代扣可作为正式接口能力写入;托收仅保留正式契约边界与批次状态语义 | +| 取消送盘 | REV-008 / SYS-009 | `BankWithholdingController#cancelDisc` / `BankCollectionController#cancelDisc` | 代扣已实现;托收部分实现 | 代扣可作为正式接口能力写入;托收仅保留正式契约边界与可取消条件 | +| 回盘 | REV-008 / SYS-009 | `BankWithholdingController#backDisc` / `BankCollectionController#backDisc` | 代扣已实现;托收部分实现 | 代扣可作为正式接口能力写入;托收仅保留正式契约边界与回盘处理语义 | +| 回盘状态查询 | REV-008 / SYS-009 | `BankWithholdingController#backDiscCheck` / `BankCollectionController#backDiscCheck` | 代扣已实现;托收部分实现 | 代扣可作为正式接口能力写入;托收仅保留正式契约边界与回盘状态语义 | + ### IF-EXT-004 聚合支付下单接口 | 项目 | 说明 | @@ -494,6 +524,10 @@ retrieval_priority: P0 | 功能描述 | 创建代扣批次、发起对账、接收结算回写 | | 核心表 | `biz_withholding`、`bk_withholding_batch`、`bk_reconcile_batch`、`bk_settlement_batch` | +边界约束: +- `IF-REV-011` 在当前阶段主要承接正式业务协同边界,不等同于送盘、回盘、对账、结算全部已闭环。 +- 已确认的后台管理入口可证明批次、差异、结算台账对象存在,但不能替代银行 app 协同接口的完成度判断。 + ### IF-REV-012 业务参数配置接口 | 项目 | 说明 | @@ -1466,6 +1500,7 @@ sequenceDiagram BatchJob->>SYS002: 发起代扣批次处理(IF-REV-011) SYS002->>SYS002: 汇总代扣客户、账单与协议关系 SYS002->>SYS002: 生成bk_withholding_batch/bk_withholding_item + SYS002->>SYS002: 解析 send/back/reconcile 目录并固化协议、目录、文件路径 SYS002->>SYS009: 下发银行代扣批次(IF-EXT-001) SYS009->>Bank: 发送代扣文件或报文 Bank-->>SYS009: 返回受理结果 @@ -1564,12 +1599,16 @@ sequenceDiagram | 批次下发 | `batchNo` | `batchNo` | 代扣批次号 | `bk_withholding_batch.batch_no` | | 批次下发 | `businessType` | `businessType` | 代扣/对账/结算类型 | 协同参数 | | 批次下发 | `channelCode` | `channelCode` | 渠道编码 | `bk_payment_channel.channel_code` | +| 批次下发 | `protocol` | `protocol` | `SFTP/FTP` 传输协议 | 统一解析结果 | +| 批次下发 | `sendDir` / `sendFilePath` | `sendDir` / `sendFilePath` | 送盘目录与文件路径 | `bk_withholding_batch` | | 批次下发 | `billPeriod` | `billPeriod` | 账期 | 批处理参数 | | 批次明细 | `itemList[].custId` | `itemList[].customerId` | 客户标识 | `bk_withholding_item.cust_id` | | 批次明细 | `itemList[].chargeId` | `itemList[].sourceBillId` | 账单标识 | `bk_withholding_item.charge_id` | | 批次明细 | `itemList[].amount` | `itemList[].withholdingAmount` | 代扣金额 | 业务金额 | | 回盘回写 | `batchStatus` | `batchStatus` | 批次状态:已发送、已回盘等 | `bk_withholding_batch.status` | +| 回盘回写 | `backProtocol` / `backDir` / `backFilePath` | `backProtocol` / `backDir` / `backFilePath` | 回盘阶段最终解析结果 | `bk_withholding_batch` | | 回盘回写 | `successCount` / `failCount` | `successCount` / `failCount` | 成功失败数量汇总 | 汇总结果 | +| 对账回写 | `protocol` / `dir` / `filePath` | `protocol` / `dir` / `filePath` | 对账文件最终解析结果 | `bk_reconcile_batch` | | 对账回写 | `reconcileStatus` | `reconcileStatus` | 对账状态 | `bk_reconcile_batch.status` | | 对账回写 | `diffList[]` | `diffList[]` | 差异明细摘要 | `bk_reconcile_diff` | | 结算回写 | `settlementStatus` | `settlementStatus` | 结算状态 | `bk_settlement_batch.status` | diff --git a/docs/design/03_Technical_Design/04_Security_Design.md b/docs/design/03_Technical_Design/04_Security_Design.md index a717154..acb9eb1 100644 --- a/docs/design/03_Technical_Design/04_Security_Design.md +++ b/docs/design/03_Technical_Design/04_Security_Design.md @@ -228,6 +228,13 @@ graph TB - 使用PKCS12格式的数字证书 - 支持TLSv1.2和TLSv1.3协议版本 +#### 银行文件传输安全约束 +- 银行文件交换默认优先使用 `SFTP`;`FTP` 仅作为兼容能力保留,需在风险评估通过后启用。 +- 文件传输凭据以 `credentialRef` 引用形式由环境配置或配置中心承接,不在正式文档、默认仓库配置样例或测试样本中写入明文密码、私钥、证书。 +- 命中协议缺少 `host/port/username/credentialRef` 时必须立即阻断当前文件动作,避免以残缺配置尝试连接银行通道。 +- 路径模板仅允许固定变量白名单,禁止自由表达式、脚本化拼装和未声明变量,防止目录逃逸与错误路由。 +- 批次审计只保存最终实际使用的协议、目录、文件路径与文件名,不额外保存完整凭据快照,避免敏感配置在业务表中扩散。 + #### 敏感数据加密 - 采用国密SM4对称加密算法 - 实现统一的数据加密和解密服务 diff --git a/docs/design/03_Technical_Design/05_Deployment_Design.md b/docs/design/03_Technical_Design/05_Deployment_Design.md index 733ff4b..d9e49fc 100644 --- a/docs/design/03_Technical_Design/05_Deployment_Design.md +++ b/docs/design/03_Technical_Design/05_Deployment_Design.md @@ -48,6 +48,11 @@ retrieval_priority: P0 - **安全防护**:多层次安全防护体系,确保系统和数据安全 - **弹性扩展**:支持系统横向和纵向扩展,适应业务增长需求 +### 银行文件传输配置部署约束 +- `sw-business-bank` 继续沿用 `application-{profile}.yaml + Nacos` 加载环境默认文件传输规则,不在代码中硬编码送盘、回盘、对账目录。 +- 环境默认规则承接 `protocol/host/port/username/credentialRef/sendDir/backDir/reconcileDir/archiveDir/localTempDir`;银行通道、租户、租户-通道覆盖通过 `bk_channel_api_config` 的 `FILE_TRANSFER_CONFIG` 记录补充。 +- 配置切换只影响新发起文件动作;已落库批次继续沿用已固化的协议、目录和文件路径审计结果,不要求重算旧批次。 + ## 部署架构 @@ -163,6 +168,7 @@ graph - **任务调度**:Quartz集群模式 - **工作流引擎**:Flowable 6.8.0 - **文件存储**:MinIO 分布式存储 +- **配置中心**:Nacos,承接 profile 对应的银行文件传输默认规则 ## 部署方案 @@ -202,6 +208,7 @@ graph - **数据库容器**:达梦数据库,数据持久化存储 - **缓存容器**:Redis缓存服务,提升系统性能 - **文件存储容器**:MinIO对象存储,管理系统文件 +- **银行文件交换目录**:应用节点需具备本地临时目录与归档目录访问权限;外部银行 `SFTP/FTP` 白名单、账户与凭据由环境运维统一开通 ### 部署流程 diff --git a/infra/docker/bank-transfer-test/.gitignore b/infra/docker/bank-transfer-test/.gitignore new file mode 100644 index 0000000..1561bc4 --- /dev/null +++ b/infra/docker/bank-transfer-test/.gitignore @@ -0,0 +1,8 @@ +ftp-data/** +!ftp-data/.gitkeep + +sftp-data/** +!sftp-data/.gitkeep + +tmp/** +!tmp/.gitkeep diff --git a/infra/docker/bank-transfer-test/README.md b/infra/docker/bank-transfer-test/README.md new file mode 100644 index 0000000..a1649f5 --- /dev/null +++ b/infra/docker/bank-transfer-test/README.md @@ -0,0 +1,97 @@ +# Bank Transfer Test Compose + +用于本地快速拉起一组最小化 SFTP / FTP 测试容器。 + +## 服务 + +- `sftp` + - 镜像:`atmoz/sftp` + - 用户:`demo` + - 密码:`demo123` + - 目录:`/home/demo/upload` + - 主机端口:`2222` +- `ftp` + - 镜像:`fauria/vsftpd` + - 用户:`demo` + - 密码:`demo123` + - 目录:`/home/vsftpd/demo` + - 主机端口:`2121` +- `tester` + - 镜像:`alpine:3.20` + - 内置 `openssh-client` 与 `lftp` + +## 启动 + +```bash +docker compose -f infra/docker/bank-transfer-test/compose.yaml up -d +``` + +## Java Smoke + +### SFTP + +先编译 `sw-business-bank-server`: + +```bash +mvn -f ../water-backend/sw-business-bank/pom.xml -pl sw-business-bank-server -am -DskipTests compile +``` + +执行 SFTP smoke CLI: + +```bash +mvn -f ../water-backend/sw-business-bank/sw-business-bank-server/pom.xml \ + -DincludeScope=runtime dependency:build-classpath \ + -Dmdep.outputFile=/tmp/sw-business-bank-server.cp + +java -cp "$(cat /tmp/sw-business-bank-server.cp):../water-backend/sw-business-bank/sw-business-bank-server/target/classes" \ + cn.com.emsoft.sw.bankbusiness.tools.BankTransferSftpSmokeCli \ + --local-file infra/docker/bank-transfer-test/tmp/sample.txt \ + --host 127.0.0.1 \ + --port 2222 \ + --username demo \ + --password demo123 \ + --send-dir /upload/{companyId} \ + --company-id C001 \ + --channel-code 00001 \ + --batch-no SMOKE010 \ + --business-date 2026-03-24 \ + --remote-file-name smoke-cli-sample.txt \ + --download-target infra/docker/bank-transfer-test/tmp/sftp-smoke-download-smoke-cli-sample.txt +``` + +### FTP + +执行 FTP smoke CLI: + +```bash +java -cp "$(cat /tmp/sw-business-bank-server.cp):../water-backend/sw-business-bank/sw-business-bank-server/target/classes" \ + cn.com.emsoft.sw.bankbusiness.tools.BankTransferFtpSmokeCli \ + --local-file infra/docker/bank-transfer-test/tmp/sample.txt \ + --host 127.0.0.1 \ + --port 2121 \ + --username demo \ + --password demo123 \ + --send-dir {companyId} \ + --company-id C001 \ + --channel-code 00001 \ + --batch-no SMOKE010FTP \ + --business-date 2026-03-24 \ + --remote-file-name smoke-cli-ftp-sample.txt \ + --download-target infra/docker/bank-transfer-test/tmp/ftp-smoke-download-smoke-cli-ftp-sample.txt +``` + +### 当前已验证结果 + +- SFTP:通过 +- FTP:通过 +- 样本文件 SHA256: + +```text +2520ee11a48cb01c9372c91a012549a50a39de40441a4295309993727239653b +``` + +## 停止 + +```bash +docker compose -f infra/docker/bank-transfer-test/compose.yaml down +``` diff --git a/infra/docker/bank-transfer-test/compose.yaml b/infra/docker/bank-transfer-test/compose.yaml new file mode 100644 index 0000000..0d7d59d --- /dev/null +++ b/infra/docker/bank-transfer-test/compose.yaml @@ -0,0 +1,40 @@ +services: + sftp: + image: atmoz/sftp:latest + container_name: bank-transfer-test-sftp + command: demo:demo123:::upload + ports: + - "2222:22" + volumes: + - ./sftp-data:/home/demo/upload + networks: + - bank-transfer-net + + ftp: + image: delfer/alpine-ftp-server:latest + container_name: bank-transfer-test-ftp + environment: + USERS: demo|demo123|/ftp/demo + ADDRESS: ftp + MIN_PORT: 21100 + MAX_PORT: 21110 + ports: + - "2121:21" + - "21100-21110:21100-21110" + volumes: + - ./ftp-data:/ftp/demo + networks: + - bank-transfer-net + + tester: + image: alpine:3.20 + container_name: bank-transfer-test-client + command: sh -c "apk add --no-cache openssh-client lftp && tail -f /dev/null" + volumes: + - ./tmp:/work + networks: + - bank-transfer-net + +networks: + bank-transfer-net: + name: bank-transfer-test-net diff --git a/infra/docker/bank-transfer-test/ftp-data/.gitkeep b/infra/docker/bank-transfer-test/ftp-data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/infra/docker/bank-transfer-test/sftp-data/.gitkeep b/infra/docker/bank-transfer-test/sftp-data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/infra/docker/bank-transfer-test/tmp/.gitkeep b/infra/docker/bank-transfer-test/tmp/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/scripts/README.md b/scripts/README.md index 1d164ce..ae8b444 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -11,6 +11,7 @@ - `precommit-validate-markdown.sh`:提交前 Markdown 逐文件校验 - `process-mermaid.sh`:Mermaid 图表处理 - `unified_export.sh`、`quick_unified_export.sh`:统一导出 +- `run-bank-transfer-smoke.sh`:调用 `sw-business-bank` 的 Java smoke CLI,对 Docker `SFTP/FTP` 测试容器执行上传/下载/哈希校验 ## AI 治理脚本 @@ -23,3 +24,4 @@ - 本地快速校验:`make validate-file FILE=<目标文件>` - 跨文档校验:`make check-links`、`make validate-mermaid` - 提交前演练:`pre-commit run --files <变更文件>` +- 文件通道 smoke:`scripts/run-bank-transfer-smoke.sh sftp` 或 `scripts/run-bank-transfer-smoke.sh ftp` diff --git a/scripts/run-bank-transfer-smoke.sh b/scripts/run-bank-transfer-smoke.sh new file mode 100755 index 0000000..3db0e4a --- /dev/null +++ b/scripts/run-bank-transfer-smoke.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash + +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +BACKEND_DIR="${ROOT_DIR}/../water-backend/sw-business-bank" +SERVER_DIR="${BACKEND_DIR}/sw-business-bank-server" +CP_FILE="/tmp/sw-business-bank-server.cp" + +MODE="${1:-}" +if [[ -z "${MODE}" ]]; then + echo "Usage: $0 [sample-file]" + exit 1 +fi + +SAMPLE_FILE="${2:-${ROOT_DIR}/infra/docker/bank-transfer-test/tmp/sample.txt}" + +if [[ ! -f "${SAMPLE_FILE}" ]]; then + echo "Sample file not found: ${SAMPLE_FILE}" + exit 1 +fi + +case "${MODE}" in + sftp) + MAIN_CLASS="cn.com.emsoft.sw.bankbusiness.tools.BankTransferSftpSmokeCli" + PORT="2222" + SEND_DIR="/upload/{companyId}" + REMOTE_FILE="smoke-cli-sample.txt" + DOWNLOAD_TARGET="${ROOT_DIR}/infra/docker/bank-transfer-test/tmp/sftp-smoke-download-smoke-cli-sample.txt" + BATCH_NO="SMOKE010" + ;; + ftp) + MAIN_CLASS="cn.com.emsoft.sw.bankbusiness.tools.BankTransferFtpSmokeCli" + PORT="2121" + SEND_DIR="{companyId}" + REMOTE_FILE="smoke-cli-ftp-sample.txt" + DOWNLOAD_TARGET="${ROOT_DIR}/infra/docker/bank-transfer-test/tmp/ftp-smoke-download-smoke-cli-sample.txt" + BATCH_NO="SMOKE010FTP" + ;; + *) + echo "Unsupported mode: ${MODE}" + echo "Usage: $0 [sample-file]" + exit 1 + ;; +esac + +echo "[1/3] Compile sw-business-bank-server" +mvn -f "${BACKEND_DIR}/pom.xml" -pl sw-business-bank-server -am -DskipTests compile + +echo "[2/3] Build runtime classpath" +mvn -f "${SERVER_DIR}/pom.xml" -DincludeScope=runtime dependency:build-classpath -Dmdep.outputFile="${CP_FILE}" + +echo "[3/3] Run ${MODE^^} smoke" +java -cp "$(cat "${CP_FILE}"):${SERVER_DIR}/target/classes" "${MAIN_CLASS}" \ + --local-file "${SAMPLE_FILE}" \ + --host 127.0.0.1 \ + --port "${PORT}" \ + --username demo \ + --password demo123 \ + --send-dir "${SEND_DIR}" \ + --company-id C001 \ + --channel-code 00001 \ + --batch-no "${BATCH_NO}" \ + --business-date 2026-03-24 \ + --remote-file-name "${REMOTE_FILE}" \ + --download-target "${DOWNLOAD_TARGET}" diff --git a/specs/010-bank-transfer-config/backend-validation.md b/specs/010-bank-transfer-config/backend-validation.md new file mode 100644 index 0000000..3f0e760 --- /dev/null +++ b/specs/010-bank-transfer-config/backend-validation.md @@ -0,0 +1,85 @@ +# Backend Validation: sw-business-bank 银行代扣文件传输配置能力 + +## 固定基线 + +- 分支:`develop` +- 提交:`b540f1f48bf2d6c28aa183749ca61231071c0942` +- 验证日期:2026-03-24 + +## 验证命令 + +```bash +mvn -f /Volumes/Dpan/github/water-workspace/water-backend/sw-business-bank/pom.xml -pl sw-business-bank-server -am -DskipTests compile +mvn -f /Volumes/Dpan/github/water-workspace/water-backend/sw-business-bank/pom.xml -pl sw-business-bank-server -am -Dtest=BankTransferPathResolverTest,BankWithholdingTransferConfigTest -Dsurefire.failIfNoSpecifiedTests=false test +``` + +## 结果摘要 + +- 编译:通过 +- 定向测试:通过 +- 测试统计:2 个测试类,9 个测试用例全部通过 +- Docker 文件通道 smoke:通过 + +## 场景证据 + +### 默认规则 + +- `BankTransferPathResolverTest.resolve_usesDefaultRuleWhenNoOverrideMatches` +- 结论:未命中覆盖时,按默认 `SFTP` 与默认目录生成 `resolvedDir/resolvedPath` + +### 租户覆盖 + +- `BankTransferPathResolverTest.resolve_prefersTenantChannelThenTenantThenChannel` +- 结论:存在租户与租户-通道覆盖时,租户相关覆盖能命中并参与最终结果 + +### 通道覆盖 + +- `BankTransferPathResolverTest.resolve_prefersTenantChannelThenTenantThenChannel` +- 结论:通道覆盖在默认规则之上生效,并在存在更具体作用域时被更高优先级覆盖 + +### 租户-通道覆盖 + +- `BankTransferPathResolverTest.resolve_prefersTenantChannelThenTenantThenChannel` +- 结论:`TENANT_CHANNEL` 优先级最高,可同时覆盖协议与目录 + +### 字段级回退 + +- `BankTransferPathResolverTest.resolve_fallsBackFieldByFieldWhenHigherScopeIsPartial` +- 结论:高优先级仅覆盖协议时,目录继续回退到下一级有效规则,不生成空路径 + +### 协议切换 + +- `BankTransferPathResolverTest.resolve_switchesProtocolWithoutChangingCallerLogic` +- 结论:同一路径解析入口可在 `SFTP/FTP` 间切换,无需调用方自行拼路径 + +### `ARCHIVE` / `LOCAL_TEMP` + +- `BankTransferPathResolverTest.resolve_supportsArchiveAndLocalTempStages` +- 结论:归档目录与本地临时目录均纳入统一解析范围 + +### 非法模板变量失败 + +- `BankTransferPathResolverTest.resolve_rejectsUnknownTemplateVariable` +- 结论:命中未声明变量时立即抛出配置错误 + +### 配置缺失失败 + +- `BankTransferPathResolverTest.resolve_rejectsMissingConfig` +- 结论:协议连接信息不完整时立即阻断当前文件动作 + +### 已落库批次配置切换回归 + +- `BankWithholdingTransferConfigTest.resolveStoredOrCurrentBackLocation_reusesPersistedBatchConfigAfterConfigSwitch` +- 结论:已固化 `backProtocol/backDir` 的批次继续沿用原目录,不漂移到新配置 + +- `BankWithholdingTransferConfigTest.resolveStoredOrCurrentBackLocation_usesCurrentResolverWhenBatchHasNoSnapshot` +- 结论:未固化回盘目录的旧对象仍可回退到当前统一解析器 + +## 备注 + +- 已执行基于 Docker 容器的本地文件通道 smoke: + - `BankTransferSftpSmokeCli` -> `bank-transfer-test-sftp (127.0.0.1:2222)` 上传/下载/哈希比对通过 + - `BankTransferFtpSmokeCli` -> `bank-transfer-test-ftp (127.0.0.1:2121)` 上传/下载/哈希比对通过 + - 当前样本 SHA256:`2520ee11a48cb01c9372c91a012549a50a39de40441a4295309993727239653b` +- 本轮仍未执行真实银行 `SFTP/FTP` 网络连通性验证;相关联调继续作为 deferred 保留。 +- H2 测试夹具本轮未新增数据库级用例,`application-unit-test.yaml` 与 `sql/create_tables.sql` 无需为当前两组定向测试额外扩展。 diff --git a/specs/010-bank-transfer-config/baseline.md b/specs/010-bank-transfer-config/baseline.md new file mode 100644 index 0000000..5bda9cb --- /dev/null +++ b/specs/010-bank-transfer-config/baseline.md @@ -0,0 +1,31 @@ +# Baseline: sw-business-bank 银行代扣文件传输配置能力 + +## 固定基线 + +- 记录日期:2026-03-24 +- `water-backend` 分支:`develop` +- `water-backend` 提交:`b540f1f48bf2d6c28aa183749ca61231071c0942` + +## 核心代码落点 + +- `sw-business-bank-api/src/main/java/cn/com/emsoft/sw/bankbusiness/enums/ApiTypeEnum.java` +- `sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/dal/dataobject/channelapiconfig/ChannelApiConfigExtParams.java` +- `sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/service/filetransfer/` +- `sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/service/bankwithholding/BankWithholdingServiceImpl.java` +- `sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/dal/dataobject/withholdingbatch/WithholdingBatchDO.java` +- `sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/dal/dataobject/reconcilebatch/ReconcileBatchDO.java` +- `sw-business-bank-server/src/test/java/cn/com/emsoft/sw/bankbusiness/service/filetransfer/BankTransferPathResolverTest.java` +- `sw-business-bank-server/src/test/java/cn/com/emsoft/sw/bankbusiness/service/bankwithholding/BankWithholdingTransferConfigTest.java` + +## 固定结论 + +- 本轮实现将 `BankWithholdingServiceImpl` 的硬编码送盘、回盘、对账目录切换为统一解析器输出。 +- 默认规则继续由 Spring profile + Nacos 承接;覆盖规则通过 `bk_channel_api_config` 的 `apiType=FILE_TRANSFER_CONFIG` + `extParams` 承接。 +- 已落库批次的回盘目录与协议在送盘创建时固化到批次对象,后续配置切换不回溯修改旧批次。 + +## 正式文档真源 + +- `docs/design/02_Detailed_Design/12_REV_Detailed.md` +- `docs/design/03_Technical_Design/03_Interface_Design.md` +- `docs/design/03_Technical_Design/04_Security_Design.md` +- `docs/design/03_Technical_Design/05_Deployment_Design.md` diff --git a/specs/010-bank-transfer-config/checklists/requirements.md b/specs/010-bank-transfer-config/checklists/requirements.md new file mode 100644 index 0000000..c5c5122 --- /dev/null +++ b/specs/010-bank-transfer-config/checklists/requirements.md @@ -0,0 +1,37 @@ +# Specification Quality Checklist: sw-business-bank 银行代扣文件传输配置能力 + +**Purpose**: Validate specification completeness and quality before proceeding to planning +**Created**: 2026-03-23 +**Feature**: [spec.md](../spec.md) + +## Content Quality + +- [x] No implementation details (languages, frameworks, APIs) +- [x] Focused on user value and business needs +- [x] Written for non-technical stakeholders +- [x] All mandatory sections completed + +## Requirement Completeness + +- [x] No [NEEDS CLARIFICATION] markers remain +- [x] Requirements are testable and unambiguous +- [x] Success criteria are measurable +- [x] Success criteria are technology-agnostic (no implementation details) +- [x] All acceptance scenarios are defined +- [x] Edge cases are identified +- [x] Scope is clearly bounded +- [x] Dependencies and assumptions identified + +## Feature Readiness + +- [x] All functional requirements have clear acceptance criteria +- [x] User scenarios cover primary flows +- [x] Feature meets measurable outcomes defined in Success Criteria +- [x] No implementation details leak into specification + +## Notes + +- Validation completed in a single pass. +- No `[NEEDS CLARIFICATION]` markers were introduced. +- The spec keeps formal-document updates, backend evidence, security/deployment constraints, and ledger updates within explicit scope. +- SFTP/FTP are treated as feature-domain protocol requirements rather than code-level implementation details. diff --git a/specs/010-bank-transfer-config/contracts/bank-transfer-config-contract.md b/specs/010-bank-transfer-config/contracts/bank-transfer-config-contract.md new file mode 100644 index 0000000..bf46423 --- /dev/null +++ b/specs/010-bank-transfer-config/contracts/bank-transfer-config-contract.md @@ -0,0 +1,100 @@ +# Contract: 银行文件传输配置合同 + +## 目标 + +定义本轮 feature 允许承接的文件传输配置结构,作为 backend 实施与文档回写的共同约束。 + +## 作用域模型 + +支持以下四级作用域: + +1. `DEFAULT` +2. `CHANNEL` +3. `TENANT` +4. `TENANT_CHANNEL` + +优先级从高到低为: + +`TENANT_CHANNEL > TENANT > CHANNEL > DEFAULT` + +## 支持协议 + +- `SFTP` +- `FTP` + +说明: +- 正式设计优先推荐 `SFTP` +- `FTP` 仅作为兼容协议表达能力保留 + +## 连接字段最小集合 + +- `protocol` +- `host` +- `port` +- `username` +- `credentialRef` +- `passiveMode`(FTP 可选) +- `enabled` + +说明: +- 仓库工件与正式文档不得写入明文密码、密钥、证书 +- 真实凭据通过环境配置或配置中心引用承接 +- 命中协议下要求 `host/port/username/credentialRef` 齐备,否则立即阻断当前文件动作 + +## 目录字段最小集合 + +- `sendDir` +- `backDir` +- `reconcileDir` +- `archiveDir` +- `localTempDir` + +## 业务类型约束 + +- `businessType` + +说明: +- 本轮统一使用 `WITHHOLDING` +- 合同保留该字段,便于后续托收链路平移时复用同一解析器 + +## 固定变量白名单 + +仅允许以下变量: + +- `{tenantId}` +- `{companyId}` +- `{channelCode}` +- `{yyyyMMdd}` +- `{yyyyMM}` +- `{batchNo}` +- `{fileName}` + +禁止: +- 自由表达式 +- 任意脚本化拼装 +- 未声明变量 + +## 推荐 extParams 承接结构 + +```json +{ + "scopeType": "CHANNEL", + "tenantId": "optional", + "businessType": "WITHHOLDING", + "protocol": "SFTP", + "host": "example-host", + "port": 22, + "username": "config-ref-user", + "credentialRef": "bank.transfer.xxx", + "sendDir": "/withholding/{companyId}", + "backDir": "/withholding/{companyId}/back", + "reconcileDir": "/withholding/{companyId}/reconcile", + "archiveDir": "/withholding/{companyId}/archive", + "localTempDir": "/data/tmp/withholding/{yyyyMMdd}", + "enabled": true +} +``` + +说明: +- 示例仅用于字段结构表达,不代表真实配置值 +- 真实 host、账户、凭据引用名应由运行环境承接 diff --git a/specs/010-bank-transfer-config/contracts/bank-transfer-resolution-contract.md b/specs/010-bank-transfer-config/contracts/bank-transfer-resolution-contract.md new file mode 100644 index 0000000..81c291e --- /dev/null +++ b/specs/010-bank-transfer-config/contracts/bank-transfer-resolution-contract.md @@ -0,0 +1,91 @@ +# Contract: 银行文件传输统一解析合同 + +## 目标 + +定义文件动作在运行时如何根据上下文解析最终协议、目录和路径,作为 backend 统一解析器与验证工件的判定依据。 + +## 输入上下文 + +统一解析器至少接收以下字段: + +- `tenantId` +- `companyId` +- `channelId` +- `channelCode` +- `businessType` +- `stage` +- `businessDate` +- `batchNo` +- `fileName` + +其中 `stage` 取值范围为: + +- `SEND` +- `BACK` +- `RECONCILE` +- `ARCHIVE` +- `LOCAL_TEMP` + +## 作用域优先级 + +命中顺序固定为: + +`TENANT_CHANNEL > TENANT > CHANNEL > DEFAULT` + +## 字段级回退规则 + +- 更高优先级作用域可以只覆盖部分字段 +- 未覆盖字段必须回退到下一级有效配置 +- 不允许因为局部缺失而直接生成空路径 + +## 协议切换规则 + +- 同一业务动作应由统一解析结果决定最终协议 +- 业务代码不再自行判断 `SFTP/FTP` +- 配置变更仅影响新发起文件动作 +- 已开始或已落库批次继续沿用原解析结果 +- 对已创建代扣批次,送盘阶段预解析并固化的回盘目录/协议不得因后续配置切换而漂移 + +## 失败规则 + +遇到以下任一条件时,系统必须立即阻断当前文件动作并返回可诊断错误: + +- 未命中任何有效配置 +- 当前协议缺少必要连接信息 +- 当前阶段目录解析为空 +- 模板使用了未声明变量 + +## 审计输出 + +统一解析结果至少输出: + +- `protocol` +- `host` +- `port` +- `username` +- `credentialRef` +- `resolvedDir` +- `resolvedPath` +- `fileName` +- `sourceScope` + +说明: +- 本轮只强制保存最终实际使用的协议、目录、路径、文件名 +- 不强制保存配置版本号或完整配置快照 + +## 批次对象映射 + +- `WithholdingBatchDO`:承接送盘/回盘的最终协议、目录、路径、文件名 +- `ReconcileBatchDO`:承接对账文件的最终协议、目录、路径、文件名 + +## 最小验证场景 + +1. 默认规则命中 +2. 租户覆盖命中 +3. 通道覆盖命中 +4. 租户-通道覆盖命中 +5. 字段级回退 +6. 协议切换 +7. 配置缺失失败 +8. 非法模板变量失败 +9. 已落库批次配置切换后继续沿用原回盘目录 diff --git a/specs/010-bank-transfer-config/data-model.md b/specs/010-bank-transfer-config/data-model.md new file mode 100644 index 0000000..f1ea02b --- /dev/null +++ b/specs/010-bank-transfer-config/data-model.md @@ -0,0 +1,173 @@ +# Data Model: sw-business-bank 银行代扣文件传输配置能力 + +## 设计原则 + +- 优先复用现有配置载体和批次对象,不新增独立正式主表作为第一选择。 +- 本轮以逻辑实体 + 现有物理承接关系表达设计,不把真实密钥或密码写入文档。 +- 以“默认规则 + 覆盖规则 + 解析上下文 + 解析结果”构成最小可实现模型。 + +## 逻辑实体 + +### 1. FileTransferPolicy + +**说明**:环境默认文件传输策略,来源于 Spring profile + Nacos。 + +**字段**: +- `policyId`:默认可固定为 `default` +- `scopeType`:`DEFAULT` +- `protocol`:`SFTP | FTP` +- `host` +- `port` +- `username` +- `credentialRef`:凭据引用名,不存明文 +- `passiveMode`:FTP 可选 +- `sendDir` +- `backDir` +- `reconcileDir` +- `archiveDir` +- `localTempDir` +- `enabled` +- `remark` + +### 2. FileTransferOverride + +**说明**:银行通道/租户维度覆盖规则,建议复用 `bk_channel_api_config.ext_params`。 + +**字段**: +- `configId` +- `tenantId`:可为空,空表示非租户专属 +- `channelId` +- `scopeType`:`CHANNEL | TENANT | TENANT_CHANNEL` +- `businessType`:默认本轮为 `WITHHOLDING` +- `protocol`:可选覆盖 +- `host` +- `port` +- `username` +- `credentialRef` +- `passiveMode` +- `sendDir` +- `backDir` +- `reconcileDir` +- `archiveDir` +- `localTempDir` +- `enabled` +- `remark` + +**物理承接建议**: +- 使用 `ChannelApiConfigDO.extParams` +- 通过独立 `apiType` 表示“文件传输配置”,避免与交易接口配置混用 + +### 3. DirectoryResolutionContext + +**说明**:一次文件动作解析路径与协议时使用的上下文。 + +**字段**: +- `tenantId` +- `companyId` +- `channelId` +- `channelCode` +- `businessType` +- `stage`:`SEND | BACK | RECONCILE | ARCHIVE | LOCAL_TEMP` +- `businessDate` +- `batchNo` +- `fileName` + +### 4. ResolvedFileLocation + +**说明**:统一解析器输出的最终可执行目标。 + +**字段**: +- `sourceScope`:命中的作用域层级 +- `protocol` +- `host` +- `port` +- `username` +- `credentialRef` +- `resolvedDir` +- `resolvedPath` +- `fileName` +- `resolvedAt` + +## 枚举 + +### TransferStage +- `SEND` +- `BACK` +- `RECONCILE` +- `ARCHIVE` +- `LOCAL_TEMP` + +### TransferScope +- `DEFAULT` +- `CHANNEL` +- `TENANT` +- `TENANT_CHANNEL` + +### TransferProtocol +- `SFTP` +- `FTP` + +## 固定变量白名单 + +- `{tenantId}` +- `{companyId}` +- `{channelCode}` +- `{yyyyMMdd}` +- `{yyyyMM}` +- `{batchNo}` +- `{fileName}` + +## 现有物理对象扩展建议 + +### `WithholdingBatchDO` / `bk_withholding_batch` + +**现状已具备**: +- `sendFileName` +- `sendFilePath` +- `backFileName` +- `backFilePath` + +**建议新增**: +- `sendProtocol` +- `sendDir` +- `backProtocol` +- `backDir` + +**说明**: +- 送盘创建时同步固化 `sendProtocol/sendDir/sendFilePath` 与 `backProtocol/backDir`,确保后续已落库批次不因配置切换而漂移。 + +### `ReconcileBatchDO` / `bk_reconcile_batch` + +**现状已具备**: +- `fileName` +- `filePath` + +**建议新增**: +- `protocol` +- `dir` + +**说明**: +- 对账批次在回盘处理阶段固化最终 `protocol/dir/filePath/fileName`,形成最小审计闭环。 + +## 关系 + +- `FileTransferPolicy` 提供环境默认协议与目录。 +- `FileTransferOverride` 对默认规则做按字段覆盖。 +- `DirectoryResolutionContext` 驱动统一解析。 +- `ResolvedFileLocation` 由解析器生成。 +- `WithholdingBatchDO` 持久化送盘/回盘解析结果。 +- `ReconcileBatchDO` 持久化对账解析结果。 + +## Cross-Repo Impact + +- `water-docs` + - 回写 `REV-008` 详设、接口设计、安全设计、部署设计与治理台账。 +- `water-backend` + - `ChannelApiConfigExtParams` 承接四级作用域、业务类型、协议、连接字段与五类目录。 + - `BankTransferPathResolver` 负责默认规则、覆盖优先级、字段级回退与变量校验。 + - `BankWithholdingServiceImpl` 改为消费统一解析结果并固化 send/back/reconcile 审计字段。 + +## 最小实现结论 + +- 本轮不建议新增独立“文件传输策略表”。 +- 以 `profile/Nacos + ChannelApiConfigDO.extParams + 现有批次表增量字段` 完成 brownfield 最小落地。 diff --git a/specs/010-bank-transfer-config/docs-validation.md b/specs/010-bank-transfer-config/docs-validation.md new file mode 100644 index 0000000..47a101f --- /dev/null +++ b/specs/010-bank-transfer-config/docs-validation.md @@ -0,0 +1,22 @@ +# Docs Validation: sw-business-bank 银行代扣文件传输配置能力 + +## 命令结果 + +- `make validate-file FILE=docs/design/02_Detailed_Design/12_REV_Detailed.md`:通过,0 个问题 +- `make validate-file FILE=docs/design/03_Technical_Design/03_Interface_Design.md`:通过,0 个问题 +- `make validate-file FILE=docs/design/03_Technical_Design/04_Security_Design.md`:通过,0 个问题 +- `make validate-file FILE=docs/design/03_Technical_Design/05_Deployment_Design.md`:通过,0 个问题 +- `make validate-file FILE=docs/design/00_Management/01_Project_Progress.md`:通过,0 个问题 +- `make validate-file FILE=docs/design/00_Management/03_Task_Checklist.md`:通过,0 个问题 +- `make check-links`:通过,当前输出的仓库根 Markdown 链接检查无异常 +- `make validate-mermaid`:通过,当前命令输出 `README.md` 中 Mermaid 图表语法检查通过 + +## 影响文件 + +- `docs/design/02_Detailed_Design/12_REV_Detailed.md` +- `docs/design/03_Technical_Design/03_Interface_Design.md` +- `docs/design/03_Technical_Design/04_Security_Design.md` +- `docs/design/03_Technical_Design/05_Deployment_Design.md` +- `docs/design/00_Management/01_Project_Progress.md` +- `docs/design/00_Management/03_Task_Checklist.md` +- `specs/010-bank-transfer-config/*.md` diff --git a/specs/010-bank-transfer-config/final-verdict.md b/specs/010-bank-transfer-config/final-verdict.md new file mode 100644 index 0000000..e3bdc82 --- /dev/null +++ b/specs/010-bank-transfer-config/final-verdict.md @@ -0,0 +1,32 @@ +# Final Verdict: sw-business-bank 银行代扣文件传输配置能力 + +## 当前结论 + +- 状态:Implemented +- feature:`010-bank-transfer-config` +- 日期:2026-03-24 + +## 已交付范围 + +- 正式文档已补齐 `REV-008` 文件传输配置边界、统一解析优先级、安全约束与部署职责。 +- backend 已新增 `FILE_TRANSFER_CONFIG` 配置类型、统一文件传输解析器、`SFTP/FTP` 双协议解析能力,以及 send/back/reconcile 审计字段承接。 +- 已形成 `baseline.md`、`backend-validation.md`、`docs-validation.md` 三类验证工件,可追溯本轮范围、基线和验证结果。 +- 已补充独立 Java smoke CLI 与 Docker 测试环境联动验证:`BankTransferSftpSmokeCli` 对 `bank-transfer-test-sftp` 验证通过,`BankTransferFtpSmokeCli` 对 `bank-transfer-test-ftp` 验证通过,上传后再下载的样本 SHA256 一致。 + +## Deferred 范围 + +- 真实银行 `SFTP/FTP` 联调、生产凭据与白名单开通 +- `BankCollection` 托收链路对等改造 +- 运行态样本、真实回盘文件与生产环境故障演练补证 + +## 风险提示 + +- `bk_channel_api_config` 现有后台管理约束对 `FILE_TRANSFER_CONFIG` 采取“按 `configId` 管理、多条同 `channelId + apiType` 允许”的实现口径,后续若补运营端维护页面,需同步确认 UI/查询行为。 +- 当前“已落库批次不漂移”已覆盖回盘目录与协议;若后续把对账、归档也提升为更严格的跨批次快照约束,需要补充更细粒度持久化字段。 +- 当前 Docker smoke 证明了解析结果可驱动本地容器化 `SFTP/FTP` 收发,但不等同于真实银行网络、白名单、生产凭据和专有报文联调已完成。 + +## 下一步建议 + +1. 在测试或联调环境补 `SFTP/FTP` 真实连通性与样本文件验证。 +2. 若要扩展到 `BankCollection`,优先复用同一解析器与合同,而不是复制第二套路径拼接逻辑。 +3. 后续如新增运营配置入口,应把 `scopeType/businessType/tenantId/channelId` 的录入约束同步进后台表单与校验逻辑。 diff --git a/specs/010-bank-transfer-config/plan.md b/specs/010-bank-transfer-config/plan.md new file mode 100644 index 0000000..af47077 --- /dev/null +++ b/specs/010-bank-transfer-config/plan.md @@ -0,0 +1,157 @@ +# Implementation Plan: sw-business-bank 银行代扣文件传输配置能力 + +**Branch**: `010-bank-transfer-config` | **Date**: 2026-03-23 | **Spec**: [/Volumes/Dpan/github/water-workspace/water-docs/specs/010-bank-transfer-config/spec.md](./spec.md) +**Input**: Feature specification from `/Volumes/Dpan/github/water-workspace/water-docs/specs/010-bank-transfer-config/spec.md` + +**Note**: This template is filled in by the `/speckit.plan` command. For this project, planning is document-first and multi-repo aware. + +## Summary + +在既有 `REV-008 / SYS-009` 银行代扣能力基础上,为 `sw-business-bank` 增加文件传输配置能力最小闭环:将送盘、回盘、对账、归档、本地临时五类目录从 `BankWithholdingServiceImpl` 的硬编码路径中抽离,支持 `SFTP / FTP` 双协议配置选择,支持“默认规则 + 银行通道覆盖 + 租户覆盖 + 租户-银行通道覆盖”的统一解析,明确配置变更仅影响新发起文件动作、已开始或已落库批次继续沿用原解析结果,并将正式结论回写既有主文档与治理台账,不新增平行正式稿。 + +## Repository Scope + +- **Formal workflow home**: `water-docs` +- **Target repos in scope**: + - `water-docs`: Yes + - `water-backend`: Yes + - `water-frontend`: No +- **Primary delivery mode**: Mixed + +## Code Baseline + +- **Backend baseline**: `water-backend` branch `develop` @ `b540f1f48bf2d6c28aa183749ca61231071c0942` +- **Frontend baseline**: N/A +- **Baseline capture plan**: 所有“当前已支持 / 本轮新增支持 / 仍待补证”的判断均绑定上述 backend baseline,并在 `baseline.md`、`backend-validation.md`、`final-verdict.md` 中固定 branch 与 commit,确保文档结论始终锚定到可追溯实现版本。 + +## Technical Context + +**Primary Work Product**: 正式设计文档修订、`specs/010-bank-transfer-config/` 计划工件、backend 配置承接与路径解析增强、最小编译/测试验证 +**Source of Truth Documents**: `docs/design/02_Detailed_Design/12_REV_Detailed.md`、`docs/design/03_Technical_Design/03_Interface_Design.md`、`docs/design/03_Technical_Design/04_Security_Design.md`、`docs/design/03_Technical_Design/05_Deployment_Design.md`、`.specify/memory/constitution.md` +**Reference Sources**: `docs/guides/BACKEND_CURRENT_STATUS.md`、Archive 历史资料(只读核对)、`../water-backend/sw-business-bank/sw-business-bank-server/src/main/resources/application.yaml`、`../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/service/bankwithholding/BankWithholdingServiceImpl.java`、`../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/dal/dataobject/channelapiconfig/ChannelApiConfigDO.java` +**Validation Commands**: `make validate-file FILE=<目标文档>`、`make check-links`、`mvn -f /Volumes/Dpan/github/water-workspace/water-backend/sw-business-bank/pom.xml -pl sw-business-bank-server -am -DskipTests compile`、`mvn -f /Volumes/Dpan/github/water-workspace/water-backend/sw-business-bank/pom.xml -pl sw-business-bank-server -am -Dtest=BankTransferPathResolverTest,BankWithholdingTransferConfigTest -Dsurefire.failIfNoSpecifiedTests=false test` +**Target Scope**: 正式文档中的 `REV-008` 详设、接口设计、安全设计、部署设计、项目进度台账、任务清单台账;backend 中 `BankWithholding` 送盘/回盘/对账路径解析与审计承接、`ARCHIVE` / `LOCAL_TEMP` 的目录解析能力、`ChannelApiConfigDO.extParams` 的通道级覆盖能力、沿用 Spring profile + Nacos 的配置加载 +**Project Type**: 文档治理仓库 + 多仓实现协作 +**Constraints**: 不新增平行正式文档;不把真实密钥、密码、证书写入仓库;仅允许固定变量模板;配置缺失或连接信息不完整时立即阻断;配置切换仅影响新动作;审计只保留最终解析结果,不保留完整配置快照 +**Scale/Scope**: cross-document + backend focused + validation-light + +## Constitution Check + +*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* + +- [x] **主文档归属已确认**:正式结论回写既有主文档与治理台账,不新增平行正式稿。 +- [x] **多仓范围已确认**:本轮涉及 `water-docs` 与 `water-backend`;`water-frontend` 不在范围内。 +- [x] **代码基线已确认**:backend 基线固定为 `develop @ b540f1f48bf2d6c28aa183749ca61231071c0942`。 +- [x] **Archive 使用方式合规**:Archive 仅作来源核对,不替代正式口径。 +- [x] **一致性影响已列出**:影响 `REV-008` 能力边界、接口说明、安全口径、部署口径、审计字段与验证工件。 +- [x] **校验与台账动作已规划**:已规划文档校验、backend 编译/测试、`01_Project_Progress.md` 与 `03_Task_Checklist.md` 更新。 + +## Project Structure + +### Feature Artifacts + +```text +specs/010-bank-transfer-config/ +├── spec.md +├── plan.md +├── research.md +├── data-model.md +├── quickstart.md +├── contracts/ +│ ├── bank-transfer-config-contract.md +│ └── bank-transfer-resolution-contract.md +├── tasks.md +├── baseline.md +├── backend-validation.md +├── docs-validation.md +└── final-verdict.md +``` + +### Repository Touchpoints + +```text +water-docs/ +├── docs/design/02_Detailed_Design/12_REV_Detailed.md +├── docs/design/03_Technical_Design/03_Interface_Design.md +├── docs/design/03_Technical_Design/04_Security_Design.md +├── docs/design/03_Technical_Design/05_Deployment_Design.md +├── docs/design/00_Management/01_Project_Progress.md +└── docs/design/00_Management/03_Task_Checklist.md + +water-backend/ +└── sw-business-bank/sw-business-bank-server/ + ├── src/main/java/.../service/bankwithholding/ + ├── src/main/java/.../dal/dataobject/channelapiconfig/ + ├── src/main/java/.../dal/dataobject/withholdingbatch/ + ├── src/main/java/.../dal/dataobject/reconcilebatch/ + ├── src/main/resources/ + └── src/test/java/... +``` + +**Structure Decision**: 正式设计只更新既有主文档;backend 只做配置承接、统一解析、审计字段补齐、最小测试;不扩展 frontend;不把真实 SFTP/FTP 凭据写入仓库。 + +## Phase 0: Research & Alignment + +### Research Inputs + +- 当前硬编码路径分别在哪些方法生成,哪些 DO 已落库保存 +- `ChannelApiConfigDO.extParams` 是否足以承接“通道/租户覆盖” +- 统一解析上下文是否需要显式包含业务类型(`businessType`),以及它在本轮 `BankWithholding` 场景下的最小承接方式 +- 默认规则与覆盖规则的最小优先级模型如何表达 +- 审计字段最少需要新增到哪些现有 DO / 表 +- 非法模板变量、配置缺失、连接信息不完整与已落库批次配置切换等场景中,哪些验证必须自动化,哪些仅需文档声明为 deferred + +### Deliverables + +- `research.md` +- `baseline.md` + +## Phase 1: Design & Contracts + +### Planned Artifacts + +- `data-model.md` +- `contracts/bank-transfer-config-contract.md` +- `contracts/bank-transfer-resolution-contract.md` +- `quickstart.md` +- `backend-validation.md` +- `docs-validation.md` +- `final-verdict.md` + +### Design Decisions + +- 默认配置来源采用 Spring profile + Nacos +- 通道/租户覆盖优先复用 `bk_channel_api_config.ext_params` +- 在 `bk_channel_api_config` 中使用专用 `apiType` 表示“文件传输配置”,避免与单笔交易 API 混用 +- 新增统一解析器,输入至少包含 `tenantId/companyId/channelId/businessType/stage/businessDate/batchNo/fileName`,其中 `businessType` 对应业务类型,输出 `protocol/dir/path/fileName/sourceScope` +- 统一解析器必须覆盖 `SEND`、`BACK`、`RECONCILE`、`ARCHIVE`、`LOCAL_TEMP` 五类目录;其中 `ARCHIVE` / `LOCAL_TEMP` 本轮至少要求具备解析能力与测试覆盖,不强制新增独立持久化审计对象 +- 路径模板只支持固定变量集合:`{tenantId}`、`{companyId}`、`{channelCode}`、`{yyyyMMdd}`、`{yyyyMM}`、`{batchNo}`、`{fileName}` +- 使用未声明变量时,解析器必须立即失败并返回可诊断错误 +- 更具体配置覆盖更通用配置;上层不完整时逐字段回退 +- `BankWithholdingServiceImpl` 只接入解析结果,不再自行拼接路径 +- 配置变更仅影响新发起文件动作;已开始或已落库批次继续沿用原解析结果 +- 审计只记录最终协议、目录、路径、文件名,不记录配置版本号或完整配置快照 +- 缺失配置、缺失必要连接信息或命中错误作用域时直接失败,不回退到错误通道 + +## Validation Plan + +- **Document validation**: `make validate-file FILE=docs/design/02_Detailed_Design/12_REV_Detailed.md`、`make validate-file FILE=docs/design/03_Technical_Design/03_Interface_Design.md`、`make validate-file FILE=docs/design/03_Technical_Design/04_Security_Design.md`、`make validate-file FILE=docs/design/03_Technical_Design/05_Deployment_Design.md`、`make validate-file FILE=docs/design/00_Management/01_Project_Progress.md`、`make validate-file FILE=docs/design/00_Management/03_Task_Checklist.md`;如有跨文档链接更新再执行 `make check-links` +- **Backend validation**: 目标单元测试与服务级验证至少覆盖默认规则、租户覆盖、通道覆盖、租户-通道覆盖、字段级回退、协议切换、非法模板变量失败、配置缺失失败,以及“配置切换仅影响新动作、已落库批次不漂移”等场景;同时通过最小编译校验 +- **Frontend validation**: N/A +- **Evidence output**: `baseline.md`、`backend-validation.md`、`docs-validation.md`、`final-verdict.md` +- **Conditional diagram validation**: 若本轮修改 `docs/design/` 中的 Mermaid 图表,必须执行 `make validate-mermaid` 并将结果记录到 `docs-validation.md` + +## Ledger Sync Plan + +- **Project progress update required**: Yes +- **Task checklist update required**: Yes +- **Evidence or verification summary update required**: Yes +- **Result summary requirement**: 完成重要变更后,结果摘要必须说明修改文件、校验结果、剩余风险与后续建议 + +## Complexity Tracking + +> **Fill ONLY if Constitution Check has violations that must be justified** + +| Violation | Why Needed | Simpler Alternative Rejected Because | +|-----------|------------|-------------------------------------| +| 无 | 本次 Constitution Check 已通过 | 无 | diff --git a/specs/010-bank-transfer-config/quickstart.md b/specs/010-bank-transfer-config/quickstart.md new file mode 100644 index 0000000..8bab45e --- /dev/null +++ b/specs/010-bank-transfer-config/quickstart.md @@ -0,0 +1,139 @@ +# Quickstart: sw-business-bank 银行代扣文件传输配置能力 + +## 1. 固定基线 + +1. 在 `water-docs` 中确认当前 feature 为 `010-bank-transfer-config`。 +2. 在 `water-backend` 中固定 branch 与 commit: + - branch:`001-sys009-withholding-closure` + - commit:`84493513c1d06936210ab7e697985d38958ba5ee` + +## 2. 阅读必要上下文 + +- `docs/design/00_Management/01_Project_Progress.md` +- `docs/design/00_Management/03_Task_Checklist.md` +- `docs/design/02_Detailed_Design/12_REV_Detailed.md` +- `docs/design/03_Technical_Design/03_Interface_Design.md` +- `docs/design/03_Technical_Design/04_Security_Design.md` +- `docs/design/03_Technical_Design/05_Deployment_Design.md` +- `spec.md` +- `research.md` +- `data-model.md` + +## 3. 准备最小配置样本 + +准备 7 组配置样本: + +1. 默认规则 +2. 租户覆盖规则 +3. 通道覆盖规则 +4. 租户-通道覆盖规则 +5. 协议切换样本(`SFTP -> FTP` 或 `FTP -> SFTP`) +6. 非法模板变量样本(例如 `{unknown}`) +7. 已落库批次配置切换回归样本 + +要求: +- 目录分化至少覆盖 `send/back/reconcile/archive/localTemp` +- 变量仅使用固定白名单 +- 准备 1 组缺失连接信息样本用于失败验证 + +## 4. 执行 backend 验证 + +最少验证以下场景: + +1. **默认规则命中**:无覆盖时使用默认协议与目录 +2. **租户覆盖命中**:租户覆盖仅影响本租户 +3. **通道覆盖命中**:通道覆盖优先于默认 +4. **租户-通道覆盖命中**:最具体规则优先 +5. **字段级回退**:仅覆盖 `sendDir` 时,其余阶段回退上一级 +6. **协议切换**:同一业务动作切换协议后不改业务拼路径代码 +7. **配置缺失失败**:缺协议、缺 host、缺目录时立即阻断 +8. **非法变量失败**:目录模板命中未声明变量时立即阻断 +9. **已落库批次不漂移**:送盘后切换配置,再处理同批次回盘时仍沿用批次已固化目录 + +## 5. 执行文档校验 + +```bash +make validate-file FILE=docs/design/02_Detailed_Design/12_REV_Detailed.md +make validate-file FILE=docs/design/03_Technical_Design/03_Interface_Design.md +make validate-file FILE=docs/design/03_Technical_Design/04_Security_Design.md +make validate-file FILE=docs/design/03_Technical_Design/05_Deployment_Design.md +make validate-file FILE=docs/design/00_Management/01_Project_Progress.md +make validate-file FILE=docs/design/00_Management/03_Task_Checklist.md +make check-links +``` + +## 6. 执行 backend 最小验证 + +```bash +mvn -f /Volumes/Dpan/github/water-workspace/water-backend/sw-business-bank/pom.xml -pl sw-business-bank-server -am -DskipTests compile +mvn -f /Volumes/Dpan/github/water-workspace/water-backend/sw-business-bank/pom.xml -pl sw-business-bank-server -am -Dtest=BankTransferPathResolverTest,BankWithholdingTransferConfigTest test +``` + +## 6.1 执行 Docker 文件通道 Smoke + +启动 Docker 测试环境: + +```bash +docker compose -f infra/docker/bank-transfer-test/compose.yaml up -d +``` + +执行 Java SFTP smoke: + +```bash +mvn -f /Volumes/Dpan/github/water-workspace/water-backend/sw-business-bank/sw-business-bank-server/pom.xml \ + -DincludeScope=runtime dependency:build-classpath \ + -Dmdep.outputFile=/tmp/sw-business-bank-server.cp + +java -cp "$(cat /tmp/sw-business-bank-server.cp):/Volumes/Dpan/github/water-workspace/water-backend/sw-business-bank/sw-business-bank-server/target/classes" \ + cn.com.emsoft.sw.bankbusiness.tools.BankTransferSftpSmokeCli \ + --local-file /Volumes/Dpan/github/water-workspace/water-docs/infra/docker/bank-transfer-test/tmp/sample.txt \ + --host 127.0.0.1 \ + --port 2222 \ + --username demo \ + --password demo123 \ + --send-dir /upload/{companyId} \ + --company-id C001 \ + --channel-code 00001 \ + --batch-no SMOKE010 \ + --business-date 2026-03-24 \ + --remote-file-name smoke-cli-sample.txt +``` + +执行 Java FTP smoke: + +```bash +java -cp "$(cat /tmp/sw-business-bank-server.cp):/Volumes/Dpan/github/water-workspace/water-backend/sw-business-bank/sw-business-bank-server/target/classes" \ + cn.com.emsoft.sw.bankbusiness.tools.BankTransferFtpSmokeCli \ + --local-file /Volumes/Dpan/github/water-workspace/water-docs/infra/docker/bank-transfer-test/tmp/sample.txt \ + --host 127.0.0.1 \ + --port 2121 \ + --username demo \ + --password demo123 \ + --send-dir {companyId} \ + --company-id C001 \ + --channel-code 00001 \ + --batch-no SMOKE010FTP \ + --business-date 2026-03-24 \ + --remote-file-name smoke-cli-ftp-sample.txt +``` + +当前已验证结论: + +- SFTP roundtrip 通过 +- FTP roundtrip 通过 +- 上传后再下载的样本 SHA256 一致 + +## 7. 汇总验证工件 + +- `baseline.md` +- `backend-validation.md` +- `docs-validation.md` +- `final-verdict.md` + +## 8. 通过标准 + +- 五类核心验证场景全部有证据 +- 文档校验通过 +- backend 编译通过 +- 正式文档与验证结论一致 +- 台账已同步 diff --git a/specs/010-bank-transfer-config/research.md b/specs/010-bank-transfer-config/research.md new file mode 100644 index 0000000..b863042 --- /dev/null +++ b/specs/010-bank-transfer-config/research.md @@ -0,0 +1,93 @@ +# Research: sw-business-bank 银行代扣文件传输配置能力 + +## 研究目标 + +本轮研究只解决“配置承接 + 统一解析 + 审计落点 + 文档闭环”,不把真实银行生产联调、完整 SFTP/FTP 客户端接入或私有文件报文解析扩展进当前范围。 + +## 基线与现状 + +- backend 基线固定为:`water-backend` branch `001-sys009-withholding-closure` @ `84493513c1d06936210ab7e697985d38958ba5ee` +- 当前 `BankWithholdingServiceImpl` 在业务方法内硬编码生成送盘、回盘、对账路径,未复用统一解析层。 +- 当前批次对象已能保存送盘/回盘/对账文件名与路径,但未统一保存协议与目录。 +- 当前配置加载已沿用 Spring profile + Nacos 导入方式,可承接环境级默认规则。 +- `ChannelApiConfigDO.extParams` 已存在但当前为空对象,可作为银行通道级覆盖配置的最小 carrier。 + +## 现有实现问题归纳 + +1. 路径硬编码散落在 `BankWithholdingServiceImpl` 中,无法支撑运行时切换。 +2. 送盘、回盘、对账各自拼接路径,缺少统一优先级与字段级回退规则。 +3. 审计仅留存文件名与路径,无法完整表达本轮要求的“协议 + 目录 + 路径 + 文件名”。 +4. 当前 backend 尚未存在成熟的 SFTP/FTP 传输适配层,本轮不宜把联调闭环与传输客户端实现一并扩大到必交付。 + +## 配置承接方案比选 + +### Decision: 默认规则沿用 Spring profile + Nacos + +**Rationale**: +- 现有应用已通过 `application-{profile}.yaml` + Nacos 导入配置,具备最低接入成本。 +- 环境级默认规则更适合由 profile/Nacos 承接,避免在业务表中固化所有默认配置。 + +**Alternatives considered**: +- 完全新建独立文件传输配置表:当前范围过重,且与既有配置中心能力重复。 + +### Decision: 通道/租户覆盖优先复用 `ChannelApiConfigDO.extParams` + +**Rationale**: +- 现有 `ChannelApiConfigDO` 已具备银行通道维度配置语义,`extParams` 可以作为最小增量承接文件传输覆盖规则。 +- 复用既有对象可降低本轮 schema 扩张与治理成本。 + +**Alternatives considered**: +- 新增专门的文件传输策略表:对当前 brownfield 需求来说过重。 +- 把所有覆盖规则继续塞入 service 常量:无法满足统一解析与运行时切换。 + +### Decision: 路径模板仅支持固定变量集合 + +**Rationale**: +- 当前已澄清只允许固定变量白名单,可显著降低解析复杂度与安全风险。 +- 更适合形成稳定测试样本与正式文档说明。 + +**Alternatives considered**: +- 自由表达式模板:与已澄清约束冲突,且增加安全与维护风险。 +- 完全固定路径:无法满足租户、通道、日期分化需求。 + +### Decision: 配置缺失或连接信息不完整时立即阻断 + +**Rationale**: +- 已澄清的失败策略要求立即阻断当前文件动作,避免静默回退或进入不确定人工补救状态。 +- 有利于验证工件给出明确失败结论。 + +**Alternatives considered**: +- 仅记日志继续流程:会削弱审计与问题定位能力。 +- 自动回退到其他租户/通道配置:存在误用配置风险。 + +## 决策结论 + +1. 引入统一解析入口,输入上下文、输出最终解析结果。 +2. 作用域优先级固定为:`TENANT_CHANNEL > TENANT > CHANNEL > DEFAULT`。 +3. 上层覆盖不完整时采用字段级回退,而不是整组失败。 +4. 配置变更仅影响新发起文件动作,已开始或已落库批次沿用原解析结果。 +5. 审计只保存最终实际使用的协议、目录、路径、文件名,不强制留存配置版本或完整快照。 + +## 对正式文档的影响 + +- `12_REV_Detailed.md`:补齐 `REV-008` 的文件通道配置、路径分化、运行时切换与仍待补证边界。 +- `03_Interface_Design.md`:补齐文件交换能力边界、解析优先级、失败规则与审计说明,不新增外部接口编号。 +- `04_Security_Design.md`:补齐协议选择、凭据管理、敏感配置禁入仓库、优先 SFTP / 兼容 FTP 的治理口径。 +- `05_Deployment_Design.md`:补齐 profile/Nacos 承接、银行文件交换通道、环境差异、白名单与本地临时/归档目录职责说明。 + +## Cross-Repo Impact + +- `water-docs` + - 更新正式主文档与治理台账,形成可评审的规格闭环。 +- `water-backend` + - `ApiTypeEnum` 新增文件传输配置类型。 + - `ChannelApiConfigExtParams` 扩展作用域、业务类型、连接字段、目录字段。 + - 新增 `config/filetransfer/` 与 `service/filetransfer/` 解析器。 + - `BankWithholdingServiceImpl` 从硬编码目录切换到统一解析入口,并固化 send/back/reconcile 审计字段。 + +## 风险与 Deferred + +- 真实 SFTP/FTP 客户端与网络连通性联调:Deferred +- `BankCollection` 托收链路对等改造:Deferred +- 生产凭据、证书、白名单开通:Deferred +- `ARCHIVE / LOCAL_TEMP` 的独立持久化审计对象:Deferred,但当前可先纳入统一解析能力范围 diff --git a/specs/010-bank-transfer-config/spec.md b/specs/010-bank-transfer-config/spec.md new file mode 100644 index 0000000..50f2d2d --- /dev/null +++ b/specs/010-bank-transfer-config/spec.md @@ -0,0 +1,187 @@ +# Feature Specification: sw-business-bank 银行代扣文件传输配置能力 + +**Feature Branch**: `010-bank-transfer-config` +**Created**: 2026-03-23 +**Status**: Implemented +**Input**: User description: "/speckit-specify 实现 sw-business-bank 银行代扣文件传输配置能力,支持 SFTP/FTP 双协议、租户与银行通道维度的目录分化、统一路径解析与运行时配置切换" + +## Document Scope & Sources *(mandatory)* + +- **Target documents**: + - `docs/design/02_Detailed_Design/12_REV_Detailed.md` + - `docs/design/03_Technical_Design/03_Interface_Design.md` + - `docs/design/03_Technical_Design/04_Security_Design.md` + - `docs/design/03_Technical_Design/05_Deployment_Design.md` + - `docs/design/00_Management/01_Project_Progress.md` + - `docs/design/00_Management/03_Task_Checklist.md` + - `specs/010-bank-transfer-config/spec.md` +- **Primary source of truth**: + - `docs/design/02_Detailed_Design/12_REV_Detailed.md` + - `docs/design/03_Technical_Design/03_Interface_Design.md` + - `docs/design/03_Technical_Design/04_Security_Design.md` + - `docs/design/03_Technical_Design/05_Deployment_Design.md` + - `.specify/memory/constitution.md` +- **Reference sources**: + - `docs/guides/BACKEND_CURRENT_STATUS.md` + - `docs/design/04_Appendix/Archive/03_Design_Docs/营业收费管理系统-概要设计说明书20250912.md` + - `../water-backend/sw-business-bank/sw-business-bank-server/src/main/resources/application.yaml` + - `../water-backend/sw-business-bank/sw-business-bank-server/src/main/resources/application-dev.yaml` + - `../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/service/bankwithholding/BankWithholdingServiceImpl.java` +- **Scope decision**: 本次需求在范围内。其目标是在既有 `REV-008` / `SYS-009` 银行代扣能力基础上补齐文件传输配置、路径分化与运行时切换能力,并将结果回写到现有正式主文档,不新增平行正式稿。 + +## Repository Scope *(mandatory)* + +- **Target repos**: + - `water-docs`: Required + - `water-backend`: Required + - `water-frontend`: Not Required +- **Expected delivery type**: Mixed +- **Out of scope for this round**: + - 真实银行生产联调、白名单开通与正式网络连通性验收 + - 具体银行私有文件报文格式的逐字段解析补完 + - `BankCollection` 托收链路与前端运营页面同步改造 + - 新建独立的正式主文档替代现有接口设计、详细设计、部署设计或安全设计主文档 + +## Code Baseline *(mandatory for brownfield work)* + +- **Backend baseline**: `water-backend` `001-sys009-withholding-closure` @ `84493513c1d06936210ab7e697985d38958ba5ee` +- **Frontend baseline**: N/A +- **Baseline capture rule**: 所有“已支持”“待实现”“运行时可切换”“仍需联调补证”的判断,必须绑定到本次 backend baseline,并在验证工件中标明对应配置入口、路径解析入口和最小验证结果。 + +## Evidence Scope *(mandatory)* + +- **Document evidence required**: + - `specs/010-bank-transfer-config/spec.md` + - `docs/design/02_Detailed_Design/12_REV_Detailed.md` 中 `REV-008` 银行代扣文件通道与路径分化口径 + - `docs/design/03_Technical_Design/03_Interface_Design.md` 中银行文件交换能力边界与运行态说明 + - `docs/design/03_Technical_Design/04_Security_Design.md` 中凭据管理、协议选择与敏感配置口径 + - `docs/design/03_Technical_Design/05_Deployment_Design.md` 中运行环境、配置中心与文件通道部署口径 + - 管理台账中的进度记录与任务状态更新 +- **Backend evidence required**: + - `sw-business-bank` 现有送盘、回盘、对账路径生成逻辑的基线证据 + - 新增的文件传输配置承接入口、路径解析入口与协议选择入口 + - 至少覆盖默认配置、租户覆盖、通道覆盖、阶段目录解析的自动化验证 + - 最小编译或测试验证结果 +- **Frontend evidence required**: + - N/A +- **Verification artifacts required**: + - `specs/010-bank-transfer-config/baseline.md` + - `specs/010-bank-transfer-config/backend-validation.md` + - `specs/010-bank-transfer-config/docs-validation.md` + - `specs/010-bank-transfer-config/final-verdict.md` + +## Clarifications + +### Session 2026-03-23 + +- Q: 运行时配置切换应如何作用于已开始或已落库的批次? → A: 配置变更仅对新发起的文件动作生效;已开始或已落库的批次继续沿用原解析结果。 +- Q: 目录规则中的路径模板应支持多大范围的动态能力? → A: 仅支持固定变量集合,例如 `{tenantId}`、`{companyId}`、`{channelCode}`、`{yyyyMMdd}`、`{yyyyMM}`、`{batchNo}`、`{fileName}`。 +- Q: 审计追溯时,除最终解析结果外,是否必须额外留存配置版本或完整配置快照? → A: 只留存最终实际使用的协议、目录、文件路径与文件名,不强制留存配置版本号或完整配置快照。 +- Q: 当配置缺失或协议连接信息不完整时,系统应如何处理当前文件动作? → A: 立即阻断本次文件动作,返回明确配置错误,由调用方或运维后续处理。 + +## User Scenarios & Testing *(mandatory)* + +### User Story 1 - 配置外部化管理银行文件通道 (Priority: P1) + +作为银行代扣运维或实施人员,我需要把文件传输协议、连接信息和各阶段目录从代码中抽离到运行时配置中,这样我可以在不同环境、不同租户或不同银行通道下复用同一套业务实现,而不必为目录差异反复改代码。 + +**Why this priority**: 这是本次需求的核心。如果协议和目录仍散落在代码里,后续租户扩展、银行切换和运维交接都会继续依赖人工改码,无法形成稳定可交付能力。 + +**Independent Test**: 评审人仅根据规格和验证工件,即可确认系统已经定义了外部化的协议、连接与目录配置边界,并明确哪些目录允许默认值、租户覆盖和通道覆盖。 + +**Acceptance Scenarios**: + +1. **Given** 系统存在送盘、回盘、对账等不同文件阶段,**When** 运维为某银行通道配置文件传输规则,**Then** 各阶段目录必须可独立定义,而不是共用单一路径。 +2. **Given** 某租户沿用通道默认目录,另一租户需要独立目录,**When** 两者并行运行,**Then** 租户专属配置只影响自身,不影响其他租户或默认通道配置。 + +--- + +### User Story 2 - 运行时统一解析路径与协议 (Priority: P2) + +作为后端运行服务,我需要在执行送盘、回盘、对账等文件动作时,按统一规则解析当前应使用的协议、连接和目录,这样相同业务动作在不同租户、机构、通道和日期条件下都能得到一致、可追踪的文件路径。 + +**Why this priority**: 仅有配置项但没有统一解析规则,会导致送盘、回盘、对账继续各自拼接路径,最终形成新的散乱实现,无法真正支持运行时切换。 + +**Independent Test**: 通过自动化验证或人工核对工件,可以独立判断默认规则、覆盖优先级、缺省回退和配置缺失时的失败行为是否定义清晰。 + +**Acceptance Scenarios**: + +1. **Given** 同一银行通道下存在全局默认目录和租户级覆盖目录,**When** 服务解析某租户的送盘路径,**Then** 必须优先使用更具体的覆盖规则,并在未覆盖的阶段回退到低优先级配置。 +2. **Given** 文件传输协议可在 SFTP 和 FTP 间选择,**When** 某通道切换协议但业务动作不变,**Then** 服务必须按新协议选择相应连接信息,而不要求修改业务代码路径拼接逻辑。 + +--- + +### User Story 3 - 形成可审计的文档与验证闭环 (Priority: P3) + +作为项目治理与评审人员,我需要正式文档、基线和验证工件同步更新,这样后续计划、任务拆解和联调准备都能直接复用统一口径,而不需要再次解释当前能力边界。 + +**Why this priority**: 文件传输配置能力既影响实现,也影响接口边界、安全与部署口径;如果只改代码不回写正式文档,后续评审和联调会再次出现“设计与实现脱节”。 + +**Independent Test**: 仅检查 `specs/010-bank-transfer-config/` 工件和被更新的正式文档,即可确认本轮的目标、基线、验证结果、剩余风险和台账同步情况。 + +**Acceptance Scenarios**: + +1. **Given** 本轮涉及银行文件通道配置与路径解析能力扩展,**When** 功能完成,**Then** 正式文档必须明确协议选择、目录分化、凭据管理和未完成的真实联调边界。 +2. **Given** 本轮属于 brownfield 功能增强,**When** 收尾,**Then** 管理台账必须记录本次范围、最小验证结果和后续待补证事项。 + +--- + +### Edge Cases + +- 当某租户仅覆盖送盘目录而未覆盖回盘、对账目录时,系统必须对未覆盖阶段回退到更低优先级配置,而不是产生空路径。 +- 当租户级覆盖与通道级覆盖同时存在且指向不同目录时,系统必须有固定优先级,避免不同动作解析结果不一致。 +- 当协议已切换但对应连接信息不完整时,系统必须阻断本次文件动作,并给出可定位的失败原因,而不是沿用旧协议静默执行。 +- 当配置在批次处理中发生变更时,系统必须保证已开始或已落库的批次继续沿用原解析结果,避免送盘、回盘和对账记录跨版本漂移。 +- 当业务日期参与目录分层时,系统必须保证同一批次的记录路径与实际执行路径一致,避免送盘记录、回盘记录和对账记录彼此无法追溯。 +- 当目录规则引用动态变量时,系统必须仅允许使用预先定义并已文档化的固定变量集合,禁止使用未声明的自由表达式或任意脚本化拼装。 +- 当目录规则引用未声明变量时,系统必须立即阻断当前文件动作并返回可诊断错误。 +- 当系统进行审计追溯时,必须能够还原某次文件动作最终实际使用的协议、目录、文件路径与文件名;本轮不以配置版本号或完整配置快照作为强制留存项。 +- 当运行环境、租户、机构和银行通道的组合未命中任何有效配置时,系统必须立即阻断当前文件动作并返回明确的配置缺失结论,而不是回退到错误租户或错误通道的目录。 + +## Assumptions + +- 本轮优先覆盖 `BankWithholding` 代扣链路,不要求同时完成 `BankCollection` 托收链路对等改造。 +- 运行时配置中心沿用当前 `sw-business-bank` 已使用的配置加载方式,不在本轮重新定义新的配置基础设施。 +- 文件传输目录分化至少覆盖送盘、回盘、对账、归档和本地临时目录五类场景。 +- 本轮对 `ARCHIVE` 与 `LOCAL_TEMP` 至少要求具备统一解析能力与验证覆盖,不强制新增独立持久化审计对象。 +- 真实银行账号、密码、密钥和网络连通性仍按环境安全流程管理,本轮只定义正式口径与承接能力,不把真实凭据写入仓库文档。 + +## Requirements *(mandatory)* + +### Functional Requirements + +- **FR-001**: 系统必须支持将银行代扣文件传输的协议、连接信息和阶段目录从业务代码中外部化管理。 +- **FR-002**: 系统必须支持 SFTP 与 FTP 两种文件传输模式,并允许按银行通道选择其一作为当前生效模式。 +- **FR-003**: 系统必须支持分别定义送盘、回盘、对账、归档和本地临时目录,而不是把所有文件动作绑定到同一路径。 +- **FR-004**: 系统必须支持全局默认规则、银行通道规则、租户规则,以及租户下银行通道规则四级配置表达能力。 +- **FR-005**: 系统必须定义固定的目录解析优先级,使更具体的配置覆盖更通用的配置,且解析结果在所有文件阶段上保持一致。 +- **FR-006**: 系统必须根据当前运行上下文解析文件路径;该上下文至少包括租户、机构、银行通道、业务类型(businessType)、文件阶段和业务日期。 +- **FR-007**: 系统必须支持在目录规则中引用命名上下文变量;变量集合必须限定为预先定义、可文档化的固定变量,不支持自由表达式或脚本化模板能力。 +- **FR-008**: 系统必须支持在不修改业务代码的前提下切换文件传输协议或目录规则;配置变更仅对新发起的文件动作生效,已开始或已落库的批次必须继续沿用原解析结果。 +- **FR-009**: 系统必须在每次送盘、回盘、对账等文件动作中留存实际使用的协议、目录、文件路径与文件名,以便后续审计和问题追踪;本轮不强制留存配置版本号或完整配置快照。 +- **FR-010**: 当上层覆盖配置未完整定义所有目录时,系统必须对缺失项回退到下一级有效配置,而不是生成空值或错误拼接路径。 +- **FR-011**: 当当前协议缺少必要连接信息或未命中任何有效目录规则时,系统必须立即阻断当前文件动作并返回可诊断的配置错误结论,由调用方或运维后续处理。 +- **FR-012**: 正式文档必须同步说明该能力属于 `REV-008` / `SYS-009` 的实现增强,并明确其与真实银行文件解析、生产联调和运行态样本补证的边界关系。 +- **FR-013**: 正式文档必须同步说明文件传输凭据、协议选择和环境配置属于安全与部署约束的一部分,不得将敏感凭据写入正式文档或默认仓库配置样例。 +- **FR-014**: 验证工件必须覆盖默认规则、租户覆盖、通道覆盖、租户-通道覆盖、字段级回退、协议切换、非法变量失败和配置缺失失败等场景中的最小样本。 +- **FR-015**: 重要正式文档修改完成后,必须更新 `docs/design/00_Management/01_Project_Progress.md` 的变更记录;当本轮任务项达到可关闭状态时,必须更新 `docs/design/00_Management/03_Task_Checklist.md`。 +- **FR-016**: 变更完成后必须执行与改动范围匹配的最小校验,至少包括被修改正式文档的单文件校验;涉及链接或 Mermaid 变化时,必须补充对应校验。 + +### Key Entities *(include if feature involves data)* + +- **File Transfer Policy**: 描述协议、连接信息来源、目录规则与覆盖优先级的一组正式配置对象。 +- **Directory Resolution Context**: 一次文件动作在解析目录时使用的上下文信息,包含租户、机构、通道、业务类型(businessType)、文件阶段和业务日期等要素。 +- **Stage Directory Rule**: 面向送盘、回盘、对账、归档或本地临时目录的单阶段路径规则,可被默认规则或覆盖规则承接。 +- **Override Scope**: 用于表达默认、通道、租户和租户-通道四种不同粒度配置来源的作用域对象。 +- **Resolved File Location**: 某次具体文件动作最终得到的协议、目录和文件路径结果,用于执行与审计追溯。 +- **Verification Artifact**: 记录基线、验证步骤、验证结果和最终结论的工件文件。 + +## Success Criteria *(mandatory)* + +### Measurable Outcomes + +- **SC-001**: 评审人能够从规格与验证工件中明确识别 5 类文件阶段(送盘、回盘、对账、归档、本地临时)各自的目录承接规则。 +- **SC-002**: 至少 3 组不同作用域组合(默认、租户覆盖、通道覆盖或租户-通道覆盖)能够被独立验证,并得到不相同且可解释的解析结果。 +- **SC-003**: 协议从一种传输模式切换到另一种传输模式时,不需要修改业务代码即可完成后续执行路径选择。 +- **SC-004**: 验证工件能够独立说明目录解析优先级、缺省回退规则和配置缺失时的失败结论,评审人无需阅读源代码即可判断行为是否正确。 +- **SC-005**: 本轮产出的正式文档、基线工件、验证工件和台账记录全部可定位,且规格中不保留 `[NEEDS CLARIFICATION]` 标记。 diff --git a/specs/010-bank-transfer-config/tasks.md b/specs/010-bank-transfer-config/tasks.md new file mode 100644 index 0000000..3a29d6a --- /dev/null +++ b/specs/010-bank-transfer-config/tasks.md @@ -0,0 +1,210 @@ +# Tasks: sw-business-bank 银行代扣文件传输配置能力 + +**Input**: Design documents from `/specs/010-bank-transfer-config/` +**Prerequisites**: plan.md (required), spec.md (required), research.md, data-model.md, contracts/, quickstart.md + +**Validation**: Validation and evidence tasks are NOT optional. Every feature task set MUST include the applicable document validation, code validation, ledger-sync, and final-verdict tasks. + +**Organization**: Tasks are grouped by user story so each slice can be completed, reviewed, and validated independently. + +## Format: `[ID] [P?] [Story] Description` + +- **[P]**: Can run in parallel (different files, no dependencies) +- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3) +- Include exact file paths in descriptions + +## Path Conventions + +- Formal workflow: `water-docs/` +- Main documents: `docs/design/01_Overview/`, `docs/design/02_Detailed_Design/`, `docs/design/03_Technical_Design/` +- Governance documents: `docs/design/00_Management/` +- Feature artifacts: `specs/010-bank-transfer-config/` +- Backend modules: `../water-backend/...` +- Frontend modules: `../water-frontend/...` + +## Phase 1: Scope, Baseline & Source Confirmation + +**Purpose**: Confirm the source-of-truth set, repo boundary, governance prerequisites, and code baselines before editing anything. + +- [x] T001 Confirm target documents, target repos, clarified requirements, and exact chapter landing points from `specs/010-bank-transfer-config/spec.md` +- [x] T002 Read `docs/design/00_Management/01_Project_Progress.md`, `docs/design/00_Management/02_Delivery_Standards.md`, and `docs/design/00_Management/03_Task_Checklist.md` before any formal document edits +- [x] T003 Read `docs/design/00_Management/04_Writing_Guide.md`, `docs/design/00_Management/08_AI_Agent_Maintenance_SOP.md`, `docs/design/00_Management/10_AI_Retrieval_Whitelist.md`, and `docs/design/00_Management/11_Main_Doc_Chapter_Index.md` before structural updates in `docs/design/` +- [x] T004 Confirm governing source-of-truth documents, validation commands, and repo touchpoints from `specs/010-bank-transfer-config/plan.md` +- [x] T005 [P] Record backend baseline branch and commit in `specs/010-bank-transfer-config/baseline.md` +- [x] T006 [P] Map cross-document and cross-repo impacts in `specs/010-bank-transfer-config/research.md` and `specs/010-bank-transfer-config/data-model.md` + +--- + +## Phase 2: Shared Foundation + +**Purpose**: Establish the shared alignment baseline for docs, code evidence, and verification outputs. + +- [x] T007 Normalize terminology, scope priority, protocol vocabulary, and audit field naming in `specs/010-bank-transfer-config/plan.md` and `specs/010-bank-transfer-config/contracts/bank-transfer-resolution-contract.md` +- [x] T008 Confirm final validation command set and minimum scenario matrix in `specs/010-bank-transfer-config/quickstart.md` +- [x] T009 Create verification placeholders and expected evidence sections in `specs/010-bank-transfer-config/backend-validation.md`, `specs/010-bank-transfer-config/docs-validation.md`, and `specs/010-bank-transfer-config/final-verdict.md` +- [x] T010 [P] Inspect current backend landing files for implementation scope in `../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/service/bankwithholding/BankWithholdingServiceImpl.java`, `../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/dal/dataobject/withholdingbatch/WithholdingBatchDO.java`, `../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/dal/dataobject/reconcilebatch/ReconcileBatchDO.java`, and `../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/dal/dataobject/channelapiconfig/ChannelApiConfigExtParams.java` + +--- + +## Phase 3: User Story 1 - 配置外部化管理银行文件通道 (Priority: P1) 🎯 MVP + +**Goal**: 建立银行代扣文件传输的外部化配置边界,并把默认规则、通道覆盖、租户覆盖与目录字段合同回写到正式文档和 backend 配置模型中。 + +**Independent Test**: 评审人仅通过规格、合同、正式文档与配置模型,即可确认系统支持 `SFTP/FTP`、五类目录、四级作用域和固定变量白名单,且不需要阅读解析实现细节。 + +### Implementation for User Story 1 + +- [x] T011 [US1] Update `docs/design/02_Detailed_Design/12_REV_Detailed.md` to describe `REV-008` file transfer configuration scopes, stage directories, and fixed template variable rules +- [x] T012 [US1] Update `docs/design/03_Technical_Design/04_Security_Design.md` to define protocol selection, credential reference rules, and secret-handling constraints for bank file transfer config +- [x] T013 [US1] Update `docs/design/03_Technical_Design/05_Deployment_Design.md` to document Spring profile + Nacos default config loading, channel override source, and environment responsibilities +- [x] T014 [P] [US1] Refine config contract details in `specs/010-bank-transfer-config/contracts/bank-transfer-config-contract.md` and scope/entity alignment in `specs/010-bank-transfer-config/data-model.md` +- [x] T015 [US1] Extend `../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/dal/dataobject/channelapiconfig/ChannelApiConfigExtParams.java` to carry file transfer protocol, connection fields, stage directories, scope type, and tenant-specific override fields +- [x] T016 [US1] Update `../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/dal/dataobject/channelapiconfig/ChannelApiConfigDO.java` and `../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/dal/type/ChannelApiConfigExtParamsTypeHandler.java` to support a dedicated file-transfer `apiType` and persistence of the new extParams structure +- [x] T017 [US1] Record story-specific document validation results for config-boundary docs in `specs/010-bank-transfer-config/docs-validation.md` +- [x] T018 [US1] Record backend configuration-model evidence and baseline notes in `specs/010-bank-transfer-config/backend-validation.md` + +**Checkpoint**: User Story 1 is independently reviewable with both document and configuration-model evidence aligned. + +--- + +## Phase 4: User Story 2 - 运行时统一解析路径与协议 (Priority: P2) + +**Goal**: 为送盘、回盘、对账建立统一的文件传输解析入口,支持协议切换、作用域优先级、字段级回退、失败阻断与审计结果落库。 + +**Independent Test**: 通过自动化验证与批次对象落值结果,可独立确认默认规则、租户覆盖、通道覆盖、租户-通道覆盖、协议切换、非法变量失败与配置缺失失败行为全部符合 spec。 + +### Implementation for User Story 2 + +- [x] T019 [US2] Update `docs/design/03_Technical_Design/03_Interface_Design.md` to document runtime resolution priority, failure behavior, and audit outputs for file exchange actions +- [x] T020 [P] [US2] Sync resolution rules and audit expectations in `specs/010-bank-transfer-config/contracts/bank-transfer-resolution-contract.md` and `specs/010-bank-transfer-config/quickstart.md` +- [x] T021 [US2] Add file transfer properties, enums, context, and resolver classes under `../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/config/filetransfer/` and `../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/service/filetransfer/` +- [x] T022 [US2] Align 业务类型(`businessType`) handling across `specs/010-bank-transfer-config/data-model.md`, `specs/010-bank-transfer-config/contracts/bank-transfer-resolution-contract.md`, and `../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/service/filetransfer/` resolution context definitions +- [x] T023 [US2] Refactor `../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/service/bankwithholding/BankWithholdingServiceImpl.java` to consume unified resolved protocol/dir/path results instead of hardcoded send/back/reconcile path builders +- [x] T024 [US2] Implement `ARCHIVE` and `LOCAL_TEMP` stage resolution support under `../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/service/filetransfer/` +- [x] T025 [US2] Extend `../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/dal/dataobject/withholdingbatch/WithholdingBatchDO.java` and `../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/dal/dataobject/reconcilebatch/ReconcileBatchDO.java` to persist final protocol and directory audit fields together with resolved paths +- [x] T026 [US2] Update `../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/dal/mysql/withholdingbatch/WithholdingBatchMapper.java` and `../water-backend/sw-business-bank/sw-business-bank-server/src/main/java/cn/com/emsoft/sw/bankbusiness/dal/mysql/reconcilebatch/ReconcileBatchMapper.java` when newly added DO audit fields are not automatically persisted by the existing mapper definitions +- [x] T027 [P] [US2] Create resolver-focused tests in `../water-backend/sw-business-bank/sw-business-bank-server/src/test/java/cn/com/emsoft/sw/bankbusiness/service/filetransfer/BankTransferPathResolverTest.java` +- [x] T028 [P] [US2] Add `ARCHIVE` and `LOCAL_TEMP` stage coverage to `../water-backend/sw-business-bank/sw-business-bank-server/src/test/java/cn/com/emsoft/sw/bankbusiness/service/filetransfer/BankTransferPathResolverTest.java` +- [x] T029 [P] [US2] Add invalid-template-variable failure cases to `../water-backend/sw-business-bank/sw-business-bank-server/src/test/java/cn/com/emsoft/sw/bankbusiness/service/filetransfer/BankTransferPathResolverTest.java` +- [x] T030 [P] [US2] Create integration-oriented service tests in `../water-backend/sw-business-bank/sw-business-bank-server/src/test/java/cn/com/emsoft/sw/bankbusiness/service/bankwithholding/BankWithholdingTransferConfigTest.java` +- [x] T031 [US2] Add persisted-batch config-switch regression cases to `../water-backend/sw-business-bank/sw-business-bank-server/src/test/java/cn/com/emsoft/sw/bankbusiness/service/bankwithholding/BankWithholdingTransferConfigTest.java` +- [x] T032 [US2] Check whether `../water-backend/sw-business-bank/sw-business-bank-server/src/test/resources/application-unit-test.yaml` and `../water-backend/sw-business-bank/sw-business-bank-server/src/test/resources/sql/create_tables.sql` already support withholding/reconcile test coverage and new audit fields; update them if the new tests cannot run against the current fixtures +- [x] T033 [US2] Run story-specific backend validation commands and capture compile/test results in `specs/010-bank-transfer-config/backend-validation.md` + +**Checkpoint**: User Story 2 is independently reviewable and validated. + +--- + +## Phase 5: User Story 3 - 形成可审计的文档与验证闭环 (Priority: P3) + +**Goal**: 形成正式文档、治理台账、基线工件和最终 verdict 的一致闭环,使本轮增强能力可追溯、可评审、可归档。 + +**Independent Test**: 仅检查正式文档、台账和 `specs/010-bank-transfer-config/` 下工件,即可确认范围、基线、验证结果、剩余 deferred 项和后续建议全部齐备。 + +### Implementation for User Story 3 + +- [x] T034 [US3] Update `docs/design/00_Management/01_Project_Progress.md` with this feature’s scope, baseline, minimum validation results, and remaining deferred items +- [x] T035 [US3] Update `docs/design/00_Management/03_Task_Checklist.md` to reflect the closure state for this feature’s planning and implementation checkpoints +- [x] T036 [US3] Finalize `specs/010-bank-transfer-config/baseline.md` with backend branch, commit, inspected code paths, and source-of-truth references +- [x] T037 [US3] Finalize `specs/010-bank-transfer-config/docs-validation.md` with document command results and impacted-file notes +- [x] T038 [US3] Finalize `specs/010-bank-transfer-config/backend-validation.md` with separate evidence sections for default rule, tenant override, channel override, tenant-channel override, field-level fallback, protocol switch, invalid-template-variable failure, config-missing failure, and persisted-batch config-switch regression +- [x] T039 [US3] Prepare `specs/010-bank-transfer-config/final-verdict.md` with outcome summary, delivered scope, deferred scope, risks, and recommended next actions +- [x] T040 [US3] Run story-specific document validation for `docs/design/02_Detailed_Design/12_REV_Detailed.md`, `docs/design/03_Technical_Design/03_Interface_Design.md`, `docs/design/03_Technical_Design/04_Security_Design.md`, `docs/design/03_Technical_Design/05_Deployment_Design.md`, `docs/design/00_Management/01_Project_Progress.md`, and `docs/design/00_Management/03_Task_Checklist.md`, then capture results in `specs/010-bank-transfer-config/docs-validation.md` + +**Checkpoint**: All planned updates are independently reviewable and validated. + +--- + +## Final Phase: Verification & Closure + +**Purpose**: Ensure repository-wide consistency, baseline traceability, and final verdict output. + +- [x] T041 [P] Re-check source-of-truth alignment across `specs/010-bank-transfer-config/spec.md`, `specs/010-bank-transfer-config/plan.md`, `specs/010-bank-transfer-config/tasks.md`, and all modified formal documents +- [x] T042 [P] Re-check relative links, stable anchors, and Mermaid consistency across modified files in `docs/design/` and `specs/010-bank-transfer-config/` +- [x] T043 [P] Re-check backend baseline SHA, compile/test outputs, and evidence completeness in `specs/010-bank-transfer-config/baseline.md` and `specs/010-bank-transfer-config/backend-validation.md` +- [x] T044 [P] Run `make validate-mermaid` and capture results in `specs/010-bank-transfer-config/docs-validation.md` if any Mermaid diagrams are added or modified in `docs/design/`; if no Mermaid diagrams are changed, record `N/A` with a brief reason in `specs/010-bank-transfer-config/docs-validation.md` +- [x] T045 Prepare final closure summary and verdict sign-off in `specs/010-bank-transfer-config/final-verdict.md` + +--- + +## Dependencies & Execution Order + +### Phase Dependencies + +- **Phase 1: Scope, Baseline & Source Confirmation**: No dependencies; MUST finish before edits +- **Phase 2: Shared Foundation**: Depends on Phase 1 and MUST finish before story execution +- **Phase 3: User Story 1**: Depends on Phase 2 and is the MVP slice +- **Phase 4: User Story 2**: Depends on User Story 1 config model/contract completion +- **Phase 5: User Story 3**: Depends on User Story 1 and User Story 2 evidence being available +- **Final Phase**: Depends on all selected user stories being complete + +### Within Each User Story + +- Complete formal/contract updates before validation capture +- Complete backend model or resolver work before service integration and tests +- Complete code/test validation before ledger closure and final verdict updates +- Record evidence before marking closure tasks done + +### Parallel Opportunities + +- `T005` and `T006` can run in parallel once the feature scope is confirmed +- `T014` can run in parallel with `T015`-`T016` after User Story 1 document intent is fixed +- `T020` can run in parallel with `T021` after User Story 2 contract shape is confirmed +- `T027`-`T030` can run in parallel after resolver and service integration points are stable +- `T041`, `T042`, `T043`, and `T044` can run in parallel during final closure + +## Parallel Execution Examples + +### User Story 1 + +```bash +# Parallel after config boundary is agreed +Task: T014 Refine contracts/data-model +Task: T015 Extend ChannelApiConfigExtParams +Task: T016 Update DO/type handler persistence +``` + +### User Story 2 + +```bash +# Parallel after resolver design is fixed +Task: T027 Create BankTransferPathResolverTest +Task: T028 Add ARCHIVE and LOCAL_TEMP coverage +Task: T029 Add invalid-template-variable failure cases +Task: T030 Create BankWithholdingTransferConfigTest +Task: T031 Add persisted-batch config-switch regression cases +Task: T032 Check and update test fixtures +``` + +### Final Closure + +```bash +# Parallel final checks +Task: T041 Re-check source-of-truth alignment +Task: T042 Re-check links and Mermaid consistency +Task: T043 Re-check backend baseline and validation completeness +Task: T044 Run conditional Mermaid validation +``` + +## Implementation Strategy + +### MVP First + +1. Finish Phase 1 and Phase 2 to lock source-of-truth, baseline, validation plan, and evidence targets +2. Deliver **User Story 1** first as the MVP: formalize configuration scopes, fixed variables, and backend config carrier +3. Deliver **User Story 2** next: implement unified runtime resolution, audit persistence, and automated tests +4. Deliver **User Story 3** last: close governance, evidence, and verdict artifacts + +### Incremental Delivery + +- After **US1**, reviewers can confirm whether the configuration model and formal doc scope are acceptable +- After **US2**, reviewers can confirm runtime behavior and backend evidence independently +- After **US3**, the feature is ready for governance review and handoff + +## Notes + +- Every task set MUST preserve the single-source-of-truth model in `water-docs` +- Archive is for verification and traceability, not direct formal output replacement +- `../water-backend/` consumes and evidences the official spec; it does not replace formal docs +- Validation, evidence, baseline, and ledger tasks are mandatory for this feature +- Frontend is out of scope unless the user explicitly expands repository scope