P3_WP10_MULTI_TENANCY_EVIDENCE.md 5.6 KB

P3-WP10 多租户底座验证证据

结论边界

独立最终复验已通过,本地工程状态为 ENGINEERING_BASELINE_COMPLETE_MULTI_TENANCY_ACTIVATION_BLOCKED。此前 501503 payload/GUC gateway 缺陷已由后续闭合控制链替代;此状态不激活 SaaS 或共享控制面,不配置真实 tenant/provider/secret,不代表企业 UAT 或生产完成。

2026-08-17 第四轮整改证据:521 撤销 PUBLIC/control/runtime/approver 对旧 lifecycle gateway 的执行,recover/delete 只能经 approval wrapper;522 使 quota worker 在同一受控事务中消费 digest-bound claim、reserve 后 settle 或 release;523524 只为 queued retry 重臂已释放的 claim/attempt;525 使任何 live tenant/control data 在首个 downgrade step 即拒绝。真实 Docker PostgreSQL 已验证低权旧 gateway 拒绝、approved wrapper/API 正向、quota settled/released、三次 fail、restart/fence、并发和 downgrade fence。最终本地定向 suite 为 33 unit/API + 13 real PostgreSQL = 46 passed;Ruff、OpenAPI 483-operation byte parity、source/deployment/migration byte parity 与 git diff --check 通过。状态为 ENGINEERING_BASELINE_COMPLETE_MULTI_TENANCY_ACTIVATION_BLOCKED;外部 activation 仍为 TBD_EXTERNAL

TDD 记录

  • 当前整改 RED/GREEN: 20260817_503 下真实 dataops_app runtime 可自行设定 beta tenant GUC 并直接调用 tenant_foundation_write,即使调用者只应属于 alpha,攻击测试为 1 failed20260817_504 未修改已应用迁移,只撤销共享 runtime 对 payload-authorized tenant gateways 和 tenants 根表的访问;同一攻击为 1 passed。这是紧急封堵,完整 authenticated claim/API replacement 尚未完成。

  • RED:test_wp10_tenant_context.pytest_wp10_tenant_boundaries.pytenant_context / tenant_resources 缺失时收集失败;最小闭合实现后 GREEN。

  • RED:lifecycle/repository PostgreSQL 测试在模块/方法缺失时失败;501 tenant foundation 与 502 lifecycle gateway 后 GREEN。

  • RED:迁移后重跑 role-init 时,真实 dataops_app runtime 能在设定 tenant GUC 后直 DELETE audit;role-init 的广泛 DML grant matrix 未排除 WP10 表。修复为先撤销且排除所有 tenants/tenant_* 表后,真实攻击 GREEN。

  • RED:low-privilege migrator 从 480 到 head 时因缺少 dataops_tenant_foundation_owner member 被 501 前置检查拒绝;测试 role-init fixture 增加最小 owner membership/schema grant 后 GREEN,migrator 保持 NOSUPERUSER,NOCREATEROLE

  • RED:初版持久 outbox 在 FORCE RLS 下无法在尚未知道 tenant scope 时读取 worker UID;514 新增只允许 owner gateway 读取的 outbox_uid -> tenant_id lookup,先用持久映射设置 DB-local scope 再 lease outbox,未放宽 RLS;真实 Flask/PG worker GREEN。

  • RED:从较新 head 降级时会先遇到后续迁移 guard,不能将安全拒绝稳定归因到最外层边界;515 作为 marker-only final head fence,在 tenant/control/outbox 任一数据存在时立即拒绝,live-data 515 -> 503 攻击 GREEN,version 保持 515

本地 PostgreSQL 证据(Docker)

  • 初始只读 head:20260813_500;当前本地 Docker PostgreSQL head:20260817_525。live tenant 时 525 -> 520 在第一步被 final fence 拒绝且 head 不变;空表已真实运行 525 -> 520 -> 525 并确认旧 lifecycle gateway execute 仍为 false;受限 migrator 已真实运行 480 -> 525。数据库边界不属于被允许跳过的网络安全监测范围。
  • 动态创建的 NOSUPERUSER,NOCREATEROLE shared-runtime login 即使设置 alpha GUC 并以 beta payload 调用旧 tenant_foundation_write 仍得到 PostgreSQL permission denied;动态 dedicated control login 才能 issue/consume claim。两连接只能消费一个 claim,重启后 replay 拒绝。
  • 真实 Flask API 以 server PRIVATE_SINGLE_TENANT_ID provision,body 不含 tenant;随后 quota claim、持久 outbox lease、object/graph/cache/index namespace propagation、freeze、status/audit/manifest read、recover、activate、deletion-candidate、rollback、delete 和 delete 后 rollback 拒绝均已在 Docker PostgreSQL 验证。worker 不带显式已派生 scope 或 tenant 已 frozen 时默认拒绝。
  • 受限 migrator、OpenAPI、静态与 source/deployment parity 已按上述 fresh 数字复跑;本证据不将本地检查表述为企业验收。

本地工程覆盖与未覆盖

  • 已覆盖:服务端派生 private default、持久 membership+route、未批准 shared/SaaS 拒绝、route/spoof/缺 scope 拒绝、真实 Flask RBAC/no-store/closed schema、background durable outbox/worker scope、event envelope、ASCII resource namespace、hash-only/default-disabled manifest、RLS/runtime direct DML、quota atomicity、append-only audit 和完整 lifecycle fence。
  • 图、对象存储、缓存和索引只有 namespace contract/攻击 fixture;没有宣称其现有 Neo4j/MinIO/cache/search 实例已获得真实 tenant ACL/partition 隔离。
  • keys/connectors/models/plugins/backup/restore/audit export 只有 digest/namespace contract;没有 secret/provider、插件仓库、真实备份恢复或审计导出作业。
  • deletion candidate/delete/rollback 的企业审批、legal hold、retention、备份恢复演练和真实外部服务隔离仍须在批准 profile 中完成。

外部门禁

multi_tenancy 仍为 TBD_EXTERNAL。尚缺批准的 SaaS/共享控制面决策、tenant count、isolation level、capacity/delivery profile、外部 service isolation、backup/restore 目标和 enterprise UAT。任何本地测试通过均不解除这些条件。