forked from wangziqi/gongxue-base
38 lines
1.9 KiB
Markdown
38 lines
1.9 KiB
Markdown
# 租户外键完整性审计
|
|
|
|
## 目的
|
|
|
|
RLS 负责控制一行是否可见,但不能保证一条租户内记录引用的父记录也属于同一租户。历史 schema 仍有一批只引用父表 `id` 的外键,因此上线门禁同时执行:
|
|
|
|
- 快速 schema 指纹:生产 readiness 查询 `pg_catalog`,发现新增、删除、改名、未验证的租户间外键即阻断。
|
|
- 完整数据审计:只在 `local`、`test`、`ci` 隔离克隆库执行,逐条检查现有数据是否满足租户不变量并输出 JSON 证据。
|
|
|
|
默认规则是子表与父表 `tenant_id` 必须一致。当前只有三个显式例外:
|
|
|
|
- 平台审计规则允许 `tenant_id is null`,代表全局规则;租户专属规则必须与告警租户一致。
|
|
- 租户采用公共题库时,源题库可以属于平台租户,但必须是 `source_scope='platform'`。
|
|
- 公共题库通知可以指向平台源题库,同样必须是 `source_scope='platform'`。
|
|
|
|
新增例外必须同时补业务理由、查询不变量、合同测试和 schema 指纹。不得只更新指纹跳过审计。
|
|
|
|
## 执行
|
|
|
|
隔离库必须已应用全部迁移,并在 `app_private.environment_safety` 标记为 `local/test/ci` 且 `allow_destructive_tests=true`。该命令只读,但会扫描相关业务表,因此沿用破坏性测试确认口令,防止误连生产主库:
|
|
|
|
```bash
|
|
DATABASE_URL='postgresql://postgres:postgres@127.0.0.1:55432/postgres' \
|
|
node scripts/tenant-foreign-key-audit.js \
|
|
--confirm=SMOKE_SEED_LOCAL_OR_CI_ONLY \
|
|
--write=docs/refactor/launch-artifacts/tenant-foreign-key-audit.json
|
|
```
|
|
|
|
通过条件:
|
|
|
|
- `schema.schemaMatches=true`
|
|
- `schema.unvalidatedRelations=[]`
|
|
- `data.auditedRelations` 等于指纹关系数
|
|
- `data.invalidRelations=0`
|
|
- `status=pass`
|
|
|
|
生成的 JSON 及 SHA-256 需要写入 `production-launch-evidence.json` 的 `db.tenant-foreign-key-audit` 检查项。
|