# 变更审计记录：user_site_roles / user_assistant_binding 软删除实施

| 字段 | 值 |
|------|-----|
| 日期 | 2026-03-24 09:43:22 |
| Prompt-ID | P20260324-093259 |

## 操作摘要

在 `auth.user_site_roles` 和 `auth.user_assistant_binding` 两张表上实施软删除，替代原有物理删除。DDL 新增 `is_removed boolean DEFAULT false` 和 `removed_at timestamptz` 字段及部分索引。后端所有查询这两张表的位置（7 个文件、23+ 处）添加 `AND is_removed = false` 过滤条件，`remove_user` 操作改为 `UPDATE SET is_removed = true, removed_at = now()`。

## 本次对话文件变更

### 新增文件
- `docs/audit/prompt_logs/prompt_log_20260324_093259.md`
- `docs/audit/session_logs/2026-03/24/36_e6cfbf4c_085324/main_01_fd2ad307.md`
- `docs/audit/session_logs/2026-03/24/36_e6cfbf4c_085324/sub_01_39f5c47c.md`
- `docs/audit/session_logs/2026-03/24/41_cd5cdd22_091638/main_01_39f5c47c.md`

### 删除文件
- `docs/audit/session_logs/2026-03/24/36_e6cfbf4c_085324/main_01_22ae44a6.md`
- `docs/audit/session_logs/2026-03/24/41_cd5cdd22_091638/main_01_f4046b07.md`

## 涉及文件

| 文件 | 变更类型 | 风险等级 |
|------|----------|----------|
| `db/zqyy_app/migrations/20260324_soft_delete_user_site_roles_and_binding.sql` | 新增 | 高（DDL） |
| `apps/backend/app/routers/xcx_auth.py` | 修改 | 高 |
| `apps/backend/app/routers/tenant_users.py` | 修改 | 高 |
| `apps/backend/app/services/role.py` | 修改 | 高 |
| `apps/backend/app/services/task_manager.py` | 修改 | 高 |
| `apps/backend/app/services/task_generator.py` | 修改 | 高 |
| `apps/backend/app/services/performance_service.py` | 修改 | 高 |
| `docs/database/ddl/zqyy_app__auth.sql` | 修改 | 中（DDL 基线） |
| `docs/database/BD_Manual_soft_delete_user_site_roles.md` | 新增 | 低（文档） |

## 改动注解

### `db/zqyy_app/migrations/20260324_soft_delete_user_site_roles_and_binding.sql`
- 变更类型：新增
- 原始原因：用户要求"移除用户时，要有字段来标记此记录被移除/删除"，需要在数据库层面支持软删除
- 思路分析：在 `auth.user_site_roles` 和 `auth.user_assistant_binding` 两张表各新增 `is_removed boolean DEFAULT false` 和 `removed_at timestamptz` 字段。创建部分索引 `ix_user_site_roles_active` 和 `ix_user_assistant_binding_active`（`WHERE is_removed = false`），确保活跃记录查询性能不受软删除数据膨胀影响
- 修改结果：DDL 已在测试库 `test_zqyy_app` 执行成功。现有数据默认 `is_removed = false`，无需数据迁移

### `apps/backend/app/routers/xcx_auth.py`
- 变更类型：修改
- 原始原因：软删除后，所有查询必须排除已移除记录，否则已移除用户仍能登录和操作
- 思路分析：在 7 处查询中添加 `AND is_removed = false` / `AND usr.is_removed = false` 过滤条件。涉及函数：`_get_user_roles_at_site`、`_get_user_default_site`、`get_my_status`（user_assistant_binding 查询）、`get_my_sites`、`switch_site`、`dev_context`（2 处：binding + site_roles）
- 修改结果：已移除用户的角色和门店绑定在所有小程序认证流程中被正确过滤。已移除用户登录时将获得受限令牌（无 site_id/roles），前端路由至相应状态页

### `apps/backend/app/routers/tenant_users.py`
- 变更类型：修改
- 原始原因：租户管理后台的用户列表、编辑、绑定更新等操作需排除已移除记录；`remove_user` 需改为软删除
- 思路分析：8 处查询添加过滤条件。`list_users` 的 COUNT 和列表查询（含 JOIN 条件）、`edit_user` 的验证/角色查询/角色更新/门店更新、`update_binding` 的验证/site_id 查询/更新子查询。`remove_user` 从 `DELETE` 改为 `UPDATE SET is_removed = true, removed_at = now()`，同时新增对 `user_assistant_binding` 的软删除（此前完全缺失）
- 修改结果：租户后台用户管理全链路正确过滤已移除记录。移除操作可追溯（保留 `removed_at` 时间戳），支持未来恢复

### `apps/backend/app/services/role.py`
- 变更类型：修改
- 原始原因：权限服务查询 `user_site_roles` 时需排除已移除记录
- 思路分析：3 处添加过滤：`get_user_permissions`、`get_user_sites`、`check_user_has_site_role`
- 修改结果：权限校验正确排除已移除用户的角色，防止已移除用户通过缓存令牌访问受保护资源

### `apps/backend/app/services/task_manager.py`
- 变更类型：修改
- 原始原因：任务管理器查询助教绑定时需排除已移除记录
- 思路分析：`_get_assistant_id` 添加 `AND is_removed = false`
- 修改结果：已移除的助教绑定不再被任务管理器使用，避免为已移除助教生成任务

### `apps/backend/app/services/task_generator.py`
- 变更类型：修改
- 原始原因：任务生成引擎查询助教绑定和门店列表时需排除已移除记录
- 思路分析：3 处添加过滤：门店列表查询、助教规模检查、入驻时间保护
- 修改结果：任务生成引擎正确排除已移除的助教绑定，不再为已移除助教生成或转移任务

### `apps/backend/app/services/performance_service.py`
- 变更类型：修改
- 原始原因：绩效服务查询助教信息时需排除已移除记录
- 思路分析：助教信息查询添加 `AND is_removed = false`
- 修改结果：绩效报表不再包含已移除助教的数据

### `docs/database/ddl/zqyy_app__auth.sql`
- 变更类型：修改
- 原始原因：DDL 基线需与实际数据库结构保持同步
- 思路分析：在 `user_site_roles` 和 `user_assistant_binding` 表定义中添加新字段和索引
- 修改结果：DDL 基线反映最新表结构

### `docs/database/BD_Manual_soft_delete_user_site_roles.md`
- 变更类型：新增
- 原始原因：数据库结构变更需配套 BD 手册文档
- 思路分析：记录软删除字段的用途、查询约定、索引策略
- 修改结果：为后续开发者提供软删除查询规范参考

## 合规检查

| 检查项 | 状态 |
|--------|------|
| DDL 迁移已执行 | ✅ 已在测试库执行（`new_migration_sql` 为空） |
| DDL 基线已更新 | ✅ `docs/database/ddl/zqyy_app__auth.sql` 已更新 |
| BD 手册已创建 | ✅ `docs/database/BD_Manual_soft_delete_user_site_roles.md` |
| API 文档同步 | ⚠️ `tenant_users.py` 变更需同步 `apps/backend/docs/API-REFERENCE.md` |
| OpenAPI Spec | ⚠️ 接口代码已变更但 OpenAPI spec 未同步，待手动导出 |
