P3_WP10_MULTI_TENANCY_IMPLEMENTATION_PLAN.md 9.7 KB

P3-WP10 多租户与混合交付底座实施计划

For agentic workers: 本计划只构建可验证的本地工程底座;不得把它表述为已批准的 SaaS、共享控制面、企业 UAT 或生产就绪。

目标: 在不改变默认私有化单租户交付的前提下,提供版本化、服务端派生并在 PostgreSQL 中强制隔离的租户上下文、生命周期、配额、审计和资源命名空间契约。

架构: 请求或后台任务只可从已批准的服务端交付配置/已持久化路由映射获得 TenantContext,永不接受 body/query 自报的 tenant_id。所有 WP10 新的持久化事实由 SECURITY DEFINER 的闭合 JSONB 网关写入,并由 restricted runtime 角色直连 DML 默认拒绝;租户读路径以 RLS 和事务内 dataops.tenant_id 设置进行限制。Neo4j、对象存储、缓存和搜索现有部署没有可验证的原生租户隔离,故只提供严格命名空间适配器、manifest 和攻击测试,实际外部服务隔离仍为 TBD_EXTERNAL

技术栈: Flask、SQLAlchemy、Alembic、PostgreSQL RLS/SECURITY DEFINER/DB clock、pytest、Docker PostgreSQL。


只读盘点(2026-08-17)

当前迁移 head 是 20260813_50020260813_500_runtime_control_claims.py,source/deployment 字节一致)。工作树已有 WP05–WP09 和用户未提交变更,WP10 不重写它们。

面向 已有可复用覆盖 WP10 缺口/本计划闭合
身份/权限 enterprise_identity.py 提供 fail-closed IdP 映射;permissions.py 提供 API 默认拒绝 租户域名/路由映射、服务端派生 delivery mode、管理员显式 scope
模型/预算/审计 WP09 已有部分 tenant_id、DB-time lease/fence、append-only invocation audit 这些不是全局 tenant model;新增租户注册表、通用配额、tenant audit 和跨服务传播契约
任务/事件 既有 outbox 和 WP05/WP06 任务实现 背景任务必须有已验证 tenant scope、冻结时拒绝和事件 envelope 契约
数据库 WP06/WP09 使用 owner/runtime 角色与受控网关 通用 tenant 表强制 RLS、runtime 无直 DML、闭合 tenant gateway、真实两连接验证
图/对象/缓存/索引 图、知识缓存和 Compose Neo4j/MinIO 现存 无可复核的原生多租户隔离;只增加 namespace adapter/manifest/digest/escape 拒绝,外部 service 验证保留 TBD
备份/恢复/插件 Compose backup 脚本和 WP09 provider contract 已有 tenant backup/restore/audit-export manifest、approval/hold/fence 及 default-disabled provider 契约;不建设插件仓库

执行任务

安全整改收口(2026-08-17,工程基线完成但 activation blocked)

  • 独立复验已证明 501–503 不能作为授权边界;504 保留为历史后续 revoke,legacy repository sealed,不再允许 shared runtime 通过 payload tenant_id 或 session GUC 触发写入。
  • 505–520 是唯一有效的本地工程控制链:dedicated dataops_tenant_control identity、持久 membership+route、DB-clock one-shot claim、claim-bound quota/lifecycle、private-only provision、持久 outbox/worker scope lookup、独立 approver fact 与真实签发 API、只读 status/audit/manifest gateway、final downgrade security fence,以及有界 worker fail/retry terminal state。
  • 新 API 为 /api/system/tenant/provisionsquota-claims、六个 lifecycle action 以及 status/audit/manifests;全部由 Flask RBAC、no-store、closed schema 和 server-derived identity/route 保护。OpenAPI 同步,shared/SaaS 仍不可激活。
  • 当前实际 head 20260817_525;独立复验已通过,真实本地验证包括 live-data 525 -> 520 downgrade attack、空库 525 -> 520 -> 525、restricted 480 -> 525、旧 lifecycle gateway 低权拒绝、独立 control/runtime/approver login、两连接 provision/worker race、DB-clock expiry/restart replay、Flask provision/approval/lifecycle/read/outbox 与 quota worker reserve/settle/release。工程状态为 ENGINEERING_BASELINE_COMPLETE_MULTI_TENANCY_ACTIVATION_BLOCKED

Task 1: 写入基础行为测试并记录 RED

文件:

  • Create: tests/core/system/test_wp10_tenant_context.py
  • Create: tests/security/test_wp10_tenant_boundaries.py

  • [ ] 写失败测试:私有模式只能从 server approved default 解析;共享/saas 未批准时拒绝;请求 payload、后台任务和管理员缺 scope 均拒绝;域名映射、Unicode 同形/路径/URL 逃逸、跨租户 namespace 均拒绝。

  • [ ] 运行 .venv/bin/pytest tests/core/system/test_wp10_tenant_context.py tests/security/test_wp10_tenant_boundaries.py -q,确认因 WP10 模块不存在而 RED。

Task 2: 实现版本化 TenantContext 与资源 namespace 契约

文件:

  • Create: app/core/system/tenant_context.py
  • Create: app/core/system/tenant_resources.py
  • Modify: app/core/system/permissions.py

  • [ ] 仅实现 Task 1 所需最小模型:closed DeliveryModeTenantContext、服务端 resolver、后台/管理员 scope validator、统一 namespace builder。

  • [ ] namespace 仅接受 ASCII canonical tenant/resource token;对象、图、缓存、索引、keys、connectors、models、plugins、backup、audit export 均产生不可混用的前缀或 manifest;provider 默认 disabled。

  • [ ] 重跑 Task 1 测试,确认 GREEN。

Task 3: 为 lifecycle/quota/database boundary 先写 RED

文件:

  • Create: tests/core/system/test_wp10_tenant_lifecycle.py
  • Create: tests/integration/test_wp10_tenant_postgres.py

  • [ ] 覆盖 provision -> active -> frozen -> recovering -> active -> deletion_candidate -> deleted,审批/hold/backup/retention、幂等 replay、changed replay、DB clock lease/fence、冻结任务拒绝、negative/bool/overflow quota 拒绝及跨租户不可借用。

  • [ ] 真实 PostgreSQL 测试覆盖 low-privilege migrator、runtime direct DML/trigger/owner/SET ROLE 拒绝、RLS cross-tenant read/write 拒绝、two connection single quota winner、gateway audit append-only 与精确 fixture 清理。

  • [ ] 运行上述两文件,确认其因实现/迁移不存在而 RED。

Task 4: 实现 PostgreSQL 闭合网关、RLS 与 repository

文件:

  • Create: migrations/versions/20260817_501_tenant_foundation.py
  • Create: app/core/system/tenant_repository.py
  • Modify: app/core/edge_gateway/runtime_roles.py
  • Mirror: deployment/migrations/versions/20260817_501_tenant_foundation.py, deployment/app/core/system/tenant_repository.py, deployment/app/core/system/tenant_context.py, deployment/app/core/system/tenant_resources.py, deployment/app/core/edge_gateway/runtime_roles.py

  • [ ] 使用 migration 500 作为唯一 down revision;不修改已应用迁移。创建 owner/runtime roles 的初始化前置检查,Tenant registry/routes/quotas/reservations/lifecycle/audit/manifest 表,并对 tenant-scoped 表 ENABLE/FORCE ROW LEVEL SECURITY

  • [ ] runtime 无 direct DML、TRUNCATE、trigger/owner 修改和未经授权 SET ROLE 权限;只可执行 owner 控制的 closed-schema tenant_foundation_write,该函数以 DB clock、advisory lock、lease/fence 和原子 reserve/settle/release 运行。

  • [ ] 只保存摘要/manifest;拒绝 raw secret、URL/path traversal、Unicode 同形和跨 tenant ref。将 source/deployment 逐字同步。

  • [ ] 重跑 Task 3 的 unit/integration 测试,确认 GREEN;使用 Docker PostgreSQL 做 500 -> 501 -> 500 -> 501,保留独立连接输出和 head 证据。

Task 5: 接入最小 API/事件契约并同步 OpenAPI

文件:

  • Create: app/api/system/tenant_foundation.py
  • Modify: app/api/system/__init__.py, app/core/events/outbox.py, docs/architecture/OPENAPI.yaml
  • Mirror corresponding deployment paths
  • Create: tests/test_wp10_tenant_api.py

  • [ ] 测试先行:认证/既有 RBAC 后的 status/read endpoint 不接收 client tenant id;无 scope/no-store/closed response;事件 envelope 无 tenant scope 被拒绝。

  • [ ] 添加仅供本地工程验证的最小 status 与 audit/manifest read contract,不开放 SaaS provisioning、真实 key/provider、插件上传或管理 UI。

  • [ ] 重新生成 OpenAPI(或明确记录无生成差异)并运行 API/事件定向测试。

Task 6: 交付证据与状态台账

文件:

  • Create: docs/architecture/ADR_P3_WP10_HYBRID_DELIVERY.md
  • Create: docs/runbooks/P3_WP10_TENANT_FOUNDATION_OPERATIONS.md
  • Create: docs/validation/P3_WP10_FAILURE_INJECTION.json
  • Create: docs/validation/P3_WP10_MULTI_TENANCY_EVIDENCE.md
  • Modify: docs/phase3/P3_WP00_REQUIREMENTS.json, docs/DATAOPS_PHASE3_6_MONTH_DEVELOPMENT_PLAN_20260802.md

  • [ ] 记录 RED/GREEN、真实 PostgreSQL head/round-trip/runtime attack/two-connection/restart-fence、OpenAPI/parity/secret-scan、私有单租户兼容。

  • [ ] 状态最高为 ENGINEERING_BASELINE_COMPLETE_MULTI_TENANCY_ACTIVATION_BLOCKEDmulti_tenancy、SaaS/共享控制面决策、租户数、隔离等级、容量/交付 profile、真实外部 graph/object/cache/index/provider 与企业 UAT/production 均保持 TBD_EXTERNAL

验证与不可越过边界

  • 仅运行 WP10 与直接 identity/permissions/task/event/audit/backup/knowledge/graph/storage/private delivery 相关测试;不运行全量回归。
  • 静态门禁:WP10 Ruff、py_compile、JSON、OpenAPI、source/deployment/migration byte parity、git diff --check、WP10 scoped secret scan。
  • 迁移和 Docker PostgreSQL 的数据库、角色与精确命名空间清理为本地工程证据;不是独立审计、企业 UAT 或生产验收。
  • 外部门禁: multi_tenancy = TBD_EXTERNAL,尚缺 SaaS/共享控制面决策、租户数量、隔离等级、容量和混合交付 profile 的书面批准。因此条件包未正式激活。