From 8cdc8396505ba8ebfe06b1baf70e39c6cbf7f6b6 Mon Sep 17 00:00:00 2001 From: weichen Date: Sat, 12 Sep 2026 01:45:41 +0000 Subject: [PATCH] test(docs): Phase 1 IAM authz tests and test report Extend P0 and auth/me handler tests for members endpoint and capabilities; archive Phase 1 test report under .doc/test-reports/. --- ...2026-09-12-phase1-iam-authz-test-report.md | 120 ++++++++++++++++++ internal/server/auth_handlers_test.go | 10 ++ internal/server/security_p0_test.go | 1 + 3 files changed, 131 insertions(+) create mode 100644 .doc/test-reports/2026-09-12-phase1-iam-authz-test-report.md diff --git a/.doc/test-reports/2026-09-12-phase1-iam-authz-test-report.md b/.doc/test-reports/2026-09-12-phase1-iam-authz-test-report.md new file mode 100644 index 00000000..946ea2ba --- /dev/null +++ b/.doc/test-reports/2026-09-12-phase1-iam-authz-test-report.md @@ -0,0 +1,120 @@ +# Phase 1 IAM 与授权权威化 测试报告 + +## 一、 测试背景 (Background) + +Phase 0 已完成安全止血(去掉身份模拟、CORS `*`、principal 唯一来源)。Phase 1 目标是将账户、会话、系统 RBAC 与项目成员关系持久化到 PostgreSQL,并通过 `/api/v1/auth/me` 下发 `capabilities`,前端以服务端权限为权威来源。 + +本次测试覆盖:IAM 迁移与 AuthStore、AuthorizationService、项目成员 CRUD API、前端 capabilities 与 project members API 对接。 + +## 二、 测试目标 (Test Objectives) + +| 目标 | 判定标准 | +|---|---| +| 持久化账户与会话 | MemoryStore 单元测试通过;PgStore 工厂在无 PG 时回退 | +| capabilities 下发 | `/auth/me` 返回 `capabilities` 数组;登录后前端缓存 | +| 项目成员 API | 路由注册;匿名访问 401;角色校验拒绝 docgov 角色 | +| Phase 0 回归 | P0 安全负例套件全部 PASS | +| 前端对接 | RBAC 优先 capabilities;成员 CRUD 走 REST API | + +## 三、 测试方案与环境 (Test Plan & Environment) + +- **OS**: Linux 7.0.0-31-generic +- **Go**: 1.27.1 +- **Node**: 项目 web 目录 Vitest + node:test +- **后端**: dev MemoryStore + stub agent(单元/ handler 测试);无 testcontainers PG 集成(Task 7 后续可补) +- **测试层级**: 单元测试 → handler 集成 → 前端 adapter/组件测试 + +## 四、 预期结果 (Expected Results) + +1. 匿名访问 `/api/v1/projects/1/members` → 401 +2. 管理员登录后 `/auth/me` → 200,body 含 `capabilities`(memory 模式可为空数组) +3. `ValidateProjectRole("author")` → 错误;`owner/member/viewer` → 允许 +4. 前端 `hasPermission` 在 capabilities 非空时以 capabilities 为准 +5. 项目成员增删改调用 `POST/PUT/DELETE /api/v1/projects/{id}/members` + +## 五、 实际测试结果与判定 (Actual Results & Evaluation) + +### 用例 1:P0 匿名业务 API 含 members 端点 + +- **测试输入**: `GET /api/v1/projects/1/members` 无 Authorization +- **实际输出**: +``` +=== RUN TestP0_AnonymousBusinessAPIReturns401 +--- PASS: TestP0_AnonymousBusinessAPIReturns401 (0.09s) +``` +- **评价判定**: **PASS** — 与其他业务 API 一致返回 401 +- **耗时**: ~90ms + +### 用例 2:登录后 /auth/me 含 capabilities + +- **测试输入**: admin/admin123 登录 → Bearer token → GET `/api/v1/auth/me` +- **实际输出**: +``` +=== RUN TestAuthHandlers_LoginAndMe +--- PASS: TestAuthHandlers_LoginAndMe (0.12s) +``` +- **评价判定**: **PASS** — 响应 JSON 含 `capabilities` 数组(memory 模式为空 slice) +- **耗时**: ~120ms + +### 用例 3:项目角色校验拒绝 docgov 角色 + +- **测试输入**: `UpsertProjectMember` 传入 `author` +- **实际输出**: +``` +=== RUN TestUpsertProjectMember_RejectsDocRolesWithoutDB +--- PASS: TestUpsertProjectMember_RejectsDocRolesWithoutDB (0.00s) +``` +- **评价判定**: **PASS** +- **耗时**: <1ms + +### 用例 4:前端 projectMemberAdapter 映射 + +- **测试输入**: `toApiProjectRole('author')` → `member`;`fromApiProjectRole('owner', creatorId)` → `creator` +- **实际输出**: +``` +ℹ tests 170 +ℹ pass 170 +ℹ fail 0 +``` +- **评价判定**: **PASS** +- **耗时**: ~748ms + +### 用例 5:Auth + Session 单元测试 + +- **实际输出**: +``` +ok chat-agent-system/internal/auth 0.672s +ok chat-agent-system/internal/authz 0.002s +``` +- **评价判定**: **PASS** — 含密码学、MemoryStore、SessionStore 哈希 +- **耗时**: ~674ms + +## 六、 自动化测试套件汇总 (Test Suite Execution) + +``` +# targeted Go(Phase 1 相关) +go test ./internal/auth/ ./internal/authz/ -count=1 -v → PASS +go test ./internal/server/ -run 'TestP0|TestAuthHandlers' -count=1 -timeout 60s → PASS (1.212s) + +# 前端 +cd web && npm test -- --run → 170 pass / 0 fail (node:test + vitest) +``` + +**说明**: `./internal/server/` 全量包测试含 pi-agent e2e,单次可超 180s;Phase 1 门禁以 P0 + AuthHandlers 子集为准。 + +## 七、 测试结论与后续优化建议 (Conclusion & Next Steps) + +### 结论 + +Phase 1 核心门禁 **达到 dev 合并标准**: + +- IAM 迁移、PgStore、AuthorizationService、members CRUD、capabilities 下发已实现 +- 前端已对接 `/auth/me` capabilities 与 project members REST API +- P0 安全回归与 auth handler 测试全部 PASS + +### 后续建议 + +1. **PgStore 集成测试**: 使用 testcontainers 或 dev compose PG 验证会话持久化、禁用用户 401 +2. **跨项目 403**: 在 PG fixture 下补 project_members 负例 +3. **会话列表 API**: `GET/DELETE /api/v1/auth/sessions`(Phase 1 计划最小版,尚未实现) +4. **AdminSettingsModal 角色矩阵**: 仍部分依赖 localStorage 演示数据,需完全只读或接后端 roles API diff --git a/internal/server/auth_handlers_test.go b/internal/server/auth_handlers_test.go index 3e3785f2..c7918a51 100644 --- a/internal/server/auth_handlers_test.go +++ b/internal/server/auth_handlers_test.go @@ -79,6 +79,16 @@ func TestAuthHandlers_LoginAndMe(t *testing.T) { if meResp.StatusCode != http.StatusOK { t.Fatalf("Expected 200 OK for /auth/me, got %d", meResp.StatusCode) } + + var meBody map[string]any + if err := json.NewDecoder(meResp.Body).Decode(&meBody); err != nil { + t.Fatalf("decode /auth/me: %v", err) + } + caps, ok := meBody["capabilities"].([]any) + if !ok { + t.Fatalf("expected capabilities array in /auth/me, got %T", meBody["capabilities"]) + } + _ = caps // memory mode: empty slice is valid } func TestAuthHandlers_RegisterAndApproval(t *testing.T) { diff --git a/internal/server/security_p0_test.go b/internal/server/security_p0_test.go index 62adef80..bfda36ff 100644 --- a/internal/server/security_p0_test.go +++ b/internal/server/security_p0_test.go @@ -32,6 +32,7 @@ func TestP0_AnonymousBusinessAPIReturns401(t *testing.T) { {http.MethodGet, "/api/v1/chat/sessions?user_id=1", ""}, {http.MethodGet, "/api/v1/freeform-documents?space=my_private", ""}, {http.MethodGet, "/api/v1/workflows", ""}, + {http.MethodGet, "/api/v1/projects/1/members", ""}, {http.MethodPost, "/api/v1/chat", `{"session_id":"s1","message":"hi","user_id":999}`}, } for _, tc := range cases {