# OIDC Platform AI 快速上手技术文档 > 目标:让后续接手的 AI 或工程师不需要从零扫完整仓库,就能理解项目边界、数据流、模块关系、常见修改入口和验证方式。 ## 1. 项目一句话定位 这是一个自托管 OIDC / OAuth2 身份认证平台。用户在平台内通过邮箱注册登录,并绑定 GitHub、Google、GitLab、Gitee、Discord、Microsoft、Apple、Telegram、QQ、微信、手机号、自定义 OAuth2 等身份来源来提升“信任等级”。下游业务系统只需要接入本平台的标准 OIDC 端点,并配置最低信任等级、邮箱验证要求和访问规则,即可获得统一认证、准入控制和基础风控能力。 核心产品形态: - 用户中心:注册、登录、找回密码、邮箱验证、社交绑定、会话、授权应用、Passkey、信任等级查看。 - 开发者门户:创建 OIDC 客户端、管理密钥和回调地址、查看授权用户、举报/拉黑用户。 - 管理后台:用户、客户端、Provider、信任等级规则、系统设置、审计日志、签名密钥、风控列表。 - 标准协议服务:`/.well-known/openid-configuration`、`/oauth2/authorize`、`/oauth2/token`、`/oauth2/userinfo`、`/jwks.json`。 ## 2. 技术栈和运行命令 ### 后端 - 语言:Go `1.25.6`,module 为 `github.com/anthropic/oidc-platform`。 - HTTP 路由:`chi`。 - OIDC/OAuth2 引擎:`ory/fosite`。 - 配置:`viper`,支持 YAML + `OIDC_*` 环境变量覆盖。 - 存储:SQLite 或 PostgreSQL。 - 缓存:SQLite 模式默认内存缓存;PostgreSQL 模式使用 Redis。 - Passkey:`go-webauthn/webauthn`。 - 密码:Argon2id。 ### 前端 - Vue 3 + Vite + TypeScript + Pinia + Vue Router + Vue I18n。 - API 统一走 `/api/v1`,fetch 带 `credentials: 'same-origin'`。 ### 常用命令 ```bash # 后端测试 go test ./... # 后端格式化 gofmt -w # 前端构建 cd frontend && npm run build # 前端开发 cd frontend && npm run dev # 构建后端二进制 go build -o oidc-platform ./cmd/server # Docker Compose 启动 Postgres + Redis + App cp .env.example .env docker compose up --build ``` ### 当前已验证命令 最近一次验证已通过: ```bash go test ./... cd frontend && npm run build ``` ## 3. 目录地图 ```text cmd/server/ 服务启动入口、依赖注入、种子数据、后台任务 configs/ YAML 配置,含 config.yaml / config.sqlite.yaml db/migrations/ 数据库迁移,PostgreSQL 风格;SQLite 适配器内有兼容迁移执行 db/queries/ sqlc 查询定义,当前仓库实际主要使用手写 repository frontend/ Vue 3 SPA internal/adapter/ 外部系统和基础设施适配层 memcache/ 内存缓存 redis/ Redis 缓存 smtp/ 邮件发送 social/ 第三方 OAuth/OIDC Provider sqlite/ SQLite 仓储实现 postgres/ PostgreSQL 仓储实现 internal/config/ 配置结构和加载逻辑 internal/domain/ 领域数据结构 internal/handler/ HTTP handler 和中间件 internal/oidcprovider/ fosite 封装、OIDC session/claims internal/port/ 接口边界:repository、cache、email、social provider 等 internal/router/ HTTP 路由总表 internal/service/ 业务服务层 ``` 前端目录: ```text frontend/src/api/client.ts API 包装 frontend/src/router/index.ts 路由和权限守卫 frontend/src/stores/auth.ts 登录态、用户信息、开发者权限 frontend/src/i18n/ 中英文文案 frontend/src/layouts/ 公开页、登录页、用户中心、开发者、管理员布局 frontend/src/pages/ 页面组件 frontend/src/composables/ 公共组合逻辑,如 public config、Turnstile、密码策略 ``` ## 4. 运行时组装关系 启动入口:`cmd/server/main.go`。 核心流程: ```mermaid flowchart TD A[config.Load] --> B[bootstrap] B --> C[选择数据库: sqlite/postgres] C --> D[初始化 repo/cache] D --> E[Social Registry] E --> F[Service 层] F --> G[OIDC Provider] G --> H[Handler 层] H --> I[router.NewRouter] I --> J[HTTP Server] ``` `cmd/server/bootstrap.go` 做了大部分运行时组装: - 根据 `database.driver` 选择 SQLite 或 PostgreSQL。 - SQLite:`internal/adapter/sqlite` + `memcache`。 - PostgreSQL:`internal/adapter/postgres` + `redis`。 - 初始化所有 repository。 - 初始化 `SecretCipher`,用于客户端密钥加密。 - 初始化 Social Provider Registry。 - 初始化 SMTP sender。 - 初始化业务服务。 - 初始化 Passkey/WebAuthn。 - 加载或创建 RSA signing key。 - 创建 fosite OAuth2/OIDC provider。 - 创建所有 handler。 - 启动后台任务。 - 种子管理员、Provider 配置、全局设置。 - 找到 `frontend/dist` 并交给 SPA handler。 后台任务: - 每 15 分钟清理过期用户 session。 - 每 1 小时重算全部用户信任等级。 - 如果 `social_auth_sync.enabled=true`,定期同步第三方绑定授权状态。 ## 5. 配置模型 配置入口:`internal/config/config.go`。 加载规则: - 配置文件名:`config.yaml`。 - 搜索路径:`./configs`、`.`、`/etc/oidc`。 - 环境变量前缀:`OIDC_`。 - `.` 会映射为 `_`,如 `server.public_url` 可由 `OIDC_SERVER_PUBLIC_URL` 覆盖。 关键配置: ```text server.host / port / public_url / issuer database.driver / dsn / postgres host 等 redis.host / port session.cookie_name / secure / same_site / ttl security.password_* / max_login_attempts / lockout_duration oauth2..* social_auth_sync.enabled / interval / batch_size smtp.* secrets.client_secret_encryption_key webauthn.rp_id / rp_origin / rp_display_name admin.email / admin.password ``` 常用文件: - `configs/config.yaml`:默认主配置。 - `configs/config.sqlite.yaml`:SQLite 最小配置。 - `.env.example`:Docker Compose 环境变量模板。 - `docker-compose.yml`:PostgreSQL + Redis + App。 注意:`Dockerfile` 只构建 Go 服务并复制 `configs`、`db/migrations`。如果要容器内服务前端,需保证构建上下文里有可用的前端产物,或调整 Dockerfile 先构建 `frontend/dist`。 ## 6. HTTP 路由总览 路由入口:`internal/router/router.go`。 ### 公开路由 ```text GET /healthz GET /readyz GET /.well-known/openid-configuration GET /jwks.json ``` ### OIDC / OAuth2 ```text GET /oauth2/authorize POST /oauth2/token POST /oauth2/revoke POST /oauth2/introspect GET /oauth2/userinfo POST /oauth2/userinfo ``` `/oauth2/authorize` 支持平台登录态检查、客户端准入检查、用户同意页挑战。 ### API `/api/v1` 公开设置: ```text GET /api/v1/settings/public GET /api/v1/settings/password-policy ``` 认证: ```text POST /api/v1/auth/register/code POST /api/v1/auth/register POST /api/v1/auth/login POST /api/v1/auth/logout POST /api/v1/auth/verify-email POST /api/v1/auth/forgot-password POST /api/v1/auth/reset-password POST /api/v1/auth/passkey/begin POST /api/v1/auth/passkey/finish ``` 社交登录/绑定: ```text GET /api/v1/social/providers GET /api/v1/social/{provider}/begin GET /api/v1/social/{provider}/callback ``` 登录用户: ```text GET /api/v1/me PUT /api/v1/me PUT /api/v1/me/alias PUT /api/v1/me/password GET /api/v1/me/bindings DELETE /api/v1/me/bindings/{provider} GET /api/v1/me/security-level POST /api/v1/me/resend-verification GET /api/v1/me/sessions DELETE /api/v1/me/sessions/{id} GET /api/v1/me/authorized-apps DELETE /api/v1/me/authorized-apps/{clientId} ``` 用户 Passkey: ```text POST /api/v1/me/passkeys/register/begin POST /api/v1/me/passkeys/register/finish GET /api/v1/me/passkeys DELETE /api/v1/me/passkeys/{id} PUT /api/v1/me/passkeys/{id} ``` OIDC 同意页: ```text GET /api/v1/consent/context POST /api/v1/consent/accept POST /api/v1/consent/reject ``` 开发者门户: ```text GET /api/v1/developer/status GET /api/v1/developer/apps POST /api/v1/developer/apps GET /api/v1/developer/apps/{id} PUT /api/v1/developer/apps/{id} DELETE /api/v1/developer/apps/{id} POST /api/v1/developer/apps/{id}/rotate-secret GET /api/v1/developer/apps/{id}/users POST /api/v1/developer/apps/{id}/users/{user_id}/block DELETE /api/v1/developer/apps/{id}/users/{user_id}/block POST /api/v1/developer/apps/{id}/users/{user_id}/report POST /api/v1/developer/apps/{id}/report-user ``` 管理员: ```text /api/v1/admin/users... /api/v1/admin/clients... /api/v1/admin/security-rules... /api/v1/admin/providers... /api/v1/admin/alias-restrictions... /api/v1/admin/settings... /api/v1/admin/audit-log /api/v1/admin/stats /api/v1/admin/keys... /api/v1/admin/risk... ``` 管理员路由都需要 session + `admin` 或 `super_admin`。 ## 7. API 响应约定 定义在 `internal/handler/response.go`。 普通 API 响应统一包裹: ```json { "success": true, "data": {}, "meta": { "total": 100, "offset": 0, "limit": 20 } } ``` 错误: ```json { "success": false, "error": { "code": "invalid_input", "message": "..." } } ``` 例外:OIDC 标准端点和 `/oauth2/userinfo` 会按协议或 raw JSON 输出。 请求 JSON 解码使用 `DecodeJSON`,开启 `DisallowUnknownFields`,所以前端传多余字段会被拒绝。 用户身份字段边界: - `id`:内部 UUID,供数据库外键、session、管理端操作路径、开发者应用用户封禁/举报等内部操作使用。 - `uid`:面向用户展示和搜索的纯数字 UID,不能替代内部主键。 - OIDC `sub` 默认仍使用内部 UUID,避免破坏已有客户端的用户关联。 - 前端显示“UID”时只展示 `uid`;需要调用操作接口时传 `id`。 ## 8. 后端分层和模块边界 ### 8.1 domain 层 路径:`internal/domain/`。 主要领域对象: | 文件 | 作用 | | --- | --- | | `user.go` | 用户、社交绑定、绑定状态、授权检查状态 | | `client.go` | OIDC 客户端、访问规则、开发者用户摘要 | | `security_level.go` | 信任等级规则、条件类型、等级变更记录 | | `provider.go` | Provider 枚举、Provider 配置、自定义 OAuth2 配置解析 | | `session.go` | 平台用户 session | | `risk.go` | 风控举报、风控名单、审计日志、签名密钥等 | | `passkey.go` | Passkey/WebAuthn 凭据 | 领域层只放数据结构和轻量判断,不直接访问数据库或 HTTP。 ### 8.2 port 层 路径:`internal/port/`。 作用是定义接口边界: - `repository.go`:所有 repository interface。 - `cache.go`:缓存 interface。 - `email.go`:邮件发送 interface。 - `social_provider.go`:社交 Provider interface 和 Registry。 - `sms_provider.go`:短信能力边界。 新增业务能力时优先在 port 层加接口,再在 adapter 层实现。 ### 8.3 adapter 层 路径:`internal/adapter/`。 | 子目录 | 作用 | | --- | --- | | `sqlite/` | SQLite repository、迁移、fosite store | | `postgres/` | PostgreSQL repository、迁移、fosite store | | `redis/` | Redis cache 实现 | | `memcache/` | 内存 cache 实现 | | `smtp/` | 邮件发送 | | `social/` | GitHub/Google/Discord 等 Provider 适配 | SQLite 和 PostgreSQL 的 repo 名称基本一一对应。修改持久化字段时通常要同步: 1. `db/migrations/*.sql` 2. `internal/domain/*.go` 3. `internal/port/repository.go` 4. `internal/adapter/sqlite/*_repo.go` 5. `internal/adapter/postgres/*_repo.go` ### 8.4 service 层 路径:`internal/service/`。 | 服务 | 责任 | | --- | --- | | `AuthService` | 注册、登录、登出、邮箱验证、找回密码、密码修改、登录锁定 | | `SessionService` | session 创建、读取、撤销、cookie 生命周期相关辅助 | | `SocialService` | 社交绑定、社交登录、Provider profile 保存、绑定状态同步 | | `SecurityLevelService` | 信任等级规则评估、等级重算、等级详情和缺失条件 | | `ClientService` | OIDC 客户端 CRUD、密钥加密/解密/轮换、配置校验 | | `AccessControlService` | 客户端准入:最低等级、邮箱验证、邮箱/IP/用户 allow/deny、别名限制 | | `AdminService` | 管理端聚合操作:用户、Provider、设置、签名密钥、Passkey 等 | | `DeveloperHandler` 依赖的服务组合 | 开发者应用管理和用户举报入口 | | `RiskService` | 滥用举报、管理员确认/驳回、风控名单、降级/封禁执行 | | `PasskeyService` | WebAuthn 注册和登录仪式、凭据管理 | | `SecretCipher` | OIDC client secret 加密 | | `password_policy.go` / `password.go` | 密码策略和 Argon2id 哈希 | 服务层是业务规则核心。Handler 只做 HTTP 参数解析、响应映射和上下文提取。 ### 8.5 handler 层 路径:`internal/handler/`。 | Handler | 作用 | | --- | --- | | `AuthHandler` | `/api/v1/auth/*` | | `SocialHandler` | `/api/v1/social/*` | | `UserInfoHandler` | `/api/v1/me/*` | | `DeveloperHandler` | `/api/v1/developer/*` | | `AdminHandler` | `/api/v1/admin/*` | | `OIDCHandler` | `/oauth2/*` 和 consent API | | `WellKnownHandler` | discovery 和 JWKS | | `PasskeyHandler` | Passkey API | | `HealthHandler` | 健康检查 | | `SPAHandler` | 前端 SPA fallback | 中间件在 `internal/handler/middleware/`: - session 鉴权、可选 session 鉴权。 - admin 权限检查。 - CORS。 - request id。 - logging。 - rate limit。 - Turnstile。 ## 9. 核心数据模型和数据库表 主要表来自 `db/migrations/000001_initial.up.sql`,后续迁移补充风险、Provider 排序、Passkey 等。 核心表: | 表 | 作用 | | --- | --- | | `users` | 平台用户,本地邮箱、密码哈希、角色、状态、信任等级 | | `social_bindings` | 用户绑定的第三方账号,含 token、状态、`raw_profile` | | `security_level_rules` | 信任等级规则,`conditions` 是 JSON | | `security_level_changes` | 信任等级变更审计 | | `oidc_clients` | 下游 OIDC 客户端 | | `client_access_rules` | 客户端访问 allow/deny 规则 | | `oauth2_authorization_codes` | fosite 授权码存储 | | `oauth2_access_tokens` | fosite access token 存储 | | `oauth2_refresh_tokens` | fosite refresh token 存储 | | `oauth2_oidc_sessions` | OIDC session/consent 数据 | | `oauth2_pkce_requests` | PKCE 请求存储 | | `signing_keys` | OIDC 签名密钥 | | `user_sessions` | 平台登录 session | | `provider_configs` | 后台配置的 Provider | | `global_settings` | 平台开关和全局设置 | | `alias_restrictions` | 用户 alias 保留/禁用规则 | | `audit_log` | 审计日志 | | `risk_reports` | 开发者/管理员风控举报 | | `risk_list` | 风控黑名单 | | `passkey_credentials` | WebAuthn/Passkey 凭据 | `social_bindings.raw_profile` 很关键:Provider 拉到的原始 profile 会被保存,信任等级规则可从这里读取字段。 ## 10. 认证、登录和 OIDC 流程 ### 10.1 本地邮箱密码登录 ```mermaid sequenceDiagram participant FE as Frontend participant H as AuthHandler participant S as AuthService participant R as User/Session Repo FE->>H: POST /api/v1/auth/login H->>S: Login(email,password,ip,userAgent) S->>R: GetByEmail S->>S: 验证密码、状态、登录锁定 S->>R: Create session + UpdateLastLogin H-->>FE: Set-Cookie oidc_session ``` 登录成功后前端 `auth.fetchUser()` 读取 `/api/v1/me`。 ### 10.2 社交绑定 ```mermaid sequenceDiagram participant FE as Frontend participant SH as SocialHandler participant SS as SocialService participant P as Provider participant DB as Binding Repo FE->>SH: GET /api/v1/social/{provider}/begin (已登录) SH->>SS: BeginBinding SS->>SS: 写 OAuth state 到 cache SS-->>FE: redirect provider auth URL P-->>SH: callback code/state SH->>SS: CompleteBinding SS->>P: CompleteAuth 拉 profile SS->>DB: Create social_binding(raw_profile) SS->>SS: ComputeSecurityLevel ``` 绑定后会重算信任等级。 ### 10.3 社交登录 未登录状态访问 `/api/v1/social/{provider}/begin` 会进入 login 模式。callback 后如果 Provider UID 已绑定,则更新绑定 profile/token 并创建本平台 session;如果未绑定,可能按配置执行社交注册或返回错误。 ### 10.4 OIDC 授权码流程 ```mermaid sequenceDiagram participant App as Client App participant O as OIDCHandler participant U as User Session participant C as ClientService participant A as AccessControl participant F as Fosite App->>O: GET /oauth2/authorize O->>F: NewAuthorizeRequest O->>U: OptionalSessionAuth O->>C: GetClientByClientID O->>A: CheckAccess(client,user,ip) O->>O: 创建 consent challenge O-->>App: redirect /authorize?consent_challenge=... App->>O: 用户同意后回到 authorize O->>F: Grant scopes + NewAuthorizeResponse F-->>App: authorization code App->>O: POST /oauth2/token O->>F: NewAccessRequest/NewAccessResponse ``` 准入检查位置:`internal/handler/oidc_handler.go` + `internal/service/access_control_service.go`。 ## 11. 信任等级规则系统 核心文件: - `internal/domain/security_level.go` - `internal/service/security_level_service.go` - `frontend/src/pages/admin/security-rules.vue` 规则存储在 `security_level_rules.conditions` JSON 中,不改表结构即可扩展。 ### 11.1 规则结构 ```json { "operator": "AND", "rules": [ { "type": "provider_account_age_days", "provider": "github", "field": "created_at", "operator": "gte", "min_days": 180 } ] } ``` 旧规则仍兼容: ```json { "operator": "AND", "rules": [ { "provider": "github", "min_binding_days": 30 } ] } ``` 旧规则会被解释为 `binding_age_days`。 ### 11.2 条件类型 | type | 含义 | 主要字段 | | --- | --- | --- | | `provider_bound` | 已绑定某平台;provider 空表示任意活跃绑定 | `provider` | | `binding_age_days` | 绑定时长 | `provider`, `operator`, `min_days` | | `provider_account_age_days` | 第三方账号创建时长,如 GitHub `created_at` | `provider`, `field`, `operator`, `min_days` | | `provider_email_verified` | Provider 明确返回邮箱验证状态 | `provider`, `operator`, `value` | | `provider_email_domain` | Provider 邮箱域名 | `provider`, `values` | | `provider_raw_number` | RawProfile 数字字段 | `provider`, `field`, `operator`, `value` | | `provider_raw_string` | RawProfile 文本字段 | `provider`, `field`, `operator`, `value/values` | | `provider_raw_bool` | RawProfile 布尔字段 | `provider`, `field`, `operator`, `value` | | `user_email_domain` | 本地用户邮箱域名 | `values` | | `user_created_age_days` | 本地用户注册天数 | `operator`, `min_days` | | `user_has_verified_email` | 本地用户邮箱已验证 | `operator`, `value` | 比较方式: - 数字:`gte`, `gt`, `lte`, `lt`, `eq`, `neq`,也兼容 `>=`, `>`, `<=`, `<`, `=`, `==`, `!=`。 - 字符串:`eq`, `neq`, `contains`, `prefix`, `suffix`, `regex`, `in`。 - 布尔:`eq`, `neq`。 ### 11.3 评估原则 - `SecurityLevelService.ComputeSecurityLevel` 会读取用户、规则、绑定,然后从高等级到低等级排序匹配。 - 同等级按 `priority` 从高到低。 - 首个命中规则决定用户等级。 - 只使用 active binding;已解绑、禁用、过期等非活跃绑定不参与。 - `provider` 为空表示任意活跃绑定。 - `RawProfile` 路径支持点路径,如 `profile.company`。 - 时间支持 RFC3339Nano、RFC3339、`2006-01-02 15:04:05`、`2006-01-02` 和 unix timestamp。 - GitHub 账号注册天数必须来自 `RawProfile.created_at`,不能回退到绑定时间。 - 邮箱验证未知态不会被伪装成 false;条件不会匹配。 ### 11.4 Provider RawProfile 标准化 文件:`internal/adapter/social/raw_profile.go`。 目标:在保留 Provider 原始字段的基础上,稳定派生通用字段: - `email` - `email_domain` - `email_verified`:只有 Provider 明确提供可靠验证状态才写入。 各 Provider 的字段映射集中在 `internal/adapter/social/*.go`。 ### 11.5 前端规则编辑器 页面:`frontend/src/pages/admin/security-rules.vue`。 支持: - 新旧规则显示和编辑兼容。 - 条件类型选择。 - provider 推荐 + 可手填,支持 `custom_` / `oauth_` 自定义 Provider key。 - RawProfile 字段推荐 + 可手填路径。 - 数字、字符串、布尔、域名列表输入。 - GitHub 常用预设:`created_at`、`followers`、`following`、`public_repos`、`public_gists`。 文案: - `frontend/src/i18n/zh.ts` - `frontend/src/i18n/en.ts` 测试: - `internal/service/security_level_service_test.go` ## 12. Provider 系统 核心接口:`internal/port/social_provider.go`。 Provider 需要实现: ```text Name BeginAuth CompleteAuth SupportsRefresh RefreshToken ``` 可选实现:`TokenValidatingProvider`,用于后续授权状态同步。 Registry:`internal/adapter/social/registry.go`。 Provider 来源: 1. 静态配置 `oauth2.`。 2. 数据库存储 `provider_configs`,由管理后台配置。 支持内置 Provider: ```text github, google, gitlab, gitee, discord, telegram, microsoft, apple, qq, wechat, phone ``` 自定义 OAuth2 Provider: - key 必须通过 `domain.IsValidCustomProviderKey`。 - key 需要以 `custom_` 或 `oauth_` 开头。 - 配置字段来自 `ProviderConfig.ExtraConfig`,例如授权端点、token 端点、userinfo 端点、字段路径等。 新增 Provider 的典型步骤: 1. 在 `internal/domain/provider.go` 增加常量和 `AllProviders`。 2. 在 `internal/adapter/social/` 增加 Provider 实现。 3. 在 `registry.go` 和 `cmd/server/bootstrap.go` 接入构造逻辑。 4. 在后台 Provider 页面和 i18n 增加展示字段。 5. 确认 `RawProfile` 字段标准化,不伪造不可证明字段。 ## 13. 客户端和准入控制 客户端模型:`internal/domain/client.go`。 `OIDCClient` 关键字段: - `ClientID` - `ClientSecretEncrypted` - `RedirectURIs` - `GrantTypes` - `ResponseTypes` - `Scopes` - `TokenEndpointAuthMethod` - `MinSecurityLevel` - `RequireEmailVerified` - `IsConfidential` - `IsActive` - `OwnerUserID` 客户端服务:`internal/service/client_service.go`。 负责: - 创建/更新客户端。 - 校验回调地址、grant type、scope、安全等级。 - 生成和加密 client secret。 - 轮换 secret。 - 验证 secret。 准入控制:`internal/service/access_control_service.go`。 检查顺序: 1. 客户端是否 active。 2. 用户状态是否 active。 3. 用户信任等级是否达到 `client.MinSecurityLevel`。 4. 客户端是否要求本地邮箱已验证。 5. `client_access_rules` 中的 user/email/email_domain/ip allow/deny。 注意:信任等级规则决定 `User.SecurityLevel`;客户端准入只消费这个等级并叠加自己的规则。 ## 14. 风控系统 核心文件: - `internal/domain/risk.go` - `internal/service/risk_service.go` - `frontend/src/pages/admin/risk.vue` - `frontend/src/pages/developer/apps/[id]/users.vue` 流程: ```mermaid flowchart LR A[开发者举报用户] --> B[risk_reports pending] B --> C{管理员确认?} C -->|确认| D[用户降到 Lv0] D --> E[用户状态 suspended] E --> F[用户绑定账号进入 risk_list] C -->|驳回| G[report dismissed] ``` `RiskService.ReportUser` 有自动升级逻辑:同一目标用户已有足够 confirmed reports 时,会自动确认当前报告并执行风控。 社交绑定/登录时会检查 `risk_list`,命中则阻止。 ## 15. Passkey / WebAuthn 核心文件: - `internal/domain/passkey.go` - `internal/service/passkey_service.go` - `internal/handler/passkey_handler.go` - `db/migrations/000007_passkey_credentials.up.sql` 配置: ```text webauthn.rp_id webauthn.rp_origin webauthn.rp_display_name ``` 开关:`global_settings.passkey_enabled`。 登录和注册 challenge 存在 cache 中,key 前缀为 `passkey:challenge:`,过期时间 60 秒。 前端使用 `@simplewebauthn/browser`。 ## 16. 前端结构 ### 16.1 应用入口 - `frontend/src/main.ts`:创建 Vue app,挂载 Pinia、i18n、router。 - `frontend/src/App.vue`:只放 `RouterView` 和全局 Toast。 - `frontend/src/api/client.ts`:统一 API client。 - `frontend/src/stores/auth.ts`:登录态、用户信息、开发者权限。 ### 16.2 路由 文件:`frontend/src/router/index.ts`。 主分组: | 路径 | 布局 | 页面 | | --- | --- | --- | | `/` | `DefaultLayout` | 首页、features、docs、privacy、terms | | `/login` 等 | `AuthLayout` | 登录、注册、找回密码、重置、授权确认、邮箱验证 | | `/me` | `DashboardLayout` | 用户中心、会话、绑定、安全、授权应用 | | `/developer` | `DeveloperLayout` | 开发者首页、创建应用、应用详情、应用用户 | | `/admin` | `AdminLayout` | 管理首页、用户、客户端、规则、Provider、设置、审计、密钥、风控 | 路由守卫: - 首次进入会并发 `auth.fetchUser()` 和 `auth.fetchPublicSettings()`。 - `requiresAuth` 未登录跳 `/login?return_to=...`。 - 登录用户访问受保护区域时拉取 developer status。 - `requiresAdmin` 检查 `role`。 - `requiresDeveloper` 检查 developer access。 ### 16.3 API client `frontend/src/api/client.ts`: - base path 固定为 `/api/v1`。 - 每个请求默认 JSON。 - 默认带 cookie。 - 非 2xx 或 `success=false` 直接 throw `Error(message)`。 新增前端 API 通常不需要新 client,只需要页面内调用: ```ts api.get('/path') api.post('/path', body) api.put('/path', body) api.del('/path') ``` ### 16.4 页面入口索引 用户端: ```text frontend/src/pages/login.vue frontend/src/pages/register.vue frontend/src/pages/forgot-password.vue frontend/src/pages/reset-password.vue frontend/src/pages/verify-email.vue frontend/src/pages/authorize.vue frontend/src/pages/me/index.vue frontend/src/pages/me/bindings.vue frontend/src/pages/me/security.vue frontend/src/pages/me/sessions.vue frontend/src/pages/me/authorized.vue ``` 开发者: ```text frontend/src/pages/developer/index.vue frontend/src/pages/developer/create.vue frontend/src/pages/developer/apps/[id].vue frontend/src/pages/developer/apps/[id]/users.vue ``` 管理员: ```text frontend/src/pages/admin/index.vue frontend/src/pages/admin/users.vue frontend/src/pages/admin/clients.vue frontend/src/pages/admin/security-rules.vue frontend/src/pages/admin/providers.vue frontend/src/pages/admin/settings.vue frontend/src/pages/admin/audit.vue frontend/src/pages/admin/keys.vue frontend/src/pages/admin/risk.vue ``` Provider 配置组件: ```text frontend/src/components/admin/providers/*.vue ``` ### 16.5 i18n 文件: ```text frontend/src/i18n/index.ts frontend/src/i18n/zh.ts frontend/src/i18n/en.ts ``` 页面新增文案必须同步中英文,否则构建期不一定报错,但运行时可能显示 key。 ## 17. 数据流速查 ### 17.1 本地用户注册 ```mermaid flowchart LR A[注册页] --> B[SendRegisterCode] B --> C[cache: register code] C --> D[邮件发送] A --> E[Register] E --> F[校验 code/password/domain] F --> G[users] G --> H[audit_log] ``` ### 17.2 社交绑定到信任等级 ```mermaid flowchart LR A[Provider OAuth callback] --> B[ProviderUserInfo] B --> C[SocialBinding.RawProfile] C --> D[SecurityLevelService] D --> E[security_level_rules.conditions] E --> F[User.SecurityLevel] F --> G[security_level_changes] ``` ### 17.3 客户端授权 ```mermaid flowchart LR A[下游 App authorize] --> B[OIDCHandler] B --> C[本平台 session] C --> D[ClientService] D --> E[AccessControlService] E --> F[Consent] F --> G[Fosite authorization code] G --> H[token + id_token] ``` ### 17.4 风控举报 ```mermaid flowchart LR A[Developer report] --> B[RiskService] B --> C[risk_reports] C --> D[Admin confirm] D --> E[User suspended + Lv0] E --> F[risk_list] F --> G[后续社交登录/绑定拦截] ``` ## 18. 常见修改入口 ### 18.1 新增后端 API 1. 在合适的 service 加业务方法。 2. 在 handler 中加 HTTP 方法。 3. 在 `internal/router/router.go` 注册路由。 4. 如需持久化,先改 domain/port/repo/migration。 5. 前端页面调用 `api.*`。 6. 补 i18n 和测试。 ### 18.2 新增数据库字段 1. 改 `db/migrations`。 2. 改 `internal/domain`。 3. 改 `internal/port/repository.go` 如果接口变化。 4. 同步 `internal/adapter/sqlite` 和 `internal/adapter/postgres`。 5. 检查 JSON 序列化字段名。 6. 跑 `go test ./...`。 ### 18.3 新增信任等级条件 1. `internal/domain/security_level.go` 新增 condition type 和字段。 2. `internal/service/security_level_service.go`: - `normalizeCondition` - `validateCondition` - `evaluateCondition` - 必要时 `conditionStatus` 3. Provider 字段来自 `RawProfile` 时,优先在 `internal/adapter/social/raw_profile.go` 或具体 provider 适配器补标准化。 4. 前端 `frontend/src/pages/admin/security-rules.vue` 增加编辑能力。 5. 中英文 i18n 增加文案。 6. `internal/service/security_level_service_test.go` 补回归测试。 ### 18.4 新增 Provider 参考“Provider 系统”章节。 重点不要把不可证明字段伪造成可证明字段。例如邮箱验证只能在 Provider 明确返回 verified/verified_email/email_verified 时写入。 ### 18.5 改 OIDC token claims 相关文件: - `internal/oidcprovider/session.go` - `internal/oidcprovider/claims.go` - `internal/handler/oidc_handler.go` `Authorize` 中会调用 `oidcprovider.NewSession` 和 `oidcprovider.AddCustomClaims`。 需要保证 `/oauth2/userinfo` 和 ID Token claims 语义一致。 ### 18.6 改前端权限导航 相关文件: - `frontend/src/router/index.ts` - `frontend/src/stores/auth.ts` - 各 layout:`frontend/src/layouts/*.vue` 开发者权限由 `/api/v1/developer/status` 决定,不只是 `security_level` 单字段。 ## 19. 测试和验证建议 必跑: ```bash go test ./... cd frontend && npm run build ``` 按修改范围补充: | 修改范围 | 重点验证 | | --- | --- | | 认证/注册/密码 | 登录、注册、找回、锁定、邮箱域名限制 | | 社交 Provider | begin/callback、profile 保存、绑定冲突、risk list | | 信任等级 | 旧规则兼容、AND/OR、RawProfile 字段缺失、非活跃绑定过滤 | | OIDC | discovery、authorize、consent、token、userinfo、client secret | | 客户端准入 | min level、email verified、email/ip/user allow/deny | | Passkey | begin/finish register、begin/finish login、challenge 过期 | | 前端页面 | vue-tsc 构建、i18n key、API 路径、权限守卫 | ## 20. 已知工程注意点 - 工作区可能存在未提交改动;不要随意回退用户或其他任务的变更。 - 后端 handler 的 JSON 解码拒绝未知字段,前端 payload 要精准。 - SQLite 和 PostgreSQL repository 经常要同步改。 - `security_level_rules.conditions` 是 JSON,扩展规则优先保持旧结构兼容。 - `social_bindings.raw_profile` 是信任等级高级规则的重要依据,Provider 修改要谨慎。 - 邮箱验证不能靠 `email != ""` 判断。 - GitHub 注册天数必须读 GitHub profile 的 `created_at`。 - `provider` 允许自定义 key,但必须满足 `custom_` 或 `oauth_` 前缀规则。 - 前端构建会跑 `vue-tsc -b`,模板里的 TypeScript 类型断言容易导致构建失败,复杂转换放到 script 方法里。 - `OIDC_OAUTH2_SECRET` 少于 32 字符时会随机生成,重启后 OAuth session 不可持续。 - 启动时会自动创建 signing key;JWKS 来自 `signing_keys` 表。 - 默认全局设置会在启动时 seed,包括注册、登录、社交绑定、Passkey 开关。 ## 21. 当前仓库状态提示 最近完成的关键增强: - 信任等级规则已从旧的 `provider + min_binding_days` 扩展为可读 Provider RawProfile 的通用规则系统。 - GitHub 注册天数读取 `RawProfile.created_at`。 - Provider 邮箱验证未知态不会匹配。 - 管理端规则 UI 已支持新结构并兼容旧规则。 - 新增 `internal/adapter/social/raw_profile.go`。 - 新增 `internal/service/security_level_service_test.go`。 如果后续 AI 接手信任等级相关问题,优先看: ```text internal/domain/security_level.go internal/service/security_level_service.go internal/service/security_level_service_test.go internal/adapter/social/raw_profile.go internal/adapter/social/*.go frontend/src/pages/admin/security-rules.vue frontend/src/i18n/zh.ts frontend/src/i18n/en.ts ``` ## 22. 最短接手路径 如果你是新 AI,只需要按这个顺序读: 1. 本文档。 2. `internal/router/router.go` 看系统入口和 API 边界。 3. `cmd/server/bootstrap.go` 看依赖如何组装。 4. 当前任务相关的 service 文件。 5. 当前任务相关的 handler 文件。 6. 如涉及存储,再看对应 domain、port 和 repo。 7. 如涉及前端,再看 `frontend/src/router/index.ts`、`frontend/src/api/client.ts`、目标页面和 i18n。 不要一开始全仓库泛读,除非任务本身是架构重构。