Files
user-system/docs/team/TECHNICAL_GUIDE.md
long-agent 9b1cea246e feat: permissions CRUD browser integration + E2E enhancements
Backend:
- permission_handler: 完善权限 CRUD 接口(列表/创建/更新/删除)
- auth_handler: 修复认证处理逻辑
- router: 新增权限管理路由
- handler_test: 新增权限 handler 测试覆盖

Frontend:
- permissions.ts/test.ts: 权限服务层完整实现
- profile/settings/service_tests: 服务适配器修正
- client.ts: HTTP 客户端健壮性增强
- vite.config.js: 构建配置优化
- E2E 脚本: run-playwright-cdp-e2e 大幅增强(权限流程覆盖)

Docs:
- REAL_PROJECT_STATUS: 状态更新
- PRODUCTION_CHECKLIST/QUALITY_STANDARD/TECHNICAL_GUIDE/PROJECT_EXPERIENCE_SUMMARY: 团队规范完善
- plans/2026-04-23: 权限浏览器 CRUD 设计方案

验证: go build 0错误
2026-04-24 07:30:18 +08:00

12 KiB
Raw Blame History

技术指南

更新时间2026-03-25

本文件不再承载泛化培训内容,改为当前项目的技术入口索引。

1. 先读什么

建议阅读顺序:

  1. README.md
  2. docs/status/REAL_PROJECT_STATUS.md
  3. docs/team/QUALITY_STANDARD.md
  4. docs/team/PRODUCTION_CHECKLIST.md
  5. docs/team/PROJECT_EXPERIENCE_SUMMARY.md

2. 当前项目最重要的真实结论

  • 主验收路径是 cd frontend/admin && npm.cmd run e2e:full:win
  • 当前闭环的是浏览器级真实 E2E不是完整 OS 级自动化
  • smoke 仅用于诊断,不是运行时依赖
  • 非测试代码中的 panic、fake success、mock runtime provider 都应视为缺陷

3. 常用命令

后端

go test ./... -count=1
go vet ./...
go build ./cmd/server

前端

cd frontend/admin
npm.cmd run lint
npm.cmd run build

真实浏览器

cd frontend/admin
npm.cmd run e2e:full:win

4. 常见工程经验

  • 如果结论依赖真实用户流程,就不要只跑单元测试。
  • 如果终端出现乱码,不要把乱码文本继续复制进业务逻辑。
  • 如果错误分级依赖字符串子串,后续大概率会回归;优先改成显式错误类型。
  • 如果 service 依赖具体 repository 类型断言,后续替换实现或测试 mock 会变脆。

5. 文档维护规则

  • 状态变更:更新 docs/status/REAL_PROJECT_STATUS.md
  • 规则变更:更新 docs/team/QUALITY_STANDARD.md
  • 发布门槛变更:更新 docs/team/PRODUCTION_CHECKLIST.md
  • 阶段性经验:更新 docs/team/PROJECT_EXPERIENCE_SUMMARY.md

6. 2026-04-10 多轮 Review 实操指引

6.1 如何判断“是否闭环”

  • 结论优先级:文档支持的主入口 > repo 内单步命令 > 局部 smoke、单个用例、-short 结果。
  • 只要 go test ./... -count=1 仍被 LL_001 卡住,或 npm.cmd run e2e:full:win 仍未跑通,就不能把项目表述为“全量验证通过”。
  • go build ./cmd/server 通过,只能证明 repo 内该命令通过;不能自动推出包装脚本里的 build 路径也稳定。

6.2 如何审查 stub 转 live 的高风险改动

  • 先看权限边界:调用者是否真的具备读取或修改目标资源的资格。
  • 再看治理边界:是否存在 self-actionlast-admin、越权枚举、越权提升等问题。
  • 再看一致性:多步写操作是否在事务内;失败时是否有显式回滚。
  • 最后看文档与测试:是否补了负向测试、边界测试、回滚测试,以及状态文档与规范文档。

6.3 当前需要持续关注的热点

  • internal/service/scale_test.goLL_001 仍是全量 go test ./... -count=1 的门槛。
  • frontend/admin/scripts/run-playwright-auth-e2e.ps1:需要优先保证文档支持的 e2e:full:win 入口自身稳定,而不是只验证子命令。
  • frontend/admin/src/components/common/ui-consistency.test.tsx:原生弹窗噪声仍会污染测试结果,应继续清理。
  • internal/api/handler/user_handler.gointernal/service/user_service.goRBAC / 管理员治理逻辑需要持续按越权、事务、自删、最后管理员等维度审查。

2026-04-18 优化修复入口

本附录是任何工程师或智能体在当前仓库状态下开启新一轮优化或修复批次时的强制入口。

1. 改代码前的阅读顺序

开始前按以下顺序阅读:

  1. docs/status/REAL_PROJECT_STATUS.md
  2. docs/code-review/FULL_CODE_REVIEW_REPORT_2026-04-17.md
  3. docs/team/QUALITY_STANDARD.md
  4. docs/team/PROJECT_EXPERIENCE_SUMMARY.md

用途:

  • REAL_PROJECT_STATUS 告诉你当前已经验证过的工作区真相。
  • FULL_CODE_REVIEW_REPORT 告诉你已经复核过的风险清单和任务分级。
  • QUALITY_STANDARD 告诉你当前必须遵守的工程约束。
  • PROJECT_EXPERIENCE_SUMMARY 告诉你哪些失败模式已经真实消耗过项目时间。

2. 先执行的新鲜命令

在做出任何“当前状态”判断前,先执行:

go build ./cmd/server
go vet ./...
go test ./... -count=1

cd frontend/admin
npm.cmd run lint
npm.cmd run build

如果本轮工作涉及认证、会话、路由守卫、导航、弹窗防线或用户主流程,还要执行:

cd frontend/admin
npm.cmd run e2e:full:win

3. 当前发布阻塞级关注点

在一般优化之前,优先处理这些区域:

  • internal/api/handler/user_handler.go UpdateUser authorization boundary
  • internal/service/auth.go password login MFA/device-trust enforcement
  • internal/service/auth.go refresh-token revocation persistence failure handling
  • internal/api/middleware/cors.go unsafe default CORS behavior
  • internal/repository/user.go cursor/sort mismatch in ListCursor
  • internal/service/password_reset.go single-use verification code consumption semantics

4. 修复批次工作规则

  • 不要把历史绿灯当作当前证据。
  • 不要在没有分别验证的情况下,把门禁刷新、安全修复和重构混在同一个“已完成”结论里。
  • 修 bug 或安全问题时,没有对应回归测试,就不要把任务提升为“完成”。
  • 不要让包装脚本掩盖项目正式支持主命令的失败。

5. 文档更新规则

当一轮修复改变了真实结论时,必须在同一批次同步更新:

  • docs/status/REAL_PROJECT_STATUS.md
  • 规则变化时更新 docs/team/QUALITY_STANDARD.md
  • 产出可复用经验时更新 docs/team/PROJECT_EXPERIENCE_SUMMARY.md

0. 2026-04-23 Latest Technical Snapshot

Use this section as the current workspace truth when older notes elsewhere in this file describe earlier failures.

Main Acceptance Path

  • The supported browser-level gate remains cd frontend/admin && npm.cmd run e2e:full:win.
  • That gate was re-run green on 2026-04-23 after fixes in device pagination flow, backend-response envelope decoding, settings-service adapter alignment, and Playwright CDP selector and suite-retry stability.

Recovery Notes That Matter

  • DevicesPage must keep the request cursor separate from the response next_cursor; otherwise the initial load can auto-chain into extra /admin/devices requests and trigger rate limiting.
  • Frontend services must decode backend envelopes by their actual fields and by the shared HTTP client contract. The recovered cases in this round were list, deliveries, accounts, and /admin/settings direct data.
  • Late-stage E2E scenarios are more stable when assertions target route, heading, and role-based locators instead of broad page text matches.
  • If suite retry reuses the same backend process, one-time preconditions such as admin-bootstrap must be refreshed from live backend capabilities before the next attempt starts.

Boundary

  • This snapshot proves browser-level real E2E closure in the current workspace.
  • It does not by itself prove the full backend matrix, OS-level automation, or live third-party provider verification.

2026-04-23 Late-Suite E2E Triage Order

Use this order before blaming the browser wrapper when cd frontend/admin && npm.cmd run e2e:full:win fails in later admin scenarios.

  1. Check whether the failing page consumes an API whose response envelope or field names changed.
  2. Check whether the page state machine, pagination flow, or derived state issued unexpected follow-up requests.
  3. Check whether the failing assertion uses a broad text locator where route, heading, role, or labeled-control matching would be more precise.
  4. Only after the first three checks stay clean, investigate CDP session lifecycle, page/context closure, or local browser startup instability.

2026-04-23 Password Reset And CDP Recovery Notes

Root Cause

  • The password-reset browser gap came from a backend contract omission: /api/v1/auth/capabilities returned password_reset=false even when passwordResetHandler was mounted and the reset routes were live.

Minimal Fix

  • AuthHandler now carries the password-reset capability bit and fills caps.PasswordReset in GetAuthCapabilities().
  • Router assembly now synchronizes that bit from the same passwordResetHandler != nil condition that mounts the reset routes.

Browser Flow Proof

  • The supported browser suite now proves the real password-reset chain end to end:
    • admin creates a real user
    • login surface exposes the forgot-password entry
    • /api/v1/auth/forgot-password emits a real SMTP-captured reset link
    • /api/v1/auth/password/validate and /api/v1/auth/reset-password complete through the browser
    • the user logs in with the new password

Stability Rule

  • When headless-shell closes the last live target late in the suite, reconnect the CDP browser connection and reacquire the persistent page before declaring the whole run failed.

2026-04-23 Permissions CRUD And Full Matrix Technical Snapshot

Use this section as the newest technical snapshot when earlier 2026-04-23 notes describe only the 19-scenario gate.

Main Acceptance Path

  • The supported browser-level gate remains cd frontend/admin && npm.cmd run e2e:full:win.
  • That gate was re-run green on 2026-04-23 after adding permissions-management-crud, fixing permissions payload compatibility, fixing auth-header selection under concurrent refresh state, and stabilizing CDP observation for proxied permission calls.
  • The same branch state also re-ran go test ./... -count=1, go vet ./..., go build ./cmd/server, cd frontend/admin && npm.cmd run test:run, cd frontend/admin && npm.cmd run lint, and cd frontend/admin && npm.cmd run build successfully.

Recovery Notes That Matter

  • The permissions frontend adapter must accept raw numeric backend type values, normalize them to the frontend string enum, and serialize writes back to the backend numeric form.
  • The permissions backend handler must continue accepting menu type=0 and status payloads delivered as either numeric or string values, because real browser flows and clients can send both forms during incremental rollout.
  • A valid non-expired access token must still be attached to requests even when a different refresh flow is already in flight. Refresh state alone is not evidence that the current request should lose authentication.
  • In the permissions CRUD scenario, the page and backend were healthy even when Playwright CDP request and response observers missed the proxied /api/v1/permissions call. The reliable proof path was the in-page fetch diagnostic log plus the post-submit UI refresh.
  • Ant modal leave animations can keep intercepting clicks after the dialog is visually closing. Scenario code should wait for the modal to stop blocking interaction before the next action.
  • Vite 8 on Windows with --configLoader native can fail the supported build path if project root resolution is implicit. The stable fix is an explicit root in vite.config.js.

Boundary

  • This snapshot proves browser-level real E2E closure with 20 supported scenarios in the current workspace.
  • It does not by itself prove OS-level automation, live third-party provider verification, or remote-repository publication status.

2026-04-24 Profile Security Contract Recovery

Root Cause

  • The profile password form used the UI model (current_password, confirm_password) all the way through the service layer, but the real backend PUT /users/:id/password handler binds old_password and new_password only.

Minimal Fix

  • frontend/admin/src/services/profile.ts now maps the UI request to the real backend payload shape before calling the shared HTTP client.
  • frontend/admin/scripts/run-playwright-cdp-e2e.mjs now couples password and TOTP fetch waits to the submit action that triggers them, so a later locator failure does not leave an orphaned background waiter that hides the real error.

Browser Flow Proof

  • The targeted profile page and service regression set is green.
  • The supported browser-level gate cd frontend/admin && npm.cmd run e2e:full:win is green with 20 scenarios, including profile-and-security.

Stability Rule

  • When a scenario uses asynchronous fetch diagnostics for proof, create the waiter in the same control flow as the triggering action and tear it down implicitly with that action path. A background waiter that survives a failed action is a runner bug because it can replace the primary failure with misleading page-closed noise.