diff --git a/.trellis/tasks/09-09-existing-deploy-seed-separation/design.md b/.trellis/tasks/09-09-existing-deploy-seed-separation/design.md index 7379c711..358267d3 100644 --- a/.trellis/tasks/09-09-existing-deploy-seed-separation/design.md +++ b/.trellis/tasks/09-09-existing-deploy-seed-separation/design.md @@ -48,6 +48,18 @@ ## 审批边界 +### 新候选发布准备草案(提交后,未授权部署) + +- 候选固定为 b87cc55aca0003130cf8a5bbe38d0dd15528389c,已推远端。执行来源为干净的 seed-preflight-integration 副本,不使用仍在旧基线且有其他治理差异的主工作树。此前候选和例外不自动转移。 +- 本地已有证据:已审两包、顺序补丁集成与 110/110 定向回归。尚无完整镜像构建或完整候选门禁通过证据;不将定向回归冒充普通发布资格,不自动启动暂停的 R1、阶段 B 或修复 58 条红项。 +- 下一步申请本候选的一次生产只读预检:运行版本/镜像身份、候选迁移集合与数据库迁移状态、三类 enabled/active 最低配置计数、磁盘余量、最近备份时效及已有回滚制品元数据。只输出脱敏摘要;不读取个人访问历史、单据明细或银行信息,不执行 migrate/seed,不写配置,不切容器。现有审批记录不替代本轮明确边界。 +- 预检必须执行已修的状态解析逻辑;如远端仍为旧脚本,应先设计获准的调用方式,不以“只读”名义自行上传或安装文件。读取受限则标未验证,不绕权限。 +- 回滚目标以本轮确认的生产运行版本为准,不默认仍是历史 f223bfb。旧镜像必须保持独立可用;备份完整性与恢复能力分别记录。已知 DB 最小恢复成功不代表附件或应用恢复成功,也不证明新备份已恢复演练;不沿用历史“从未成功”的过期结论。 +- 若最低配置缺失,报告管理员,不自动 seed/启用配置。existing 仍会执行迁移,配置检查失败可能发生在迁移落库之后,镜像回滚不能撤销数据变化;任何数据恢复还涉及恢复点之后业务数据的处置,另行审批。 +- 汇总本轮证据后再提交发布决定:普通路径需要完整候选验收;若仍未具备,明确列出缺口与回滚验收,用户对本 SHA 单独批准例外和部署。未获批准不执行真实发布,不拿旧例外填空。 +- 部署获批后按既有 existing 路径执行,检查日志无 seed 阶段、版本/健康一致;AP 验收覆盖仅 ceo/manager 拒绝、finance/finance_mgr 可读、兼财务多角色可读、审批/复核入口保留。真人制单/付款流程由授权人员验收,下载不等于付款;不代操作真实银行业务。 +- 失败停止并报告,不自动扩大写入或恢复范围;成功也不删除独立回滚制品。磁盘治理、恢复附件/应用验证、统一待办和错误豁免期限沿原任务处理,不混进本次发布写入。 + 用户已同意本 task 规划方向;以上统一入口、直接调用显式模式和三类非空硬门禁为本轮收敛的待审实施方案。获批前保持 planning;不把此前“好的”解释成批准尚未呈现的兼容变化。实施只在独立工作树,不叠加未提交的治理修复。提交、推送、生产部署另批。 后续授权与实施:用户对收敛方案明确回复“是”,已进入独立工作树实施。共享入口为 server/src/scripts/deploy-init.js。只读检查通过 Prisma repeatable-read 事务显式 SET TRANSACTION READ ONLY;费用类型没有专用管理页面,改为提示管理员核对既有 /api/expense-types,缺失数据另批修复,不新增 UI。 diff --git a/.trellis/tasks/09-09-existing-deploy-seed-separation/implement.md b/.trellis/tasks/09-09-existing-deploy-seed-separation/implement.md index c346ca5e..b9696dac 100644 --- a/.trellis/tasks/09-09-existing-deploy-seed-separation/implement.md +++ b/.trellis/tasks/09-09-existing-deploy-seed-separation/implement.md @@ -82,3 +82,79 @@ - 预检缺陷定性是“该拦时可能拦不住”,未证明生产曾误放行。独立审查在其环境较大输出触发 141,但约 64KB 不是通用安全阈值;此前已有短输出捕获 producer=141/consumer=0 的记录,调度和管道实现都会影响触发,不采纳“日常绝不会触发”的推断。 两笔提交准备顺序:先 preflight(门禁 task 三文档、预检脚本、测试及 spec 对应增量),再 seed(原 17 文件范围,包含 F1/F2 手册补充和 seed task 最新状态;spec 只取 seed 增量)。共享 spec 第二笔以第一笔结果为基线。提交、推送、完整候选门禁与部署均未因此授权;当前只做隔离集成和定向验证。 +## 本轮提交推送回执 + +用户明确授权按清单两笔提交并推送,不含部署。已在隔离集成副本完成: +- 81102c2:迁移预检修复,6 文件,归 09-06-release-gate-integrity。 +- b87cc55aca0003130cf8a5bbe38d0dd15528389c:日常发布与首次初始化分离,17 文件,归 09-09-existing-deploy-seed-separation。 +逐笔暂存内容按已批准补丁、路径集合和文件摘要核验;没有纳入其他治理改动。推送后 fetch 回读:集成副本 HEAD = origin/main = b87cc55,副本工作树干净。原冻结包保留;未新建分支、未归档 task、未部署或查询生产。 +主工作树仍在 b918530,保留原有未提交治理差异及任务状态补记,没有强行快进覆盖它们。后续候选检查必须在隔离集成副本或新建干净候选副本执行,不能用主工作树 HEAD 冒充新候选。 +验证沿用同字节输入的集成 110/110;源码包独立复核通过,集成由主会话验证,完整候选门禁尚未执行。当前段落为提交后的本地回执,不倒改提交前冻结材料;不为状态补记另造第三笔提交。下一步按 seed design 的新候选发布准备草案核对前置,生产只读预检与部署不在本次 Git 授权内。 +## 新候选生产只读预检回执(2026-09-09) + +用户在提交推送后批准本候选只读预检。本次在内存经 SSH stdin 执行已提交的新预检脚本,没有上传安装、修改远端文件、执行 migrate/seed、切换容器或业务写入。执行脚本摘要 2386ac545d8d12595c61fbcdb5e807746965a36ce539170cc6118f3eb6f15d2e,与 b87cc55 候选一致;原始身份字段只在内存传递,输出为既有脱敏摘要。 + +观测时间 2026-09-09 12:54 CST: +- 候选 b87cc55;生产运行 build f223bfb72fb2baef51199702c2def84c41af7aef,容器运行中且检查前后身份/启动时间不变。Docker 未提供 Health 状态,未据此声明公网健康通过。 +- 目标/数据库身份及迁移对账 PASS,无待执行迁移。脚本 rollbackWindow=OPEN 仅是既有 terminated 状态计数检查,不是备份可恢复或完整回滚演练结论。 +- 三类最低配置在明确 READ ONLY 事务内读取:启用费用类型 39、启用审批规则 3、活动报销流程 1,全部满足本候选最低非空门禁;没有读取员工或业务明细。 +- 数据/附件/回滚制品所在文件系统可用 8.32 GiB、使用率 85.9%。不能据此单独保证镜像构建和备份峰值空间够用,未清理任何文件。 +- 最新备份状态文件 ACCESS_DENIED,不能确认其完成时间、制品身份或摘要。备份 service 最后退出时间为本日 02:30:53 CST、Result=success/exit=0;这只是服务元数据,不能替代备份验真,不绕权限升级读取。 +- 独立旧镜像文件仍存在,匹配当前生产 build/image,大小 1117595648 字节与旧 receipt 一致;只核元数据,未重算 archive SHA-256、未 docker load 或恢复测试,不把旧 receipt 中的摘要冒充本轮实测。 + +证据入口:artifacts/qa-flow/20260909-b87cc55-readonly/,含只读脚本、preflight-result.json、metadata-result.json 与脱敏 migration 输出。候选副本仍干净,未提交额外代码、未推送、未部署。当前仅完成只读预检,不产生发布资格。 + +下一步:先通过获准管理员读取路径补最新备份的时效/manifest/数据库包和附件包完整性验证;在发布前另外核算构建峰值空间、确认回滚制品验收范围。读权限缺口不以自动 sudo、切 root 或宣称服务成功代替。材料齐后对本 SHA 明列完整候选门禁未通过等缺口,再请用户决定例外及部署;当前不建议直接发布。不重复要求已完成的数据库最小恢复演练,也不把它扩为附件/应用恢复成功。 +## 获准 root 通道备份验真与空间盘点(2026-09-09) + +用户明确允许 hyinda-root 执行只读备份验真,并询问发布空间及旧部署内容清理。本轮经该既有 SSH 身份内存执行检查;未自动 sudo、上传安装、恢复数据、删除文件或部署。已有管理员备份校验脚本沿用严格的 f223bfb/build/image 约束,未放宽失败条件。 + +最新备份 PASS_INTEGRITY_ONLY:完成于 2026-09-09 02:30:53 CST,检查时约 10.48 小时;manifest 摘要、数据库 dump 和附件归档大小/摘要全部一致。验证的是当前备份完整性,本轮未恢复;此前 DB 最小恢复成功不因此扩为附件或应用恢复成功。 + +磁盘约 58.94 GiB,可用 8.32 GiB,使用率 85.9%,可用 inode 1400857。Docker system df:Images 39.54GB、标称可回收 39.24GB;停止容器标称约 190MB;构建缓存约 268MB。目录 allocated 统计:日志约 1.019 GiB、独立回滚制品约 1.041 GiB、自动备份 0.132 GiB、数据库 0.092 GiB、附件 0.018 GiB、部署仓库 0.028 GiB;目录可能重叠,不相加。Docker store 的 du 超时记 NOT_MEASURED,不当作零占用。image ls -a 含中间镜像,与 system df 汇总计数口径不同,不相加或冒充同一分母。 + +已生成只读清理候选清单:845 个创建至少 7 天、无 tag/digest、未被任何运行或停止容器引用且排除已固定生产回滚镜像的镜像。清单 SHA256=30d78bac23658f70453e5cc8a6d2e9c943c32c0ab48227e605efa3abb8e6438e。共享层与中间镜像依赖使实际可释放字节未知,不能承诺释放 Docker 标称全部 39.24GB。这是候选清单,不是用户已授权删除。 + +建议先做这批精确清单的受控清理,不直接部署:8.32 GiB 不能证明构建峰值够用,候选 server/package.json 变化会失效 server_deps 的依赖安装缓存。若用户另批清理,每项删除前必须重新核对年龄/标签/digest/容器引用/受保护镜像;引用变化、存在后继依赖或条件不符则跳过报告,不强制删除。不执行 system prune -a/--volumes,不删除任何容器、卷、数据库、附件、备份、独立回滚制品或带标签镜像。清理前后核对运行镜像/启动时间及磁盘,剩余空间再用于发布预算判断;未达余量不扩大清理范围。 + +证据位于 artifacts/qa-flow/20260909-b87cc55-readonly/:backup-integrity-result.json、disk-inventory-result.json、image-cleanup-candidates-result.json 及本轮只读脚本。下一步请用户批准上述精确范围的删除;本轮只读授权不包含清理或部署。原备份 ACCESS_DENIED 已由本次获准 root 完整性检查补齐,不能继续写作验不了。 +## 已授权镜像清理结果(2026-09-09) + +用户对“仅清理已列明 845 项、逐项复核、不强删、不动容器/卷/业务数据/备份/回滚制品”回复“是”,本轮据此执行。没有将权限扩大为全局 prune、删除带标签镜像或部署。 + +通过获准 hyinda-root 的 SSH stdin 执行本地检查脚本,未远端安装脚本。每项操作前复核全部容器 ID/镜像/状态/启动时间不变,重新检查镜像无 tag/digest、年龄至少七天、与冻结创建时间一致,排除所有容器引用和已固定回滚镜像。唯一删除命令为 docker image rm --no-prune <完整批准ID>,不用 force;--no-prune 防止隐式继续删除清单外父镜像。Docker 拒绝的依赖项保留,不改依赖关系、不重新扩大范围。 + +2026-09-09 13:11 CST 结束: +- 845 个批准 ID 全部逐项处理,811 删除成功,34 SKIPPED_DOCKER_REFUSED;本地逐事件核对 ID 集合与批准清单完全相等,无重复或额外项。 +- 可用空间 8.32 → 46.43 GiB,净增加 38.11 GiB。此为文件系统实测净变化,不是把镜像虚拟大小相加。空间薄余量问题本次已解除,不继续清理备份或回滚制品来凑空间;具体构建峰值仍未实测,不承诺任意后续构建永不耗尽。 +- 全部运行/停止容器的 ID、镜像、状态、启动时间在清理前后保持一致;Docker volume 名单不变,没有执行容器/卷删除或业务数据写入。 +- 独立回滚归档在清理前后完整 SHA256 都与原保存回执匹配,本轮已重新验摘要;没有 docker load/恢复演练,不能把此写成恢复成功。 +- 真实生产版本未切换,未部署、未提交额外代码、未推送,未删除任何备份或审计日志。 + +证据:artifacts/qa-flow/20260909-b87cc55-readonly/cleanup-result.json、cleanup-execution-events.jsonl、cleanup-approved-images.py。脚本 SHA256=748c2d11e92ed5373969418410bfd83a5cc86fe16f3099e683879b75311a6895;原批准清单 SHA256=30d78bac23658f70453e5cc8a6d2e9c943c32c0ab48227e605efa3abb8e6438e。34 项保留不是重新索要强删授权的理由。 + +### 下一步:新候选发布审批,不再追加空间清理 + +候选仍是 b87cc55。已有:独立源码复核、集成 110/110、本候选生产身份/迁移只读预检(无 pending)、39/3/1 最低配置、最新备份 manifest/数据库/附件完整性、独立旧镜像完整性及 46.43 GiB 余量。生产仍处于旧候选,Git 推送和清理授权均不是部署授权。 +尚缺完整候选门禁通过;真实候选镜像尚未构建,附件/应用恢复未演练。原数据库最小恢复已成功,不能继续表述为“从未成功恢复”;镜像回滚不能撤销迁移等数据库写入,恢复备份会影响恢复点后的数据。应据这些明确缺口对本 SHA 提交发布例外及部署审批,获批后才执行 existing 发布与版本/健康/AP权限验收;不沿用旧 AP 候选的例外授权。直到该批准到来,保留原回滚制品、34 个被拒绝镜像及业务数据不动。 +## 本候选例外与部署授权 + +用户对明确列出的 b87cc55 发布例外、existing 部署及必要的旧版本应用回滚回复“是”。接受完整候选验收未通过/真实镜像尚未构建/附件与应用恢复未演练;不授权自动数据库恢复或删除回滚制品。本次使用远端 main 的干净克隆作为发布源(原集成副本 detached 不满足 upstream 门禁,不设置未发布 override);固定 b87cc55,来源检查 published/remoteVerified=true。Trellis start 写入本克隆 task branch 元数据后,已只恢复该自动改动到候选原字节,保留会话指针;未改变候选代码或新建功能分支。 + +执行证据归 artifacts/qa-flow/20260909-release-b87cc55/。沿既有 deploy-existing.sh 调用链,固定 existing/SYNC_ENV=0,使用原受控 refresh 身份,不运行初始化 seed;任何失败停止,应用是否已切换以阶段与运行版本实测为准。准备阶段尚不代表部署成功。 +## 已按本候选例外完成部署(2026-09-09) + +用户明确批准 b87cc55 的例外、existing 发布及必要旧应用回滚,不授权自动数据库恢复。14:07 CST 既有 deploy-existing.sh 返回 0:build-init、run-init、build-server、build-switch-server 均 PASS;随后迁移对账、就绪/依赖/runtime smoke、公网构建标识及前端 bundle 检查和受控备份合同 refresh 完成。没有使用未发布 override,没有执行回滚。独立 clone main=origin/main=b87cc55 是本次发布来源,主工作树仍保留原未提交治理改动,不据主工作树旧 HEAD 判断生产版本。 + +部署后复核: +- 正式运行 build=b87cc55aca0003130cf8a5bbe38d0dd15528389c;14:08 CST 单独公网 /ready 与首页 HTTP 200,/ready buildSha=b87cc55aca00。 +- init 日志的阶段精确为 validate_config → migrate → check_required_configuration,INIT_PASS/existing,无 seed 阶段;发布前后迁移对账无 pending。 +- 运行容器内权限常量、AP 路由、workspaceSettings、auth 插件及 deploy-init 五文件摘要与候选完全一致。直接调用运行镜像中的权限解析器:manager/ceo 不获 finance.ledger.view,finance/finance_mgr 及兼财务角色可读,admin 通配保留;manager/ceo 的 expense.approve 和 payment.batch.review 保留。 +- 上一项是部署制品字节核验和运行时代码策略执行,不是使用真人会话请求 AP 接口或实际点击菜单。本轮没有伪造真人 token、登录真实账户或读取台账明细;authenticated account route test / real-user page acceptance 均 NOT_RUN,不冒充四项真人验收全通过。 +- 系统已发布且公网可测试,但经理/CEO 仍可经既有报销列表查看全部报销的开口保留,本轮仅收窄 AP,不宣称“经理只能看所有相关单据”整体实现。 +- 发布后可用空间 45.50 GiB;旧备份、独立旧镜像制品及 34 个 Docker 拒绝删除项仍保留,未追加清理。backup unit BUILD_SHA 已刷新为新版本;最新已验备份仍是发布前 f223bfb,不把合同刷新写作新版本备份已产出。 +- 例外缺口仍保留:完整候选验收没有通过证据;本次真实镜像构建现已通过,不能继续列为未构建;附件与应用恢复尚未演练,镜像回滚不撤销数据库写入。数据库最小恢复历史成功不等于任意当前备份均已演练恢复。 + +证据归 artifacts/qa-flow/20260909-release-b87cc55/:deployment-result.json、postcheck-result.json、public-check.json、脱敏迁移回执;完整发布输出为受控 0600 日志,不回传原始环境/业务内容。主会话执行发布及验证,不伪称独立 reviewer 验证部署集成。此次状态补记未另行提交或推送,不归档整个门禁 task,不启动 R1/阶段 B 或修 58 条。 + +下一步回到业务验收:majianyong 本人确认 AP 台账入口不可用、原审批/付款复核入口可用;财务本人确认 AP 可读和已复核批次可下载银行制单。仅让用户验证自己的授权界面,不代付、不代批、不创建额外测试付款。实际付款仍是复核 → 制单 → 网银付款 → 回单登记,下载成功不等于付款成功。取得真人交接证据后按已排队的统一待办任务收敛下一阶段方案,不让等待验收自动变成另起一笔未批准功能改动。