# 访问规则白名单语义迁移

迁移 `0102_access_rule_allow_whitelist_semantics` 将旧版跨主体“专属占用”
规则切换为分层白名单。迁移会归档并删除已有的全部 `allow`，保留 `deny`
不变；发布后新建的 `allow` 将按白名单解释。

## 发布前

1. 暂停管理端和用户工作台的权限配置写入，并停止会创建访问规则的
   acceptance、smoke 或运维脚本。仅依赖数据库表锁不足以覆盖迁移前快照到
   应用切换之间的时间窗口。
2. 使用只读数据库账号导出脱敏基线：

   ```bash
   AI_GATEWAY_ACCESS_RULE_AUDIT_DATABASE_URL='<只读数据库连接>' \
     scripts/acceptance/export-access-rule-audit.sh export \
       --output dist/access-rule-audit/before.json
   ```

3. 保存命令输出中的总规则数、`allow`/`deny` 数量和 SHA-256。快照仅包含按
   主体类型、效果、资源类型、状态聚合的计数和摘要，不包含主体 ID、资源 ID、
   API Key Secret 或规则元数据。
4. 确认权限写入仍处于暂停状态，再开始应用发布和数据库迁移。

## 迁移后校验

继续使用只读数据库账号执行：

```bash
AI_GATEWAY_ACCESS_RULE_AUDIT_DATABASE_URL='<只读数据库连接>' \
  scripts/acceptance/export-access-rule-audit.sh verify \
    --before dist/access-rule-audit/before.json \
    --output dist/access-rule-audit/after.json
```

只有命令返回 `access_rule_audit_verify=PASS` 才能恢复权限配置写入。该校验同时
证明：

- 迁移前 `allow` 数量和摘要与归档表一致；
- 当前表中的旧 `allow` 数量为零；
- `deny` 数量和内容摘要与迁移前一致。

随后按生产验收清单创建隔离用户组和 API Key，验证父级继承、分层白名单交集、
同层并集、`deny` 优先及兄弟主体隔离。验收结束后删除隔离身份、Key 和规则，
并确认没有遗留任务、队列项或并发租约。

## 回滚限制

应用回滚不会恢复旧版“专属占用”规则。新版本一旦写入白名单 `allow`，禁止直接
切回旧应用，否则旧代码会把新白名单解释成跨主体排他规则。

必须回滚到旧应用时：

1. 再次暂停所有访问规则写入和 acceptance/smoke；
2. 导出当前脱敏快照，并单独备份数据库；
3. 明确识别并清理迁移完成后创建的 `allow`，不得删除 `deny`，也不得直接恢复
   归档中的旧 `allow`；
4. 校验当前 `allow=0` 且 `deny` 摘要未变化后，才允许切换旧应用；
5. 恢复旧规则必须作为独立、受审的数据恢复操作处理，不能包含在应用自动回滚
   中。

迁移本身会在事务中锁定 `gateway_access_rules` 的写入，校验归档数量和摘要后才
删除旧 `allow`。若检测到归档不一致，事务会失败；若迁移完成后出现新白名单，
直接重复执行迁移也会失败，不会误删新规则。
