Skip to content
Clone

refactor(proto): remove deprecated proto files for auth and email services

ZhenYi committed
parent 6ca5b70 commit 1e5e283 Browse files

10 files changed

+1 −767

File tree 10
Deleted lib/infra/proto/proto/auth/internal/v1/admin.proto
@@ -1,225 +0,0 @@
1syntax = "proto3";
2
3package auth.internal.v1;
4
5import "auth/common/v1/types.proto";
6import "google/protobuf/timestamp.proto";
7
8// auth 内部管理面。调用方:平台管理入口(api 的管理后台)与运维工具。
9// 入口统一由 `auth.oauth.rpc_key` 的共享密钥(`x-rpc-key` 头)把守,不区分调用方身份;
10// mutation 另需在 `gitdata-request-id` 里带上请求 ID。
11//
12// 本文件是特权操作(密钥轮换、缓存维护、审计),入口同样只校验共享密钥,
13// 不注册到公共网关。密钥材料永不出服务:所有响应只回标识与状态。
14service KeyRotationService {
15 // 触发密钥轮换。dry_run=true 只回报影响面,不做任何写入。
16 // mutation: request_id 通过 gitdata-request-id 头携带
17 rpc TriggerKeyRotation(TriggerKeyRotationRequest) returns (TriggerKeyRotationResponse);
18
19 // 列出密钥清单与状态。不含私钥、不含明文密钥材料。
20 rpc GetKeyInventory(GetKeyInventoryRequest) returns (GetKeyInventoryResponse);
21
22 // 确认轮换完成:把处于 ROTATING 的密钥置为 RETIRED,并解除对旧键的验证宽容期。
23 // mutation: request_id 通过 gitdata-request-id 头携带
24 rpc CompleteKeyRotation(CompleteKeyRotationRequest) returns (CompleteKeyRotationResponse);
25}
26
27// 密钥用途。不同用途的轮换代价差别很大:
28// 令牌签名键轮换只影响新签发,历史 JWT 仍可用旧公钥验证;
29// 摘要 pepper 与加密键轮换会使既有密文/摘要不可解释,必须配合数据迁移或强制失效。
30enum KeyKind {
31 KEY_KIND_UNSPECIFIED = 0;
32 KEY_KIND_TOKEN_SIGNING = 1; // JWT 私钥(service_token / 分享链接)
33 KEY_KIND_HASH_PEPPER = 2; // token_hash 摘要 pepper
34 KEY_KIND_TOTP_ENCRYPTION = 3; // MFA 密钥信封加密(auth.totp_encryption_key)
35 KEY_KIND_SESSION_MAC = 4; // 会话 cookie 签名
36 KEY_KIND_POW_MAC = 5; // 挑战签发签名(pow.mac_key)
37}
38
39enum KeyState {
40 KEY_STATE_UNSPECIFIED = 0;
41 KEY_STATE_ACTIVE = 1; // 当前签发所用
42 KEY_STATE_ROTATING = 2; // 新旧并存:新签发用新键,验证同时接受旧键
43 KEY_STATE_RETIRED = 3; // 只验证,不再签发
44 KEY_STATE_REVOKED = 4; // 完全不可用(怀疑泄露)
45}
46
47message TriggerKeyRotationRequest {
48 KeyKind kind = 1;
49 // 验证宽容期:新键启用后仍接受旧键签出物的时长。0 = 用服务端默认(24h)。
50 uint64 grace_period_secs = 2;
51 bool dry_run = 3;
52 string reason = 4;
53 // HASH_PEPPER / TOTP_ENCRYPTION 轮换必须显式确认数据迁移方案,否则返回 INVALID_ARGUMENT。
54 bool acknowledge_data_migration = 5;
55}
56
57message TriggerKeyRotationResponse {
58 KeyKind kind = 1;
59 string new_key_id = 2;
60 uint32 new_version = 3;
61 string previous_key_id = 4;
62 KeyState state = 5; // 通常为 ROTATING
63 google.protobuf.Timestamp started_at = 6;
64 Impact impact = 7;
65
66 // dry_run 时也返回,便于评估影响面。
67 message Impact {
68 uint64 active_sessions = 1;
69 uint64 active_tokens = 2;
70 uint64 mfa_factors = 3;
71 uint64 pow_challenges_outstanding = 4;
72 bool requires_migration = 5; // true = 该用途轮换会令既有密文/摘要不可读
73 }
74}
75
76message GetKeyInventoryRequest {
77 KeyKind kind = 1; // UNSPECIFIED = 全部用途
78}
79
80message GetKeyInventoryResponse {
81 repeated KeyInfo keys = 1;
82 // 当前用于签发的键(每种用途至多一个)。
83 repeated string primary_key_ids = 2;
84
85 message KeyInfo {
86 string key_id = 1;
87 KeyKind kind = 2;
88 uint32 version = 3;
89 KeyState state = 4;
90 bool is_primary = 5;
91 // 公钥可公开分发(JWKS)。非对称用途才非空。
92 string public_jwks_url = 6;
93 google.protobuf.Timestamp created_at = 7;
94 google.protobuf.Timestamp activated_at = 8;
95 google.protobuf.Timestamp retired_at = 9;
96 google.protobuf.Timestamp revoked_at = 10;
97 }
98}
99
100message CompleteKeyRotationRequest {
101 KeyKind kind = 1;
102 string key_id = 2; // 要标记为 RETIRED 的旧键
103 bool dry_run = 3;
104 string reason = 4;
105}
106
107message CompleteKeyRotationResponse {
108 bool completed = 1;
109 string key_id = 2;
110 KeyState state = 3;
111}
112
113// 缓存与索引维护。auth 的会话、内省结果、权限判定都带缓存,运维需要显式的失效通道;
114// 平时的失效由业务写入主动触发,本服务只用于事故处理与数据修复。
115service CacheMaintenanceService {
116 // 按范围清理缓存。dry_run=true 只回报预计清理的键数量。
117 // mutation: request_id 通过 gitdata-request-id 头携带
118 rpc FlushAuthCache(FlushAuthCacheRequest) returns (FlushAuthCacheResponse);
119
120 // 重建指定用户的身份缓存(会话索引、内省结果、能力判定)。
121 // mutation: request_id 通过 gitdata-request-id 头携带
122 rpc RebuildIdentityCache(RebuildIdentityCacheRequest) returns (RebuildIdentityCacheResponse);
123}
124
125enum CacheScope {
126 CACHE_SCOPE_UNSPECIFIED = 0;
127 CACHE_SCOPE_ALL = 1;
128 CACHE_SCOPE_SESSIONS = 2; // 会话索引与安全版本快照
129 CACHE_SCOPE_INTROSPECTION = 3; // 令牌内省结果
130 CACHE_SCOPE_AUTHORIZATION = 4; // 能力判定
131 CACHE_SCOPE_MFA = 5; // 第二因子状态
132 CACHE_SCOPE_CODES = 6; // 邮件验证码与尝试计数
133 CACHE_SCOPE_POW = 7; // 挑战与已用标记
134}
135
136message FlushAuthCacheRequest {
137 CacheScope scope = 1;
138 // 0 = 全部用户;>0 只清该用户的相关键。
139 int64 user_id = 2;
140 string key_prefix = 3; // 可选的额外键前缀过滤
141 bool dry_run = 4;
142 string reason = 5;
143}
144
145message FlushAuthCacheResponse {
146 uint64 matched_keys = 1;
147 uint64 deleted_keys = 2;
148 bool dry_run = 3;
149}
150
151message RebuildIdentityCacheRequest {
152 repeated int64 user_ids = 1; // 上限 1000
153 CacheScope scope = 2;
154 bool dry_run = 3;
155}
156
157message RebuildIdentityCacheResponse {
158 uint32 queued_users = 1;
159 uint32 rebuilt_users = 2; // 同步完成的部分(dry_run 时为 0)
160 uint32 skipped_users = 3;
161}
162
163// 审计读取与归档。数据源是 user_events 表与泄出的事件流;
164// 写入路径在业务代码里,不经本服务,避免审计被管理面误改。
165service AuditService {
166 // 分页查询审计事件。
167 rpc ListAuthEvents(ListAuthEventsRequest) returns (ListAuthEventsResponse);
168
169 // 流式导出。按 occurred_at 升序,服务端分批推送,单次最多 1_000_000 条。
170 rpc ExportAuthEvents(ExportAuthEventsRequest) returns (stream AuthEventRecord);
171
172 // 归档并清理:仅允许删除已超过保留期的记录。
173 // mutation: request_id 通过 gitdata-request-id 头携带
174 rpc PurgeAuthEvents(PurgeAuthEventsRequest) returns (PurgeAuthEventsResponse);
175}
176
177message ListAuthEventsRequest {
178 int64 user_id = 1; // 0 = 不过滤
179 int64 actor_user_id = 2;
180 // 事件类型名,如 "login_succeeded";空 = 全部。
181 repeated string kinds = 3;
182 google.protobuf.Timestamp from = 4;
183 google.protobuf.Timestamp to = 5;
184 auth.common.v1.PageRequest page = 6;
185}
186
187message ListAuthEventsResponse {
188 repeated AuthEventRecord events = 1;
189 auth.common.v1.PageResponse page = 2;
190}
191
192message ExportAuthEventsRequest {
193 google.protobuf.Timestamp from = 1;
194 google.protobuf.Timestamp to = 2;
195 repeated string kinds = 3;
196 uint32 batch_size = 4; // 0 = 服务端默认(500)
197}
198
199message PurgeAuthEventsRequest {
200 google.protobuf.Timestamp older_than = 1;
201 repeated string kinds = 2;
202 uint64 retention_days = 3; // 与 older_than 二者取严格者
203 bool dry_run = 4;
204}
205
206message PurgeAuthEventsResponse {
207 uint64 matched_records = 1;
208 uint64 purged_records = 2;
209 bool dry_run = 3;
210}
211
212message AuthEventRecord {
213 string event_id = 1;
214 string kind = 2;
215 int64 subject_user_id = 3;
216 int64 actor_user_id = 4;
217 google.protobuf.Timestamp occurred_at = 5;
218 string client_ip = 6;
219 string user_agent = 7;
220 string trace_id = 8;
221 // 结构化明细,与 auth.v1.AuthEventEnvelope 的 payload 同构(JSON)。
222 string details_json = 9;
223 // 凭据类型指纹,如 access_key_id 的摘要前缀;不存凭据明文。
224 string credential_fingerprint = 10;
225}
Modified lib/infra/proto/proto/auth/internal/v1/authority.proto View lib/infra/proto/proto/auth/internal/v1/authority.proto
@@ -5,43 +5,6 @@
55import "auth/common/v1/types.proto";
66import "google/protobuf/timestamp.proto";
77
8// auth 授权面。调用方固定为 api(令牌校验、用户资料、账号更新)与 socket
9// (实时通道的会话复核),以及平台管理后台(账号列表)。本文件的接口取代旧的
10// 内部 HTTP 入口,语义一一对应,不做额外扩展。
11//
12// 与 auth.v1 的边界:auth.v1.IdentityService.Authenticate 回答"凭证是否有效",
13// 返回 Principal(不含账号可用性字段);本文件回答"账号与会话现在处于什么状态",
14// 返回完整快照,由调用方自己执行 require_active 判定。两者的字段集、撤销延迟
15// 与缓存策略不可互换。
16service AuthorityService {
17 rpc RedeemSocketTicket(RedeemSocketTicketRequest) returns (RedeemSocketTicketResponse);
18 // 校验访问令牌并返回会话快照。调用方:api 的认证中间件。
19 rpc Validate(ValidateRequest) returns (ValidateResponse);
20
21 // 读取单个账号快照。不存在返回 NOT_FOUND。
22 rpc GetUser(GetUserRequest) returns (GetUserResponse);
23
24 // 批量读取账号快照。user_ids 为空直接返回空列表;超过 500 个返回
25 // INVALID_ARGUMENT;不存在的 id 静默省略。
26 rpc BatchGetUser(BatchGetUserRequest) returns (BatchGetUserResponse);
27
28 // 复核会话:user_id + security_version + session_id 三者必须自洽。
29 // 会话撤销、已过期、版本不匹配一律返回 UNAUTHENTICATED。
30 rpc GetSession(GetSessionRequest) returns (GetSessionResponse);
31
32 // 以乐观锁更新账号自述字段。version 必须回填,版本冲突返回 ABORTED。
33 rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse);
34 // 账号删除生命周期:软删 + 撤销全部凭据;有活跃组织的 OWNER 会被拒绝。
35 rpc DeleteAccount(DeleteAccountRequest) returns (DeleteAccountResponse);
36 rpc CancelAccountDeletion(CancelAccountDeletionRequest) returns (CancelAccountDeletionResponse);
37 // 宽限期结束后的匿名化清理(保留 user_id 供历史内容引用)。
38 rpc PurgeAccount(PurgeAccountRequest) returns (PurgeAccountResponse);
39
40 // 分页列出账号并筛选。平台管理面用:管理后台的账号总览。
41 // 与 IdentityService 的读取接口不重叠:那边按单/批编号取值,这里做全量分页与筛选。
42 rpc ListUsers(ListUsersRequest) returns (ListUsersResponse);
43}
44
458message RedeemSocketTicketRequest {
469 string ticket = 1;
4710 string origin = 2;
Deleted lib/infra/proto/proto/auth/internal/v1/email.proto
@@ -1,120 +0,0 @@
1syntax = "proto3";
2
3// 邮件发送入口(内部面)。
4//
5// 调用方:api、notify 以及任何需要发信的内部服务,通过 `x-rpc-key` 头鉴权。
6// 服务端只把请求放进进程内有界队列并立即返回,SMTP 由内嵌 worker 异步完成;
7// 队列满时按反压阻塞,超过 `email.enqueue_timeout_ms` 才返回 RESOURCE_EXHAUSTED。
8package auth.internal.v1;
9
10message EmailAddress {
11 // 邮箱地址,非空。
12 string address = 1;
13 // 显示名,可为空。
14 string name = 2;
15}
16
17// 附件内容用 base64 传输(proto 的 bytes 字段在本仓库不参与 JSON 编码)。
18message EmailAttachment {
19 string filename = 1;
20 string content_type = 2;
21 string data_b64 = 3;
22 // 内联附件的 Content-ID,普通附件留空。
23 string content_id = 4;
24}
25
26message SendEmailRequest {
27 // 留空时服务端生成 UUIDv7,并在响应里回传。
28 string request_id = 1;
29 // 收件人,至少一个。
30 repeated EmailAddress to = 2;
31 repeated EmailAddress cc = 3;
32 repeated EmailAddress bcc = 4;
33 // 必填。
34 string subject = 5;
35 // 纯文本正文;与 html 至少给一个。
36 string text = 6;
37 string html = 7;
38 EmailAddress reply_to = 8;
39 repeated EmailAttachment attachments = 9;
40 // 透传到投递事件里的业务标签。
41 map<string, string> metadata = 10;
42 // 链路追踪 ID,只用于日志。
43 string trace_id = 11;
44}
45
46message SendEmailResponse {
47 string request_id = 1;
48 // 已入队即为 true;入队失败由 gRPC 状态码表达。
49 bool accepted = 2;
50 // 入队后的积压条数。
51 uint32 queue_depth = 3;
52}
53
54message BatchRecipient {
55 string request_id = 1;
56 EmailAddress to = 2;
57 // 留空时回落到批量的 default_subject。
58 string subject = 3;
59 string text = 4;
60 string html = 5;
61 map<string, string> metadata = 6;
62}
63
64message SendBatchEmailRequest {
65 string request_id = 1;
66 string default_subject = 2;
67 string default_text = 3;
68 string default_html = 4;
69 // 逐个收件人单独发信,单个失败不影响其余。
70 repeated BatchRecipient recipients = 5;
71 map<string, string> metadata = 6;
72 string trace_id = 7;
73}
74
75message SendBatchEmailResponse {
76 string request_id = 1;
77 uint32 accepted = 2;
78 uint32 queue_depth = 3;
79}
80
81message RenderAndSendEmailRequest {
82 string request_id = 1;
83 // 模板名,如 verify_code / reset_link / email_change_confirm。
84 string template = 2;
85 // 模板变量(JSON 对象字符串);locale 缺省时按服务端默认语言渲染。
86 string vars_json = 3;
87 repeated EmailAddress to = 4;
88 repeated EmailAddress cc = 5;
89 repeated EmailAddress bcc = 6;
90 string subject = 7;
91 string text = 8;
92 string locale = 9;
93 map<string, string> metadata = 10;
94 string trace_id = 11;
95}
96
97message EmailQueueStatus {
98 // 当前积压条数。
99 uint32 depth = 1;
100 // 队列容量。
101 uint32 capacity = 2;
102 // SMTP 是否已配置;false 时所有发送请求都会被拒绝。
103 bool smtp_enabled = 3;
104 // 成功投递计数。
105 uint64 sent = 4;
106 // 失败计数。
107 uint64 failed = 5;
108}
109
110message EmailQueueStatusRequest {}
111
112service EmailService {
113 // 入队一封邮件,立即返回。
114 rpc SendEmail(SendEmailRequest) returns (SendEmailResponse);
115 rpc SendBatchEmail(SendBatchEmailRequest) returns (SendBatchEmailResponse);
116 // 用模板渲染 HTML 后入队。
117 rpc RenderAndSendEmail(RenderAndSendEmailRequest) returns (SendEmailResponse);
118 // 队列观测:积压、容量、累计成功/失败。
119 rpc GetQueueStatus(EmailQueueStatusRequest) returns (EmailQueueStatus);
120}
Deleted lib/infra/proto/proto/auth/v1/agreement.proto
@@ -1,63 +0,0 @@
1syntax = "proto3";
2
3package auth.v1;
4
5import "auth/common/v1/types.proto";
6import "google/protobuf/timestamp.proto";
7
8// 协议文档(服务条款、隐私政策等)与接受状态。调用方:api(注册、登录后置检查、协议页)。
9//
10// 内容来自 auth 服务的静态配置(auth.agreements),版本号由配置给出;
11// 本服务不做富文本渲染,只回传 Markdown 原文与摘要,渲染交给调用方。
12// 用户接受了某版本后,配置里该协议的版本一旦提升,接受记录即视为过期,需要重新接受。
13service AgreementService {
14 // 列出当前生效的协议文档与语言。
15 rpc ListAgreements(ListAgreementsRequest) returns (ListAgreementsResponse);
16
17 // 检查某用户是否已接受指定的协议版本。批量,上限 32 项。
18 rpc CheckAgreementsAccepted(CheckAgreementsAcceptedRequest) returns (CheckAgreementsAcceptedResponse);
19}
20
21message ListAgreementsRequest {
22 // 期望语言(BCP-47,如 "zh-CN" / "en")。空 = 服务端默认语言。
23 string locale = 1;
24 // true = 同时回传 content_md 原文;false 只回传摘要,适合列表页。
25 bool include_content = 2;
26}
27
28message ListAgreementsResponse {
29 repeated AgreementDoc agreements = 1;
30
31 message AgreementDoc {
32 string key = 1; // 如 "terms" / "privacy"
33 string version = 2; // 如 "2026-01-01"
34 string title = 3;
35 string summary = 4;
36 string content_md = 5; // include_content=true 时非空
37 string locale = 6;
38 google.protobuf.Timestamp effective_at = 7;
39 }
40}
41
42message CheckAgreementsAcceptedRequest {
43 int64 user_id = 1;
44 // 要检查的协议键;空 = 检查当前生效的全部协议。
45 repeated string keys = 2;
46 // true = 只按“是否接受过”判定;false = 版本不一致也算未接受(默认)。
47 bool accept_any_version = 3;
48}
49
50message CheckAgreementsAcceptedResponse {
51 bool accepted = 1; // 全部命中时为 true
52 repeated string missing_keys = 2; // 从未接受
53 repeated string outdated_keys = 3; // 接受过但版本低于当前生效版本
54 repeated Record records = 4;
55
56 message Record {
57 string key = 1;
58 string accepted_version = 2;
59 string current_version = 3;
60 bool up_to_date = 4;
61 google.protobuf.Timestamp accepted_at = 5;
62 }
63}
Deleted lib/infra/proto/proto/auth/v1/authorization.proto
@@ -1,96 +0,0 @@
1syntax = "proto3";
2
3package auth.v1;
4
5import "auth/common/v1/errors.proto";
6import "auth/common/v1/types.proto";
7
8// 平台级授权。调用方:api(写接口入口)、object / notify / agent(动作前置检查)。
9//
10// 边界:auth 只回答“这个用户在平台层面能不能做这类事”,
11// 工会、仓库、房间内的细粒度授权属于各自服务的领域(api / git / chat),本树不定义。
12// 判定输入是 user_id 而不是调用方自报的 principal:服务端回源读 users 与凭据状态,
13// 避免调用方伪造 role 字段。
14service AuthorizationService {
15 // 单次能力判定。拒绝不作为 gRPC 错误返回,allowed=false + reason 便于批量聚合。
16 rpc Authorize(AuthorizeRequest) returns (AuthorizeResponse);
17
18 // 批量判定。上限 32 项,超出返回 INVALID_ARGUMENT;结果顺序与请求一致。
19 rpc BatchAuthorize(BatchAuthorizeRequest) returns (BatchAuthorizeResponse);
20
21 // 平台管理员判定。热路径,按 user_id 缓存 300s。
22 rpc IsPlatformAdmin(IsPlatformAdminRequest) returns (IsPlatformAdminResponse);
23
24 // 一次性取回账号状态与有效范围,供前端渲染权限相关 UI,避免多次往返。
25 rpc GetCapabilities(GetCapabilitiesRequest) returns (GetCapabilitiesResponse);
26}
27
28// 平台级能力枚举。资源内角色(如工会 owner、仓库 maintainer)不在其中。
29enum PlatformCapability {
30 PLATFORM_CAPABILITY_UNSPECIFIED = 0;
31 PLATFORM_CAPABILITY_READ_PROFILE = 1; // 读本人资料与设置
32 PLATFORM_CAPABILITY_WRITE_PROFILE = 2; // 改本人资料与设置
33 PLATFORM_CAPABILITY_MANAGE_CREDENTIALS = 3; // 管理本人会话、令牌、公钥、多因子
34 PLATFORM_CAPABILITY_USE_GIT = 4; // 使用 git / pr 服务
35 PLATFORM_CAPABILITY_USE_CHAT = 5; // 使用 chat / realtime / sfu
36 PLATFORM_CAPABILITY_USE_AGENT = 6; // 使用 agent 服务
37 PLATFORM_CAPABILITY_ADMIN_PANEL = 7; // 进入平台管理面
38 PLATFORM_CAPABILITY_MANAGE_USERS = 8; // 增删改其他用户
39 PLATFORM_CAPABILITY_MANAGE_PLATFORM = 9; // 平台配置、密钥轮换、配额
40}
41
42message AuthorizeRequest {
43 int64 user_id = 1;
44 PlatformCapability capability = 2;
45 bool require_mfa = 3; // true = 未通过第二因子的会话不予放行
46}
47
48message AuthorizeResponse {
49 bool allowed = 1;
50 // allowed=false 时说明原因:UNAUTHENTICATED / USER_DISABLED / LOGIN_FORBIDDEN /
51 // MFA_REQUIRED / FORBIDDEN / AGREEMENT_NOT_ACCEPTED。
52 auth.common.v1.Code reason = 2;
53 bool cached = 3;
54}
55
56message BatchAuthorizeRequest {
57 int64 user_id = 1;
58 repeated PlatformCapability capabilities = 2;
59 bool require_mfa = 3;
60}
61
62message BatchAuthorizeResponse {
63 repeated Decision decisions = 1;
64
65 message Decision {
66 PlatformCapability capability = 1;
67 bool allowed = 2;
68 auth.common.v1.Code reason = 3;
69 }
70}
71
72message IsPlatformAdminRequest {
73 int64 user_id = 1;
74}
75
76message IsPlatformAdminResponse {
77 bool is_admin = 1;
78 int32 security_version = 2;
79}
80
81message GetCapabilitiesRequest {
82 int64 user_id = 1;
83}
84
85message GetCapabilitiesResponse {
86 bool allow_use = 1;
87 bool forbid_login = 2;
88 bool email_verified = 3;
89 bool mfa_enabled = 4;
90 bool is_admin = 5;
91 int32 security_version = 6;
92 // 该用户在其 access key 上声明的范围并集;会话登录的用户视为全量。
93 repeated auth.common.v1.TokenScope scopes = 7;
94 repeated PlatformCapability capabilities = 8;
95 repeated string pending_agreements = 9; // 未接受或版本过期的协议键
96}
Modified lib/infra/proto/proto/auth/v1/identity.proto View lib/infra/proto/proto/auth/v1/identity.proto
@@ -5,44 +5,6 @@
55import "auth/common/v1/errors.proto";
66import "auth/common/v1/types.proto";
77
8// 身份校验入口。调用方:api(用户接口前置)、git / ssh(HTTP 与 SSH 认证)、
9// chat / realtime / sfu(连接建立时)、issue / pr / agent / object / notify / webhook。
10//
11// 安全边界:
12// * 凭据原文只在请求里出现,auth 立即摘要后丢弃,绝不回显、绝不落日志。
13// * 认证失败一律不区分“用户不存在”与“凭据错误”(见 auth/common/v1/errors.proto 的 NOT_FOUND 说明),
14// 上游如需按用户查数据显示,请改用 GetUserPublic / GetUserStatus,并自行确保调用方已认证。
15// * 读取接口(Get / BatchGet)不做权限提升:email 字段仅在调用主体是本人或平台管理员时非空。
16//
17// 缓存:Authenticate 结果按凭据摘要缓存,TTL 60s;吊销与安全版本变更会主动失效,
18// 因此下游必须容忍最长 60s 的滞后,安全敏感操作请携带 min_security_version 强制回源。
19service IdentityService {
20 // 把一个凭据换成 Principal。凭据可以是会话密钥、access token、access key 或服务令牌。
21 rpc Authenticate(AuthenticateRequest) returns (AuthenticateResponse);
22
23 // 只判定“能不能放行”,不返回主体。供网关/边缘在热路径上使用:认证失败不作为 gRPC 错误返回,
24 // 而是 valid=false + reason,调用方无需解析 status detail。
25 rpc VerifyCredential(VerifyCredentialRequest) returns (VerifyCredentialResponse);
26
27 // 按编号、登录名或邮箱取用户公开信息。邮箱匹配大小写不敏感。
28 rpc GetUserPublic(GetUserPublicRequest) returns (GetUserPublicResponse);
29
30 // 批量取用户公开信息。单次上限 500 个编号,超出返回 INVALID_ARGUMENT;
31 // 不存在的编号不占位,调用方按 user_id 自行对齐。
32 rpc BatchGetUserPublic(BatchGetUserPublicRequest) returns (BatchGetUserPublicResponse);
33
34 // 账号可用性。签发新凭据前必须查一次;已签发凭据的持续校验走 Authenticate。
35 rpc GetUserStatus(GetUserStatusRequest) returns (GetUserStatusResponse);
36
37 // 按用户名解析或创建机器人账号。同一用户名重复调用返回同一 user_id。
38 rpc EnsureBotUser(EnsureBotUserRequest) returns (EnsureBotUserResponse);
39
40 // 校验旧口令后改写口令摘要,推进 security_version 并吊销全部会话(可保留调用方当前会话)。
41 // 口令只以客户端摘要(sha256 hex)形式出现,本服务不接触明文。
42 // mutation: request_id 通过 gitdata-request-id 头携带
43 rpc ChangePassword(ChangePasswordRequest) returns (ChangePasswordResponse);
44}
45
468message AuthenticateRequest {
479 auth.common.v1.Credential credential = 1;
4810
Modified lib/infra/proto/proto/auth/v1/mfa.proto View lib/infra/proto/proto/auth/v1/mfa.proto
@@ -6,46 +6,6 @@
66import "auth/common/v1/types.proto";
77import "google/protobuf/timestamp.proto";
88
9// 多因子状态与校验。调用方:api(登录第二因子步骤)、auth 自身(登录用例内部复用)。
10//
11// 安全边界:TOTP 密钥(user_mfa.secret_ciphertext)永不出 auth,也不提供读取密钥的 RPC;
12// 密钥明文只在 ConfigureTotp 的响应里出现一次,之后只以密文形式留存。
13// 绑定与解绑入口(ConfigureTotp / EnableTotp / DisableTotp / RegenerateRecoveryCodes)
14// 供外部账户服务的“两步验证”页面调用;口令只以客户端摘要形式出现。
15// VerifyTotp 与 RedeemRecoveryCode 都是 mutation:服务端按 user_mfa.last_totp_step 自行防重放,
16// 并消费一次性凭据,因此必须携带 request_id 以便审计。
17service MfaService {
18 // 查询某用户的多因子状态与剩余恢复码数量。
19 rpc GetMfaStatus(GetMfaStatusRequest) returns (GetMfaStatusResponse);
20
21 // 校验 TOTP 动态码。命中即推进 last_totp_step,同一码重复使用返回 TOTP_STEP_REUSED。
22 // mutation: request_id 通过 gitdata-request-id 头携带
23 rpc VerifyTotp(VerifyTotpRequest) returns (VerifyTotpResponse);
24
25 // 消费一枚恢复码。成功即标记 consumed_at,幂等重复调用返回 RECOVERY_CODE_INVALID。
26 // mutation: request_id 通过 gitdata-request-id 头携带
27 rpc RedeemRecoveryCode(RedeemRecoveryCodeRequest) returns (RedeemRecoveryCodeResponse);
28
29 // 生成新的 TOTP 密钥并以 pending 状态落库,返回密钥明文与 otpauth URI 供验证器录入。
30 // 该用户已有 pending 因子时原地替换;已有 enabled 因子时返回 ALREADY_EXISTS。
31 // mutation: request_id 通过 gitdata-request-id 头携带
32 rpc ConfigureTotp(ConfigureTotpRequest) returns (ConfigureTotpResponse);
33
34 // 校验动态码与账号口令摘要,把 pending 因子置为 enabled 并签发一批恢复码。
35 // 恢复码明文只在本响应出现一次;同用户此前未消费的恢复码会被吊销。
36 // mutation: request_id 通过 gitdata-request-id 头携带
37 rpc EnableTotp(EnableTotpRequest) returns (EnableTotpResponse);
38
39 // 校验动态码或恢复码后吊销该用户的 TOTP 因子,并吊销全部恢复码。
40 // 没有 enabled 因子时返回 disabled=false 而不报错(幂等)。
41 // mutation: request_id 通过 gitdata-request-id 头携带
42 rpc DisableTotp(DisableTotpRequest) returns (DisableTotpResponse);
43
44 // 校验账号口令摘要后重建恢复码批次,返回新的一批明文。
45 // mutation: request_id 通过 gitdata-request-id 头携带
46 rpc RegenerateRecoveryCodes(RegenerateRecoveryCodesRequest) returns (RegenerateRecoveryCodesResponse);
47}
48
499message GetMfaStatusRequest {
5010 int64 user_id = 1;
5111}
Modified lib/infra/proto/proto/auth/v1/session.proto View lib/infra/proto/proto/auth/v1/session.proto
@@ -5,31 +5,6 @@
55import "auth/common/v1/types.proto";
66import "google/protobuf/timestamp.proto";
77
8// 会话生命周期。调用方:api(设备管理页)、auth 自身的管理面、notify(异常登录提醒的收尾动作)。
9//
10// 入口由 `auth.oauth.rpc_key` 的共享密钥(`x-rpc-key` 头)把守,调用方身份由这把密钥统一把关;
11// 服务端只校验 session_id 确实属于请求里的 user_id。
12//
13// 会话校验不在这里:用会话密钥换 Principal 走 IdentityService.Authenticate。
14// 本服务只做列表、吊销与安全版本推进,全部为显式 mutation,不得隐式改状态。
15service SessionService {
16 // 列出某用户的会话。默认只返回未吊销的,按 last_seen_at 倒序。
17 rpc ListUserSessions(ListUserSessionsRequest) returns (ListUserSessionsResponse);
18
19 // 吊销单个会话。幂等:已吊销的会话重复调用仍返回 REVOKED。
20 // mutation: request_id 通过 gitdata-request-id 头携带
21 rpc RevokeSession(RevokeSessionRequest) returns (RevokeSessionResponse);
22
23 // 吊销某用户的全部会话(可保留调用方自己的当前会话)。
24 // mutation: request_id 通过 gitdata-request-id 头携带
25 rpc RevokeUserSessions(RevokeUserSessionsRequest) returns (RevokeUserSessionsResponse);
26
27 // 推进安全版本:users.security_version 自增,之后所有携带旧版本的凭据(会话、access token、
28 // 服务令牌)立即失效。口令变更、密钥吊销、账号锁定后必须调用。
29 // mutation: request_id 通过 gitdata-request-id 头携带
30 rpc BumpSecurityVersion(BumpSecurityVersionRequest) returns (BumpSecurityVersionResponse);
31}
32
338message ListUserSessionsRequest {
349 int64 user_id = 1;
3510 bool include_revoked = 2;
Deleted lib/infra/proto/proto/auth/v1/token.proto
@@ -1,123 +0,0 @@
1syntax = "proto3";
2
3package auth.v1;
4
5import "auth/common/v1/errors.proto";
6import "auth/common/v1/types.proto";
7import "google/protobuf/timestamp.proto";
8
9// 令牌签发与内省。调用方:api(为 chat / realtime / sfu / object / agent / notify 请求令牌)、
10// 各服务(连接建立或收到令牌后做内省)。
11//
12// 安全边界:
13// * JWT 签名私钥只存在于 auth;其他任何服务都不得持有,也不得自行签发同类令牌。
14// 需要某个受众的令牌时一律回调本服务,auth 依据调用方身份裁剪出最小权限集。
15// * 服务令牌携带 security_version,用户安全版本推进后自动失效,无需逐个吊销。
16// * 本服务不判定房间、仓库等资源内的准入:约束原样写入令牌,由受众服务自行决策。
17//
18// 用户 access token(Bearer,长期)的签发与吊销属于用户自助 HTTP 接口,
19// 不在此处暴露;其他服务只做内省与校验。
20service TokenService {
21 // 内省凭据。失败不返回 gRPC 错误:active=false + reason 便于网关统一处理。
22 rpc IntrospectToken(IntrospectTokenRequest) returns (IntrospectTokenResponse);
23
24 // 签发受约束服务令牌。仅受信后端(api.gitdata.ai)可调用,其他内部服务调用返回 FORBIDDEN。
25 // mutation: request_id 通过 gitdata-request-id 头携带
26 rpc IssueServiceToken(IssueServiceTokenRequest) returns (IssueServiceTokenResponse);
27
28 // 按 token_id 吊销服务令牌。对同一 token_id 重复调用幂等;event_id 用于跨重试去重。
29 // mutation: request_id 通过 gitdata-request-id 头携带
30 rpc RevokeServiceToken(RevokeServiceTokenRequest) returns (RevokeServiceTokenResponse);
31}
32
33message IntrospectTokenRequest {
34 // 只允许 access_token 或 service_token 两种凭据,其他 kind 返回 INVALID_ARGUMENT。
35 auth.common.v1.Credential credential = 1;
36 repeated auth.common.v1.TokenScope required_scopes = 2;
37}
38
39message IntrospectTokenResponse {
40 bool active = 1;
41 // active=false 时说明原因,取值同 auth/common/v1/errors.proto 的 Code:TOKEN_EXPIRED /
42 // TOKEN_REVOKED / SECURITY_VERSION_STALE / UNAUTHENTICATED。
43 auth.common.v1.Code reason = 2;
44 string token_id = 3;
45 auth.common.v1.TokenAudience audience = 4; // 服务令牌有效;用户令牌为 UNSPECIFIED
46 auth.common.v1.Principal principal = 5; // 用户令牌有效时非空
47 repeated auth.common.v1.TokenScope scopes = 6;
48 int32 security_version = 7;
49 google.protobuf.Timestamp issued_at = 8;
50 google.protobuf.Timestamp expires_at = 9;
51}
52
53message IssueServiceTokenRequest {
54 auth.common.v1.TokenAudience audience = 1; // 必须指定,UNSPECIFIED 返回 INVALID_ARGUMENT
55 int64 subject_user_id = 2; // 令牌代表哪个用户
56 repeated auth.common.v1.TokenScope scopes = 3; // 必须 ⊆ 该用户当前有效范围,超出返回 SCOPE_INSUFFICIENT
57
58 // 默认 900,上限 3600;超出上限返回 INVALID_EXPIRY。
59 uint32 ttl_seconds = 4;
60
61 // 可选的资源约束,原样写入令牌载荷。只允许一种,二者同时给出返回 INVALID_ARGUMENT。
62 oneof constraint {
63 ChatGrant chat = 5;
64 SfuGrant sfu = 6;
65 }
66
67 string event_id = 7; // 幂等键:同一 event_id 重复请求返回首次签发的令牌,不重复计数
68}
69
70// 房间能力集。缺省布尔值一律为 false;manage 默认不可请求,需调用方具备管理范围。
71message ChatGrant {
72 string tenant_id = 1;
73 repeated RoomGrant room_grants = 2;
74}
75
76message RoomGrant {
77 string room_id = 1;
78 bool join = 2;
79 bool subscribe = 3;
80 bool publish = 4;
81 bool history = 5;
82 bool presence = 6;
83 bool manage = 7;
84}
85
86// 音视频场景(livekit)能力:一个场景一个房间,角色决定可发布轨道。
87message SfuGrant {
88 string scene_id = 1;
89 string room_name = 2;
90 SfuRole role = 3;
91 bool can_publish_audio = 4;
92 bool can_publish_video = 5;
93 bool can_publish_screen = 6;
94 bool can_subscribe = 7;
95}
96
97enum SfuRole {
98 SFU_ROLE_UNSPECIFIED = 0;
99 SFU_ROLE_VIEWER = 1;
100 SFU_ROLE_SPEAKER = 2;
101 SFU_ROLE_MODERATOR = 3;
102}
103
104message IssueServiceTokenResponse {
105 string service_token = 1; // JWT,紧凑序列化
106 string token_id = 2; // 用于吊销与审计
107 string key_id = 3; // JWT 头中的 kid,受众服务据此选择验证公钥
108 int64 subject_user_id = 4;
109 int32 security_version = 5; // 写入令牌的用户安全版本
110 google.protobuf.Timestamp issued_at = 6;
111 google.protobuf.Timestamp expires_at = 7;
112}
113
114message RevokeServiceTokenRequest {
115 string token_id = 1;
116 string event_id = 2; // 幂等键
117 string reason = 3;
118}
119
120message RevokeServiceTokenResponse {
121 bool accepted = 1;
122 bool already_revoked = 2; // true = 此次调用为重复请求
123}
Modified .gitignore View .gitignore
@@ -14,3 +14,4 @@
1414config/api/keys/
1515actor.node
1616config/dev-keys/
17.archify
No newline at end of file