From 40c56c6b336ad441dfd2948eb4e1192e767baf66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=84=A6=E9=BE=99=E8=A8=80?= Date: Tue, 22 Sep 2026 13:39:18 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=A1=E5=88=92=EF=BC=9A=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=89=B9=E6=AC=A1=E5=AE=9E=E6=96=BD=E5=89=8D?= =?UTF-8?q?=E7=BD=AE=E5=A5=91=E7=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2026-09-22-test-data-batch-cleanup.md | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/docs/superpowers/plans/2026-09-22-test-data-batch-cleanup.md b/docs/superpowers/plans/2026-09-22-test-data-batch-cleanup.md index 6f35153..cdc0308 100644 --- a/docs/superpowers/plans/2026-09-22-test-data-batch-cleanup.md +++ b/docs/superpowers/plans/2026-09-22-test-data-batch-cleanup.md @@ -339,7 +339,7 @@ git commit --only shierfeng-fastapi-backend/module_business/entity/do/test_batch **Interfaces:** - Consumes: `BizTestBatch`、`BizTestBatchUser`、`CurrentUserModel`、请求头 `X-Test-Batch-Id`。 - Produces: `TestBatchScope(batch_id, mode, status, writable)`、`TestBatchScopeDependency(write: bool = False)`、`TestBatchAccessService.assert_super_admin(current_user: CurrentUserModel) -> None`、`lock_active_batch(db: AsyncSession, scope: TestBatchScope) -> BizTestBatch | None`。 -- Error contract: 不合法头返回 `ServiceWarning('测试批次标识必须为正整数')`;未授权或状态失效返回 `PermissionException(data={'reason': 'TEST_BATCH_UNAVAILABLE'}, message='当前测试批次不可用')`。 +- Error contract: 不合法头返回 `ServiceWarning('测试批次标识必须为正整数')`;未授权或批次已清理返回 `PermissionException(data={'reason': 'TEST_BATCH_UNAVAILABLE'}, message='当前测试批次不可用')`;写请求命中已关闭批次时返回同一 `reason` 与明确文案 `当前测试批次已关闭`。 - Test fixtures: `make_current_user(user_id=7, permissions=None)`、`make_admin()`、`make_test_scope(batch_id, status='ACTIVE', writable=True)` 供后续测试统一使用。 - [ ] **Step 1: 写上下文解析与越权失败测试** @@ -368,15 +368,24 @@ class TestBatchAccessTest(unittest.IsolatedAsyncioTestCase): `test_batch_fixtures.py` 提供统一构造器: ```python -def make_current_user(user_id: int = 7, permissions: list[str] | None = None) -> CurrentUserModel: +def make_current_user( + user_id: int = 7, + permissions: list[str] | None = None, + *, + admin: bool = False, +) -> CurrentUserModel: return CurrentUserModel( permissions=permissions or [], roles=[], - user=UserInfoModel(userId=user_id, userName='admin' if user_id == 1 else f'user-{user_id}'), + user=UserInfoModel( + userId=user_id, + userName='admin' if user_id == 1 else f'user-{user_id}', + admin=admin, + ), ) def make_admin() -> CurrentUserModel: - return make_current_user(1, ['*:*:*']) + return make_current_user(1, ['*:*:*'], admin=True) def make_test_scope(batch_id: int, status: str = 'ACTIVE', writable: bool = True) -> TestBatchScope: return TestBatchScope(batch_id=batch_id, mode='TEST', status=TestBatchStatus(status), writable=writable) @@ -1753,7 +1762,7 @@ git commit --only shierfeng-fastapi-frontend/src/api/system/testBatch.js \ **Interfaces:** - Consumes: Tasks 3、7、8 的批次 service,Task 4/5 的旧 DELETE 固定拒绝,Task 10 的批次管理和纳入入口。 -- Produces: SQL 菜单只保留批次清理权限;Web 无物理删除按钮/调用;旧 DELETE 路由改用对应页面 `:list` 权限后返回统一业务拒绝。 +- Produces: SQL 菜单移除八个旧删除权限并新增八个批次管理权限;Web 无物理删除按钮/调用;旧 DELETE 路由改用对应页面 `:list` 权限后返回统一业务拒绝。 - Exact contract: 13 个 controller、86 条目标路由、85 条 interface-auth 依赖、61 个唯一权限、18 个页面权限、43 个按钮权限、41 条写路由。 - [ ] **Step 1: 先更新精确权限与无删除入口失败契约** @@ -2054,13 +2063,14 @@ git commit --only shierfeng-fastapi-app/src/api/system/testBatch.js \ ```text 1. 备份并在隔离实例完成恢复演练;恢复校验失败则停止。 -2. 只读盘点目标库 18 张业务表、16 个批次字段、索引、外键和 on_delete;任一差异则停止。 -3. 在 staging 应用对应方言补丁,既有 test_batch_id 非 NULL 行数必须为 0。 -4. 发布后端、Web、PDA;保持 TEST_BATCH_ONLINE_PURGE_MAX_ROWS=0。 -5. 验证正式模式列表、扫码、首页和六报表与发布前基线一致。 -6. 用 staging 数据分别压测 100、500、1000、逐级增加的闭包,记录锁等待、事务耗时和回滚耗时。 -7. 取满足运维窗口和数据库锁等待预算的最大实测行数,配置正整数上限并重启后端。 -8. 首次创建批次、首次纳入旧数据和首次清理分别走独立变更审批。 +2. 只读盘点目标库现有业务表、索引和外键,并确认即将新增的 2 张批次表及 16 个 `test_batch_id` 字段尚不存在;结构与补丁前置不符则停止。 +3. 在 staging 应用对应方言补丁,验证 18 张业务表、16 个批次字段、索引、外键和 `on_delete`,且既有 `test_batch_id` 非 `NULL` 行数必须为 0。 +4. 在已审批维护窗口内先对目标库应用同一补丁,立即重复结构和既有数据校验;任一检查失败则停止应用发布并按数据库变更回退预案处理。 +5. 发布后端、Web、PDA;保持 `TEST_BATCH_ONLINE_PURGE_MAX_ROWS=0`。 +6. 验证正式模式列表、扫码、首页和六报表与发布前基线一致。 +7. 用 staging 数据分别压测 100、500、1000、逐级增加的闭包,记录锁等待、事务耗时和回滚耗时。 +8. 取满足运维窗口和数据库锁等待预算的最大实测行数,配置正整数上限并重启后端。 +9. 首次创建批次、首次纳入旧数据和首次清理分别走独立变更审批。 ``` 手册给出 MySQL `information_schema` 与 PostgreSQL `pg_catalog` 的只读查询,用于核对字段、索引、外键和删除规则;给出清理失败后的检查项,禁止手工补删半条链。