docs: Phase 2 计划复审修复(blank 出厂源=jiancai墙提示词/新租户管理员must_change/两处测试时点锚修正)

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-10-13 07:44:35 +08:00
parent f5d4c74f53
commit d088264ca0
@@ -78,7 +78,7 @@ def test_login_lockout_after_5_fails(app_client): # 第 6 次 429/423,15 分
def test_token_expiry(app_client, freezer_or_short_ttl) # 过期 token → 401
def test_protected_requires_auth(app_client): # 无 Authorization → 401
def test_change_password_flow(app_client): # 旧密改新密成功;旧密失效;must_change 清零
def test_tenant_admin_role_scoped(app_client): # 租户管理员 token 访问超管端点 → 403
def test_tenant_admin_role_scoped(app_client): # 依赖工厂直测(require_super 拿租户管理员 UserContext → HTTPException 403);端点级覆盖在 Task 5
def test_logout_invalidates_token(app_client)
```
@@ -104,7 +104,7 @@ def test_logout_invalidates_token(app_client)
def test_platform_api_bypasses_tenant_resolution(app_client):
# 未知 Host 下 POST /api/platform/auth/login 可达(不被中间件 404)
def test_platform_prefix_not_open(app_client):
# 无 token 访问 /api/platform/tenants → 401(豁免≠放行,认证守护)
# 无 token 打已存在的受保护 auth 端点(POST /api/platform/auth/logout)→ 401(豁免≠放行,认证守护)
def test_prefix_match_precise(app_client):
# /api/platform-evil/ 仍走租户解析(未知 Host → 404)——豁免必须 startswith("/api/platform/") 精确
```
@@ -159,7 +159,7 @@ def test_tenant_admin_cannot_create_tenant(...) # 403
```
- [ ] **Step 2: 实现**(全部 require_super,除标注)
- `POST /api/platform/tenants`:profile ∈ {auto, jiancai, blank}——auto/jiancai 读 seed_profiles/<slug>/ 合并出首版快照(tenant.json 的 config + wall.json + prompts/*.md 嵌入);blank = 出厂默认;slug 校验(^[a-z0-9-]+$、不可变、与现有租户不撞);同时建租户管理员账号
- `POST /api/platform/tenants`:profile ∈ {auto, jiancai, blank}——auto/jiancai 读 seed_profiles/<slug>/ 合并出首版快照(tenant.json 的 config + wall.json + prompts/*.md 嵌入);**blank = 其余组取 DEFAULT_CONFIG + wall/prompts 取 jiancai 出厂档案**(compile_wall 要求 wall 全字段在位、PromptProvider 要求四件套——DEFAULT_CONFIG["wall"]={} 会加载即炸;对齐既有先例 DEFAULT_WALL/DEFAULT_PROVIDER 均锚 jiancai 档案);slug 校验(^[a-z0-9-]+$、不可变、与现有租户不撞);同时建租户管理员账号(**must_change_password 置 True**——Task 2 的 409 语义对新租户管理员同样生效)
- `POST /api/platform/tenants/{slug}/sites`(站点 CRUD:建站/停用);`POST .../sites/{site}/domains`、`DELETE .../domains/{domain}`
- `PATCH /api/platform/tenants/{slug}`(name/status;status≠active 触发 registry 释放)
- 写操作后 `registry_reload(slug)`;域名表变更后重建域名索引(reload 内已做)
@@ -193,7 +193,7 @@ def test_tenant_admin_scoped_config(...) # jiancai 管理员能改自己、
- [ ] **Step 2: 实现校验管线 `config_validation.py`**
- `validate_group(group, payload, context) -> list[str]`(错误清单):类型检查(engine 组 int/bool;brand 字符串/字符串列表;contact 开关与 template_languages、misc 映射也纳入类型校验)、wall → `compile_wall`(复用全部既有校验)、prompts 大小上限(company_facts ≤50KB、其余 ≤100KB)、email notify_emails 格式、push/ai 数值范围、`context.other_prefixes` 查重
- `config_routes.py`:`GET /api/platform/tenants/{slug}/config`(当前 merged+version);`PUT .../config/{group}`(校验→整份快照写 MAX(version)+1【updated_by=当前用户, comment 可选】→ registry_reload);`POST .../config/{group}/reset`(**重置出厂**:拷出厂档案该组为新版本——auto/jiancai 档案取 seed_profiles,blank/无档案租户取 DEFAULT_CONFIG 组;spec §5.4);`GET .../config/versions`(列表:版本/时间/作者/备注);`POST .../config/rollback` `{version}`(复制为新版本);`POST .../wall/test`(试金石:compile 请求体里的 wall【或当前+覆盖】→ 逐句调 boundary_filter 纯函数给判定)
- `config_routes.py`:`GET /api/platform/tenants/{slug}/config`(当前 merged+version);`PUT .../config/{group}`(校验→整份快照写 MAX(version)+1【updated_by=当前用户, comment 可选】→ registry_reload);`POST .../config/{group}/reset`(**重置出厂**:拷出厂档案该组为新版本——auto/jiancai 档案取 seed_profiles;blank 租户的 wall/prompts 组取 jiancai 出厂档案,其余组取 DEFAULT_CONFIG;spec §5.4);`GET .../config/versions`(列表:版本/时间/作者/备注);`POST .../config/rollback` `{version}`(复制为新版本);`POST .../wall/test`(试金石:compile 请求体里的 wall【或当前+覆盖】→ 逐句调 boundary_filter 纯函数给判定)
- **平台设置 CRUD**(spec §7.3 平台配置页后端):`GET/PUT /api/platform/settings`(仅超管;PlatformSetting 表读写——集团默认 AI 凭据/默认 SMTP;**resolver 回退链接入 platform_settings 归 Phase 3**——本阶段先落存储与接口)
- 鉴权:超管任意租户;租户管理员限自己(require_tenant)