feat(web): tighten portal privacy and cleanup flows
Some checks failed
CI / pytest (Python 3.10) (push) Has been cancelled
CI / pytest (Python 3.11) (push) Has been cancelled
CI / pytest (Python 3.12) (push) Has been cancelled

This commit is contained in:
Hermes Agent
2026-06-15 21:24:55 +08:00
parent 69b74241ae
commit c03ed7a4ba
31 changed files with 1523 additions and 125 deletions

View File

@@ -0,0 +1,237 @@
# 本轮完成项摘要报告2026-06-15
## 1. 目标
本轮工作围绕 2026-06-15 系统复审报告中的 P1 / P2 整改项展开,目标是优先收口仓库内可以真实落地并可验证的风险,而不是继续停留在“文档承诺”或“计划状态”。
本轮特别聚焦四类问题:
1. portal 公开面敏感信息暴露
2. 删除 / 匿名化链路中的文件残留
3. 支付与通知域中的残留死语义
4. 隐私 / 删除入口与目标机恢复验收准备不足
## 2. 已完成项
### 2.1 Portal 通知审计页不再暴露原始 payload
已修改:
- `admin/routes/web_public.py`
- `admin/tests/test_notification_audit_page.py`
结果:
- portal 通知页不再直出 `payload_json`
- 不再向持 token 用户暴露邮箱、报告绝对路径、PDF 路径
- 页面仅保留通知摘要字段
### 2.2 删除 / 匿名化链路补齐 portal 上传附件清理
已修改:
- `data/orders/deletion_service.py`
- `admin/tests/test_order_deletion.py`
结果:
- `delete` 会删除 portal 上传附件
- `anonymize` 也会清理 portal 上传附件
- 空附件目录会一起删除
- 数据库 payload 仍会被清空
### 2.3 通知域移除 `sent` 旧语义
已修改:
- `data/notifications/email_service.py`
- `tests/test_delivery_notification.py`
结果:
- `DELIVERY_EVENT_STATUSES` 已移除 `sent`
- `mark_sent()` 已删除
- 测试切换为 `validated / delivered / failed`
### 2.4 支付域移除 `refund_pending` 死状态
已修改:
- `data/payments/dao.py`
- `data/payments/service.py`
- `admin/routes/web_public.py`
- `data/payments/tests/test_refund_flow.py`
结果:
- payment schema 不再包含 `refund_pending`
- portal 状态推导不再依赖 `refund_pending`
- 退款路径统一为真实可达的 `refunded`
### 2.5 支付回调补齐仓库内可落地的商户维度校验
已修改:
- `admin/config.py`
- `data/payments/provider_requirements.py`
- `data/payments/service.py`
- `data/payments/providers/alipay.py`
- `admin/routes/web_public.py`
- `admin/tests/test_payment_alipay_notify.py`
- `data/payments/tests/test_provider_requirements.py`
- `data/payments/tests/test_provider_alipay.py`
- `data/payments/tests/test_webhook.py`
结果:
- 新增 `GAOKAO_PAYMENT_MERCHANT_ID`
- readiness 检查要求 merchant 维度
- webhook 归一化 payload 新增 `merchant_id`
- webhook 处理新增 merchant missing / mismatch 校验
说明:
- 这只完成仓库内能力补齐
- 真实公网 acceptance 仍需外部商户凭据、notify 域名和目标环境
### 2.6 测试子进程调用改为 hermetic
已修改:
- `tests/test_retention_cleanup.py`
- `tests/test_delivery_dispatcher.py`
- `tests/test_t5_performance.py`
结果:
- 子进程 `python3` 调用改为 `sys.executable`
- Locust 调用改为 `python -m locust`
- 直接 `./.venv/bin/python -m pytest ...` 不再因 PATH 分裂失败
### 2.7 隐私 / 删除前台入口与后台审计页已补齐
已修改:
- `admin/routes/web_public.py`
- `admin/routes/notifications.py`
- `admin/config.py`
- `admin/tests/conftest.py`
- `admin/tests/test_web_public.py`
- `admin/tests/test_order_info_form.py`
- `admin/tests/test_notifications_admin.py`
结果:
新增公开页面:
- `/privacy`
- `/service-terms`
- `/deletion-policy`
新增 portal 删除申请最小闭环:
- `GET /portal/{token}/deletion-request`
- `POST /portal/{token}/deletion-request`
新增留痕与后台审计:
- `GAOKAO_DELETION_REQUEST_LOG`
- `GET /api/admin/notifications/deletion-requests`
- `GET /admin/deletion-requests`
### 2.8 目标机恢复验收准备已落成可执行模板
已修改:
- `reports/DR_DRILL_TEMPLATE.md`
- `tests/test_backup_workflow.py`
- `docs/BACKUP_AND_RECOVERY_PLAN.md`
结果:
- 新增 DR drill 模板,可记录目标主机 / 异机恢复结果
- 测试锁定模板必须引用 `backup_verify.sh --from-backup`
- 文档已明确真实演练记录归档位置
### 2.9 文档边界同步收口
已修改:
- `docs/CURRENT_STATE.md`
- `docs/DELIVERY_RETENTION_OPS_RUNBOOK.md`
- `docs/BACKUP_AND_RECOVERY_PLAN.md`
- `docker-compose.yml`
结果:
- codecov 改为“同值展示口径”,不再误写成执行单源
- `sent` / `refund_pending` 旧口径已移除或修正
- Compose 文件头已明确其仅是开发 / 本地 smoke 模板
- backup 文档不再伪装目标机告警已经完成
## 3. 验证结果
### 3.1 针对性测试
执行过的关键针对性回归包括:
- `admin/tests/test_notification_audit_page.py`
- `admin/tests/test_order_deletion.py`
- `tests/test_delivery_notification.py`
- `data/payments/tests/test_provider_requirements.py`
- `data/payments/tests/test_provider_alipay.py`
- `data/payments/tests/test_webhook.py`
- `admin/tests/test_payment_alipay_notify.py`
- `data/payments/tests/test_refund_flow.py`
- `data/payments/tests/test_service.py`
- `tests/test_retention_cleanup.py`
- `tests/test_delivery_dispatcher.py`
- `tests/test_t5_performance.py`
- `tests/test_backup_workflow.py`
- `admin/tests/test_web_public.py`
- `admin/tests/test_order_info_form.py`
- `admin/tests/test_notifications_admin.py`
其中最后一次定向回归结果:
- `23 passed`
### 3.2 标准验证入口
执行:
```bash
bash scripts/dev-verify.sh --skip-install
```
结果:
- `730 passed`
- `coverage overall = 92.70%`
- `coverage core = 100.00%`
- `ruff` 通过
- `mypy` 无错误
## 4. 本轮未在仓库内伪完成的外部阻塞
以下事项仍依赖仓库外条件,本轮没有伪装为“已完成”:
1. 真实支付宝公网 acceptance
- 仍需真实商户凭据、公网 `notify_url`、真实域名和线上演练记录
2. 目标机真实 backup / restore 演练
- 当前只完成模板与准备,不代表目标机已跑过
3. 目标机真实 SMTP / webhook 告警联调
- 当前仓库只保留真实边界说明,没有伪造不存在的 backup alert service
4. 正式法务文本最终签发
- 当前仓库已补入口与流程,但不等于外部法务审批流程已经结束
## 5. 结论
本轮工作已经把“可在仓库内真实完成并验证”的整改项全部落地。系统状态从“复审指出的问题已确认存在”推进到“主风险项已逐步切成两类”:
- **仓库内已修复并可回归验证的工程问题**
- **必须依赖外部环境、目标主机或正式业务输入才能闭环的上线前阻塞**
因此,当前仓库可以更准确地表述为:
> 已完成一轮真实工程收敛,仓库内可验证整改项已落地并通过标准验证入口;剩余阻塞集中在真实支付 acceptance、目标机 DR 演练、真实告警联调和正式外部文本签发。

View File

@@ -0,0 +1,96 @@
# DR_DRILL_TEMPLATE
日期:
负责人:
目标主机:
备用/异机主机:
对应快照目录:
对应工单/变更号:
## 1. 演练目标
- 验证目标主机可生成真实快照
- 验证 `bash scripts/backup_verify.sh --from-backup <backup-dir>` 可在目标主机跑通
- 验证恢复副本最小服务链:
- `health_status = 200`
- `portal_status = 200`
- `portal_report = 200`
- `portal_pdf = 200`
- 记录密钥位置、恢复耗时、异常与补救动作
## 2. 前置条件
- 目标主机已部署当前版本代码
- 目标主机已配置 `.env` / secrets / backup root
- 目标主机存在可执行的 `bash scripts/backup_snapshot.sh`
- 若做异机演练,备用主机已具备读取快照与最小运行依赖
## 3. 执行记录
### 3.1 生成真实快照
命令:
```bash
bash scripts/backup_snapshot.sh <backup-root>
```
结果:
- 快照目录:
- manifest 是否生成:
- 失败/异常:
### 3.2 从快照执行 restore smoke
命令:
```bash
bash scripts/backup_verify.sh --from-backup <backup-dir>
```
结果:
- `manifest_ok`:
- `sqlite_ok`:
- `health_status`:
- `portal_status`:
- `portal_report`:
- `portal_pdf`:
- 耗时:
- 失败/异常:
### 3.3 异机恢复(如执行)
命令:
```bash
bash scripts/backup_verify.sh --from-backup <backup-dir>
```
结果:
- 主机:
- 是否成功:
- 差异/异常:
## 4. 密钥与配置核对
- JWT secret 位置:
- Portal token secret 位置:
- Fernet key 位置:
- Payment key/cert 位置:
- 负责人:
## 5. 结论
- [ ] 目标主机快照成功
- [ ] 目标主机 restore smoke 成功
- [ ] 异机恢复成功(若适用)
- [ ] 可归档为上线前灾备演练证据
## 6. 后续动作
- 待修复问题:
- 风险等级:
- 下一次演练时间:

View File

@@ -0,0 +1,507 @@
# gaokao-volunteer-system 系统性复审报告2026-06-15
**评审对象**: `/home/long/project/gaokao-volunteer-system`
**复审基线**: `docs/CURRENT_STATE.md`(最后更新 2026-06-15
**评审方式**: 当前真相源复核 + 核心源码抽检 + 子系统专项复审 + 本地验证命令复核
**评审标准**: 严格标准;重点看“真实闭环、数据安全、验证可信度、生产可运维性”
**历史参照**: `reports/PROJECT_SYSTEM_REVIEW_2026-06-14.md`
---
## 1. 复审结论
**结论**:相较 2026-06-14上轮多项高优先级工程问题已经真实收口尤其是
- 支付 webhook 双写裂缝已关闭
- 退款主链闭环已关闭
- webhook DB 按 `db_path` 隔离已关闭
- 删除/匿名化按当前声明范围已扩围
- 分享 allowlist 已落地
- portal token secret / payment webhook secret 的 prod fail-closed 已落地
- CI / dev-verify / coverage gate 的**本地硬门禁**已统一
- 备份恢复已从文件级升级到**本地服务级 restore smoke**
但按严格标准,项目**仍然不能被表述为“完整商业闭环系统”或“支付/灾备/合规都已完成生产验收”**。当前仍存在两类关键未闭环问题:
1. **真实生产闭环未完成**:真实支付宝 acceptance、公网 notify、生产 SMTP/IM、目标机备份恢复、异机灾备。
2. **新增或遗留的语义/暴露面风险**portal 通知审计页暴露原始 payload、portal 上传附件未纳入删除/匿名化、`refund_pending` 死状态残留、通知底座仍保留 `sent` 旧语义。
**总体评级****工程基础明显增强,当前更接近“本地可验证的 v2.1 运营增强系统 + T12 在途”,但仍不应宣称生产级 Web 自助闭环已完成。**
---
## 2. 本次复审回答的核心问题
### 2.1 已确认关闭的旧问题
- P1-1 支付双写裂缝
- P1-4 webhook DB 连接污染
- P1-5 退款闭环
- P1-2 删除/匿名化扩围(按 CURRENT_STATE 声称范围)
- P1-6 分享 allowlist
- P2-1 孤儿订单
- P2-2 channel_sync DAO 真相收敛(实现层面)
- P2-4 portal token secret 分离
- P2-5 payment webhook secret fail-closed
- P1-7 覆盖率硬门禁本地统一
- P1-8 本地 restore smoke 升级为服务级验证
### 2.2 仍未关闭的旧问题
- P1-3 真实支付宝回调业务校验 / acceptance
- 生产备份恢复闭环
- 生产 SMTP / IM / 告警联调
- 前台正式隐私/删除/工单闭环
### 2.3 本次新增发现
- portal 通知审计页向持 token 用户暴露原始 payload含邮箱与服务器绝对路径
- portal 上传附件未纳入删除/匿名化文件清理
- `refund_pending` 已退化为死状态,模型口径继续分裂
- 通知底座仍保留 `sent` 状态P2-3 仅在 dispatcher / portal 主链层完成
- `CURRENT_STATE` 对 codecov 的“单一真相源”表述偏强;实质是数值对齐,不是执行单源
- Docker / Compose 仍是开发态模板,不能代表生产部署闭环
- 测试/脚本对子进程 PATH 有隐式依赖;直接 `.venv/bin/python -m pytest` 与激活 venv 后的 `python3`/`locust` 行为不同
---
## 3. 评审范围
### 3.1 文档
- `docs/CURRENT_STATE.md`
- `docs/P0_P1_P2_REMEDIATION_PLAN_2026-06-14.md`
- `docs/BACKUP_AND_RECOVERY_PLAN.md`
- `docs/PRODUCTION_DEPLOYMENT_CHECKLIST_2026-06-15.md`
- `docs/DELIVERY_RETENTION_OPS_RUNBOOK.md`
- `codecov.yml`
- `.github/workflows/ci.yml`
- `docker-compose.yml`
- `Dockerfile`
### 3.2 代码主链
- `data/payments/service.py`
- `data/payments/providers/alipay.py`
- `data/channel_sync/webhook_server.py`
- `data/orders/deletion_service.py`
- `data/share/permission.py`
- `data/notifications/dispatcher.py`
- `data/notifications/email_service.py`
- `admin/config.py`
- `admin/routes/web_public.py`
- `data/customer_portal/token.py`
### 3.3 关键测试样本
- `admin/tests/test_p2_4_p2_5_secrets.py`
- `admin/tests/test_order_deletion.py`
- `admin/tests/test_web_public.py`
- `admin/tests/test_payment_alipay_notify.py`
- `admin/tests/test_notification_audit_page.py`
- `data/payments/tests/test_webhook.py`
- `data/payments/tests/test_service.py`
- `data/payments/tests/test_refund_flow.py`
- `data/channel_sync/tests/test_webhook_server_db_scoping.py`
- `data/channel_sync/tests/test_single_dao_truth.py`
- `tests/test_backup_restore_service_level.py`
- `tests/test_coverage_gate_core.py`
- `tests/test_ops_alerts.py`
- `tests/test_delivery_notification.py`
- `tests/test_retention_cleanup.py`
- `tests/test_delivery_dispatcher.py`
---
## 4. 严重级别定义
- **P0**: 可直接导致系统失控/严重泄露/资金错误,且无现实缓解
- **P1**: 阻止生产闭环或存在显著数据/支付/隐私风险
- **P2**: 语义漂移、工程债务、生产边界不清或中等级暴露面
- **P3**: 已修复旧问题 / 正向发现 / 低优先改进项
---
## 5. 关键发现
## 5.1 P1仍然成立的问题
### P1-1 真实支付宝回调校验与 acceptance 仍未闭环
**证据**
- `docs/CURRENT_STATE.md:25,79,142-145` 继续将真实支付 acceptance / P1-3 列为未完成阻塞项。
- `data/payments/service.py:189-215` 当前已校验:签名、`payment_id`、成功状态白名单、金额、`app_id``notify_id` 非空、`provider_trade_no` 非空。
- `data/payments/providers/alipay.py:97-110` 的标准化字段中仍没有 merchant/seller 维度。
- `docs/P0_P1_P2_REMEDIATION_PLAN_2026-06-14.md:223-234` 明确要求 `app_id / merchant / notify_id / 状态白名单 / 金额 / payment_id` 全校验。
- `admin/tests/test_payment_alipay_notify.py:30-136` 使用临时 RSA keypair 与 `https://example.com/...` 回调地址,仅证明本地闭环,不是商户实联。
**判断**
相较上轮,这一项已**部分修复**,但仍是当前最重要的生产阻塞项之一。当前代码不支持把“本地可测”升级表述成“真实支付闭环已完成”。
**风险**
- 真实商户/真实 notify 链尚无线上验收
- 缺 merchant/seller 绑定维度
- `notify_id` 只做非空校验,不是远端真实性证明
**结论**
正式报告必须继续把该项列为 **P1 未关闭**
---
### P1-2 Portal 通知审计页向持 token 用户暴露原始通知 payload
**证据**
- `admin/routes/web_public.py:1148-1189``_render_notification_audit_page()` 直接渲染 `event.payload_json`
- `data/orders/dao.py:583-595` 在交付事件中把 `audit_report` / `pdf_path` 写入 payload。
- `tests/test_delivery_notification.py:124-129` 明确断言 email event payload 中包含 `parent@example.com`
- `admin/tests/test_notification_audit_page.py:47-85` 仅验证页面能显示事件,不校验敏感字段被裁剪。
**风险**
任何持有 portal token 的用户都可在 `/portal/{token}/notifications` 查看:
- 客户邮箱
- 交付物服务器绝对路径
- 原始通知 payload 细节
这扩大了暴露面,也泄露了服务器目录结构。
**结论**
这是本次复审最重要的**新增 P1**。
---
### P1-3 Portal 上传附件未纳入删除/匿名化文件清理
**证据**
- `admin/routes/web_public.py:286-303` `_store_portal_attachment()` 把附件写入 `portal_upload_dir/order_id/...`,并把 `storage_path` 写入 intake payload。
- `data/orders/deletion_service.py:49-69, 71-126, 157-166` 删除时仅删除 `audit_report``pdf_path`;匿名化仅清空 `payload_json`,不删除附件目录。
- `admin/tests/test_order_info_upload.py` 证明上传后的 `storage_path` 会真实落盘。
**风险**
数据库层面看似“已删除/已匿名化”,但磁盘上可能仍保留:
- 身份证/成绩单等高敏附件
- 其他 AI 方案或家庭信息材料
这会把“声明层已清理”与“真实文件仍在”重新撕裂开。
**结论**
这是隐私删除链上的**新增 P1**。
---
### P1-4 生产备份恢复仍未验收;当前只能证明本地 restore smoke 成立
**证据**
- `docs/BACKUP_AND_RECOVERY_PLAN.md:145-159,194-199` 明确承认:异机/异地备份、目标主机 timer、失败告警链、密钥轮换记录仍未闭环。
- `docs/PRODUCTION_DEPLOYMENT_CHECKLIST_2026-06-15.md:275-295` 把目标机 `backup_verify.sh --from-backup ...` 仍列为上线前待勾选项。
- `ops/systemd/gaokao-backup*.service|timer``ops/cron/gaokao-backup.crontab.example` 仅是样例,没有目标主机执行证据。
**风险**
当前仓库可以证明“本地可演练”,不能证明:
- 目标主机已持续生成可恢复快照
- 异机恢复已验证
- 密钥与配置已能回收
**结论**
这项应继续保留为 **P1 生产闭环缺口**
---
### P1-5 备份定时任务没有失败告警闭环
**证据**
- `ops/systemd/gaokao-backup.service` / `gaokao-backup-verify.service` 仅有 `ExecStart`,未见 `OnFailure=`
- `ops/cron/gaokao-backup.crontab.example` 只把输出写日志,不接 SMTP/IM/监控。
- `docs/BACKUP_AND_RECOVERY_PLAN.md:186-196` 流程图写到“告警”,但 `154-159` 又明确承认备份失败告警链未接入。
**风险**
备份或 restore smoke 失败时,当前样例部署只会留下日志,不会主动通知值班。
**结论**
这是备份链路上的 **P1 运维缺口**
---
## 5.2 P2新增风险 / 未完全收口的问题
### P2-1 `refund_pending` 已退化为死状态,模型口径继续分裂
**证据**
- `data/payments/dao.py` schema 仍允许 `refund_pending`
- `admin/routes/web_public.py:45-55` 仍渲染 `refund_pending`
- `data/payments/service.py:261-300` 实际退款入口已直接把 payment 更新为 `refunded`,无任何路径写入 `refund_pending`
- `data/payments/tests/test_refund_flow.py` / `test_service.py` 也已按直接 `refunded` 锁定
**风险**
这是死状态,不再是主链 bug但会继续污染 UI、报表、维护者心智模型。
---
### P2-2 `sent` 旧语义仍残留在通知底座
**证据**
- `data/notifications/dispatcher.py` 已把 `station` 改为 `validated``email` 才进入 `delivered`
-`data/notifications/email_service.py:29``DELIVERY_EVENT_STATUSES` 仍含 `sent`
- `mark_sent()` 仍可直接写入 `sent`,见 `data/notifications/email_service.py:131-151`
- `tests/test_delivery_notification.py` 仍把 `sent` 视作合法状态路径
**风险**
主链页面已纠偏,但底座状态空间仍允许旧语义复活。
---
### P2-3 `CURRENT_STATE` 对 codecov 的“单一真相源”表述偏强
**证据**
- `docs/CURRENT_STATE.md:54-57` 声称 `scripts/check_coverage_gate.py` 是单一真相源CI/dev-verify/codecov 全部指向同一阈值。
- `codecov.yml:13-29` 实际上单独重复维护 target/threshold/patch target。
- `codecov.yml:6,18,45-47` 还显式表明它不是硬阻断门禁。
**风险**
这不是门禁失效问题,而是表述失真问题。更准确的说法应是:
- **CI 与本地硬门禁统一**
- **Codecov 仅与其保持同值显示口径,不是执行单源**
---
### P2-4 Docker / Compose 仍是开发态模板,不应视为生产部署闭环
**证据**
- `docker-compose.yml:9-18` 未编码 checklist 所要求的大量生产变量:`GAOKAO_PORTAL_TOKEN_SECRET`、支付回调、SMTP、告警变量等。
- `docker-compose.yml:10-14` 仍默认 `GAOKAO_ENV=dev` 且带 dev fallback。
- `Dockerfile` 只构建 admin 进程镜像,不包含 dispatcher/watchdog/backup 作业编排。
- `docs/PRODUCTION_DEPLOYMENT_CHECKLIST_2026-06-15.md:27-79` 明确把这些生产变量列为必备。
**风险**
现有 Compose 只能证明“开发环境可跑”,不能证明“生产最小闭环可跑”。
---
### P2-5 测试/脚本对子进程 PATH 有隐式依赖
**证据**
本次实际运行观察到:
```bash
./.venv/bin/python -m pytest admin/tests tests data -q
```
出现 7 个失败,主要为:
- `tests/test_delivery_dispatcher.py`
- `tests/test_retention_cleanup.py`
- `tests/test_t5_performance.py`
失败原因:
- 这些测试用 `subprocess.run(["python3", ...])``locust`,直接依赖 PATH 上的解释器/可执行文件。
- 未激活 venv 时,`python3` 会落到系统 Python随后因 `admin.app -> import uvicorn` 失败。
而运行:
```bash
bash scripts/dev-verify.sh --skip-install
```
**717 passed**,因为脚本先 `source .venv/bin/activate`PATH 被修正,子进程 `python3`/`locust` 都能解析到 venv 内可执行文件。
**风险**
这不是业务 bug但说明验证闭环对“shell 激活 venv”有隐式前提直接 `.venv/bin/python -m pytest` 还不够 hermetic。
---
## 5.3 P3已确认关闭的旧问题 / 正向发现
### P3-1 支付双写裂缝已关闭
**证据**
- `data/payments/service.py:217-259` 在同一事务中同时推进 payment 与 order
- `data/payments/tests/test_service.py` 覆盖回滚场景
- 专项验证:`34 passed`
---
### P3-2 退款主链闭环已关闭
**证据**
- `data/payments/service.py:261-300` 在同一事务中推进 payment 与 order 到 `refunded`
- `data/payments/tests/test_refund_flow.py` / `test_service.py` 已锁定
---
### P3-3 webhook DB 隔离已关闭
**证据**
- `data/channel_sync/webhook_server.py:122-167` 改为按 `db_path` 缓存连接
- `data/channel_sync/tests/test_webhook_server_db_scoping.py` 覆盖多路径与并发场景
---
### P3-4 删除/匿名化按当前声明范围已扩围
**证据**
- `data/orders/deletion_service.py:71-125` 已覆盖 orders 主表、`payments.callback_payload``order_intakes.payload_json`
- `admin/tests/test_order_deletion.py` 已覆盖关键断言
**边界**
这只能证明“按 CURRENT_STATE 声称范围已修复”,**不等于完整合规闭环**。portal 上传附件仍未清理。
---
### P3-5 分享 allowlist 已收口
**证据**
- `data/share/permission.py:45-47, 85-173` edit/admin 均改为显式 allowlist
- 未知 permission 会 fail-safe 到 `read`
- `data/share/tests/test_permission.py` 已覆盖
---
### P3-6 portal token secret 分离与 payment webhook secret fail-closed 已落地
**证据**
- `admin/config.py` 已引入 `portal_token_secret` 与 prod 校验
- `admin/tests/test_p2_4_p2_5_secrets.py` 覆盖完整
---
### P3-7 覆盖率硬门禁本地统一已成立
**证据**
- `scripts/check_coverage_gate.py`
- `scripts/dev-verify.sh`
- `.github/workflows/ci.yml`
- `tests/test_coverage_gate_core.py`
---
### P3-8 本地 restore smoke 已从文件级升级到服务级
**证据**
- `scripts/backup_verify.sh`
- `scripts/backup_restore_smoke.py`
- `tests/test_backup_restore_service_level.py`
- `tests/test_backup_workflow.py`
---
### P3-9 watchdog → ops alert sink → 后台审计页本地链已存在
**证据**
- `scripts/gaokao-delivery-watchdog.py`
- `data/notifications/ops_alerts.py`
- `admin/routes/notifications.py`
- `tests/test_ops_alerts.py`
- `admin/tests/test_ops_alerts_admin.py`
**边界**
这证明本地底座存在;**不等于真实 SMTP/IM 与宿主机联调完成**。
---
## 6. 命令复核结果
### 6.1 全量直接 pytest不激活 venv PATH
执行:
```bash
./.venv/bin/python -m pytest admin/tests tests data -q
```
结果:**7 failed710 passed**。
主要失败原因:
- `tests/test_delivery_dispatcher.py` / `tests/test_retention_cleanup.py` 中子进程调用 `python3`,落到系统解释器,触发 `ModuleNotFoundError: uvicorn`
- `tests/test_t5_performance.py` 依赖 `locust` 可执行文件在 PATH 中可见
### 6.2 仓库标准验证入口
执行:
```bash
bash scripts/dev-verify.sh --skip-install
```
结果:**通过**,关键输出:
- `717 passed`
- `coverage gate summary: overall=92.59%, core=100.00%`
- `ruff`: 通过
- `mypy`: `Success: no issues found in 187 source files`
### 6.3 解释
- 仓库声明的标准入口 `dev-verify.sh` 当前是可通过的。
- 但验证闭环依赖 `source .venv/bin/activate` 改写 PATH测试本身仍不够完全自描述。
- 这更像“验证入口已统一,但底层 shell 假设仍存在”。
---
## 7. 最终判断
### 可以确认的事实
1. 上轮多项工程性 P1/P2 已真实修复,不应再按“当前未修复”表述。
2. 当前版本已经明显强于 2026-06-14 的状态,尤其在事务一致性、安全 fail-closed、本地恢复演练方面。
3. 但项目**仍不能**宣称:
- 真实支付闭环已完成
- 灾备已完成生产验收
- 合规删除链已完整闭环
- 通知/交付语义已完全收敛
### 当前最关键的未闭环项
按风险排序:
1. **真实支付宝回调业务校验 + 线上 acceptance**
2. **portal 通知审计页 payload 直出导致的敏感信息暴露**
3. **portal 上传附件未纳入删除/匿名化文件清理**
4. **生产备份恢复 / 失败告警 / 目标机验收缺失**
5. **`refund_pending` / `sent` 等残留死语义收敛**
6. **Docker / Compose 与生产 checklist 的边界澄清**
### 一句话结论
> 当前仓库已经完成一轮真实有效的工程收敛,属于“本地可验证的 v2.1 运营增强系统 + T12 在途”,但仍不是可以对外宣称“生产级 Web 自助支付/交付/灾备/合规全闭环”的系统。