@aepstore-dev/contracts 1.107.0 → 1.108.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/gen/activity.js +1 -1
- package/gen/activity.ts +1 -1
- package/gen/auth.js +1 -1
- package/gen/auth.ts +1 -1
- package/gen/mail.js +1 -1
- package/gen/mail.ts +1 -1
- package/gen/notifications.js +1 -1
- package/gen/notifications.ts +1 -1
- package/gen/payments.js +1 -1
- package/gen/payments.ts +1 -1
- package/gen/products.js +1 -1
- package/gen/products.ts +1 -1
- package/gen/support.js +1 -1
- package/gen/support.ts +1 -1
- package/gen/taxonomy.d.ts +5 -0
- package/gen/taxonomy.js +1 -1
- package/gen/taxonomy.ts +8 -1
- package/gen/upload.d.ts +40 -0
- package/gen/upload.js +4 -1
- package/gen/upload.ts +65 -1
- package/gen/users.d.ts +1 -0
- package/gen/users.js +1 -1
- package/gen/users.ts +4 -1
- package/package.json +37 -35
- package/proto/activity.proto +200 -200
- package/proto/auth.proto +417 -417
- package/proto/mail.proto +54 -54
- package/proto/products.proto +382 -382
- package/proto/taxonomy.proto +106 -101
- package/proto/upload.proto +194 -155
- package/proto/users.proto +1 -0
package/proto/auth.proto
CHANGED
|
@@ -1,417 +1,417 @@
|
|
|
1
|
-
syntax = "proto3";
|
|
2
|
-
|
|
3
|
-
package auth.v1;
|
|
4
|
-
|
|
5
|
-
// Ported from legacy auth-service (@MessagePattern → @GrpcMethod).
|
|
6
|
-
// Tokens are HMAC primitives from @aepstore-dev/passport:
|
|
7
|
-
// - access token: short TTL, carries userId; the gateway validates it
|
|
8
|
-
// locally via PassportAuthGuard (no round-trip here).
|
|
9
|
-
// - refresh token: long TTL HMAC + a RefreshToken DB row (device list +
|
|
10
|
-
// revocation). Refresh verifies the HMAC AND that the row still exists.
|
|
11
|
-
service AuthService {
|
|
12
|
-
rpc Login(LoginRequest) returns (AuthResult);
|
|
13
|
-
rpc Register(RegisterRequest) returns (AuthResult);
|
|
14
|
-
rpc CreateCode(CreateCodeRequest) returns (AuthResult);
|
|
15
|
-
rpc VerifyCode(VerifyCodeRequest) returns (AuthResult);
|
|
16
|
-
rpc CheckToken(CheckTokenRequest) returns (AuthUser);
|
|
17
|
-
rpc RefreshToken(RefreshTokenRequest) returns (AuthResult);
|
|
18
|
-
rpc Get2faStatus(Get2faStatusRequest) returns (TwoFactorStatusResponse);
|
|
19
|
-
rpc GetProfile(GetProfileRequest) returns (AuthUser);
|
|
20
|
-
rpc CleanupExpiredTotpSetups(Empty) returns (Empty);
|
|
21
|
-
rpc ResetUserTwoFactor(ResetUserTwoFactorRequest) returns (ResetUserTwoFactorResponse);
|
|
22
|
-
rpc GeneratePasskeyRegistrationOptions(GeneratePasskeyRegistrationOptionsRequest) returns (PasskeyOptionsResponse);
|
|
23
|
-
rpc VerifyPasskeyRegistration(VerifyPasskeyRegistrationRequest) returns (PasskeyRegistrationResponse);
|
|
24
|
-
rpc ListPasskeys(ListPasskeysRequest) returns (ListPasskeysResponse);
|
|
25
|
-
rpc DeletePasskey(DeletePasskeyRequest) returns (DeletePasskeyResponse);
|
|
26
|
-
rpc GeneratePasskeyAuthenticationOptions(GeneratePasskeyAuthenticationOptionsRequest) returns (PasskeyOptionsResponse);
|
|
27
|
-
rpc VerifyPasskeyAuthentication(VerifyPasskeyAuthenticationRequest) returns (AuthResult);
|
|
28
|
-
|
|
29
|
-
// First-party OAuth 2.0 provider. Authorization codes use PKCE S256;
|
|
30
|
-
// access/refresh tokens are opaque, scoped and independently revocable.
|
|
31
|
-
rpc ValidateOAuthAuthorizationRequest(ValidateOAuthAuthorizationRequestInput) returns (OAuthAuthorizationRequestInfo);
|
|
32
|
-
rpc CreateOAuthAuthorizationCode(CreateOAuthAuthorizationCodeRequest) returns (CreateOAuthAuthorizationCodeResponse);
|
|
33
|
-
rpc ExchangeOAuthToken(ExchangeOAuthTokenRequest) returns (OAuthTokenResponse);
|
|
34
|
-
rpc GetOAuthUserInfo(OAuthResourceRequest) returns (OAuthUserInfoResponse);
|
|
35
|
-
rpc ListOAuthProducts(OAuthResourceRequest) returns (OAuthProductsResponse);
|
|
36
|
-
rpc ListOAuthAuthorizations(ListOAuthAuthorizationsRequest) returns (ListOAuthAuthorizationsResponse);
|
|
37
|
-
rpc RevokeOAuthAuthorization(RevokeOAuthAuthorizationRequest) returns (RevokeOAuthAuthorizationResponse);
|
|
38
|
-
|
|
39
|
-
// Logout — kill refresh tokens. LogoutCurrent kills only the one whose
|
|
40
|
-
// HMAC matches; LogoutAll wipes every row for the user.
|
|
41
|
-
rpc LogoutCurrent(LogoutCurrentRequest) returns (LogoutResponse);
|
|
42
|
-
rpc LogoutAll(LogoutAllRequest) returns (LogoutResponse);
|
|
43
|
-
|
|
44
|
-
// Self-service restore. Verifies credentials + password against a
|
|
45
|
-
// soft-deleted user, clears deletedAt/scheduledForHardDelete, and issues
|
|
46
|
-
// fresh tokens — the one auth path that DOES read deletedAt accounts.
|
|
47
|
-
rpc RestoreLogin(RestoreLoginRequest) returns (AuthResult);
|
|
48
|
-
|
|
49
|
-
// Login history. Read-only audit feed for the settings page; rows come
|
|
50
|
-
// from LoginEvent. Internal alternative: tasks-service GC.
|
|
51
|
-
rpc ListLoginHistory(ListLoginHistoryRequest) returns (ListLoginHistoryResponse);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
enum TwoFactorType {
|
|
55
|
-
NONE = 0;
|
|
56
|
-
APP = 1;
|
|
57
|
-
EMAIL = 2;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// ---------------------------------------------------------------------------
|
|
61
|
-
// Requests
|
|
62
|
-
// ---------------------------------------------------------------------------
|
|
63
|
-
|
|
64
|
-
// Login by username OR email (one of the two must be set).
|
|
65
|
-
message LoginRequest {
|
|
66
|
-
string password = 1;
|
|
67
|
-
string credentials = 2; // username OR email — resolved by the service
|
|
68
|
-
// Gateway-supplied audit context. LoginEvent rows for LOGIN /
|
|
69
|
-
// PASSWORD_FAIL get the same ip/user-agent that REFRESH and RESTORE
|
|
70
|
-
// already carry; the gRPC layer has no transport-level access to
|
|
71
|
-
// either, so the gateway extracts them from the HTTP request.
|
|
72
|
-
string user_agent = 3;
|
|
73
|
-
string ip = 4;
|
|
74
|
-
string trusted_device_token = 5;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
message RegisterRequest {
|
|
78
|
-
string email = 1;
|
|
79
|
-
string username = 2;
|
|
80
|
-
string password = 3;
|
|
81
|
-
string ip = 4; // optional, attached by gateway from req
|
|
82
|
-
string user_agent = 5; // optional, attached by gateway from req
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// type ∈ { twofa, reset, totp_generate, confirm } (legacy strings)
|
|
86
|
-
message CreateCodeRequest {
|
|
87
|
-
string email = 1;
|
|
88
|
-
string type = 2;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// type ∈ { twofa, twofa_activate, twofa_deactivate, reset, totp, totp_activate,
|
|
92
|
-
// totp_deactivate, backup, regenerate_backup, confirm }
|
|
93
|
-
// regenerate_backup expects a current TOTP code, not an existing backup code.
|
|
94
|
-
// new_password is only used by the 'reset' flow.
|
|
95
|
-
message VerifyCodeRequest {
|
|
96
|
-
string email = 1;
|
|
97
|
-
string code = 2;
|
|
98
|
-
string type = 3;
|
|
99
|
-
string new_password = 4; // optional
|
|
100
|
-
string challenge_id = 5;
|
|
101
|
-
bool remember_device = 6;
|
|
102
|
-
string user_agent = 7;
|
|
103
|
-
string ip = 8;
|
|
104
|
-
// Internal service-to-service confirmation for sensitive account actions.
|
|
105
|
-
// Public login completions must use challenge_id instead.
|
|
106
|
-
bool account_verification = 9;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
message CheckTokenRequest {
|
|
110
|
-
string token = 1;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
message RefreshTokenRequest {
|
|
114
|
-
string refresh_token = 1;
|
|
115
|
-
string user_agent = 2; // optional
|
|
116
|
-
string ip = 3; // optional
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
message Get2faStatusRequest {
|
|
120
|
-
string username = 1;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
message GetProfileRequest {
|
|
124
|
-
string user_id = 1;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
message ResetUserTwoFactorRequest {
|
|
128
|
-
string target_user_id = 1;
|
|
129
|
-
string admin_id = 2;
|
|
130
|
-
string reason = 3;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
message GeneratePasskeyRegistrationOptionsRequest {
|
|
134
|
-
string user_id = 1;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
message VerifyPasskeyRegistrationRequest {
|
|
138
|
-
string user_id = 1;
|
|
139
|
-
string challenge_id = 2;
|
|
140
|
-
// Raw JSON returned by @simplewebauthn/browser startRegistration().
|
|
141
|
-
string response_json = 3;
|
|
142
|
-
string name = 4;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
message ListPasskeysRequest {
|
|
146
|
-
string user_id = 1;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
message DeletePasskeyRequest {
|
|
150
|
-
string user_id = 1;
|
|
151
|
-
string passkey_id = 2;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
message GeneratePasskeyAuthenticationOptionsRequest {
|
|
155
|
-
reserved 1;
|
|
156
|
-
reserved "credentials";
|
|
157
|
-
string user_agent = 2;
|
|
158
|
-
string ip = 3;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
message VerifyPasskeyAuthenticationRequest {
|
|
162
|
-
string challenge_id = 1;
|
|
163
|
-
// Raw JSON returned by @simplewebauthn/browser startAuthentication().
|
|
164
|
-
string response_json = 2;
|
|
165
|
-
string user_agent = 3;
|
|
166
|
-
string ip = 4;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
message CreateOAuthAuthorizationCodeRequest {
|
|
170
|
-
string user_id = 1;
|
|
171
|
-
string response_type = 2;
|
|
172
|
-
string client_id = 3;
|
|
173
|
-
string redirect_uri = 4;
|
|
174
|
-
repeated string scopes = 5;
|
|
175
|
-
string code_challenge = 6;
|
|
176
|
-
string code_challenge_method = 7;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
message ValidateOAuthAuthorizationRequestInput {
|
|
180
|
-
string response_type = 1;
|
|
181
|
-
string client_id = 2;
|
|
182
|
-
string redirect_uri = 3;
|
|
183
|
-
repeated string scopes = 4;
|
|
184
|
-
string code_challenge = 5;
|
|
185
|
-
string code_challenge_method = 6;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
message OAuthAuthorizationRequestInfo {
|
|
189
|
-
string client_id = 1;
|
|
190
|
-
string client_name = 2;
|
|
191
|
-
string redirect_uri = 3;
|
|
192
|
-
repeated string scopes = 4;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
message CreateOAuthAuthorizationCodeResponse {
|
|
196
|
-
string code = 1;
|
|
197
|
-
string redirect_uri = 2;
|
|
198
|
-
int32 expires_in = 3;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
message ExchangeOAuthTokenRequest {
|
|
202
|
-
string grant_type = 1;
|
|
203
|
-
string code = 2;
|
|
204
|
-
string refresh_token = 3;
|
|
205
|
-
string client_id = 4;
|
|
206
|
-
string client_secret = 5;
|
|
207
|
-
string redirect_uri = 6;
|
|
208
|
-
string code_verifier = 7;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
message OAuthTokenResponse {
|
|
212
|
-
string access_token = 1;
|
|
213
|
-
string token_type = 2;
|
|
214
|
-
int32 expires_in = 3;
|
|
215
|
-
string refresh_token = 4;
|
|
216
|
-
string scope = 5;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
message OAuthResourceRequest {
|
|
220
|
-
string access_token = 1;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
message OAuthPremiumInfo {
|
|
224
|
-
bool active = 1;
|
|
225
|
-
string expires_at = 2;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
message OAuthUserInfoResponse {
|
|
229
|
-
string id = 1;
|
|
230
|
-
string email = 2;
|
|
231
|
-
string username = 3;
|
|
232
|
-
string full_name = 4;
|
|
233
|
-
string avatar_url = 5;
|
|
234
|
-
OAuthPremiumInfo premium = 6;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
message OAuthProduct {
|
|
238
|
-
string id = 1;
|
|
239
|
-
string name = 2;
|
|
240
|
-
string description = 3;
|
|
241
|
-
string preview = 4;
|
|
242
|
-
string price = 5;
|
|
243
|
-
string currency = 6;
|
|
244
|
-
string public_url = 7;
|
|
245
|
-
string moderation_status = 8;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
message OAuthProductsResponse {
|
|
249
|
-
repeated OAuthProduct items = 1;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
message ListOAuthAuthorizationsRequest {
|
|
253
|
-
string user_id = 1;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
message OAuthAuthorization {
|
|
257
|
-
string client_id = 1;
|
|
258
|
-
string client_name = 2;
|
|
259
|
-
repeated string scopes = 3;
|
|
260
|
-
string granted_at = 4;
|
|
261
|
-
string last_used_at = 5;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
message ListOAuthAuthorizationsResponse {
|
|
265
|
-
repeated OAuthAuthorization items = 1;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
message RevokeOAuthAuthorizationRequest {
|
|
269
|
-
string user_id = 1;
|
|
270
|
-
string client_id = 2;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
message RevokeOAuthAuthorizationResponse {
|
|
274
|
-
bool revoked = 1;
|
|
275
|
-
int32 revoked_tokens = 2;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// ---------------------------------------------------------------------------
|
|
279
|
-
// Responses
|
|
280
|
-
// ---------------------------------------------------------------------------
|
|
281
|
-
|
|
282
|
-
message AuthUser {
|
|
283
|
-
string id = 1;
|
|
284
|
-
string username = 2;
|
|
285
|
-
string email = 3;
|
|
286
|
-
string avatar_url = 4;
|
|
287
|
-
string banner_url = 5;
|
|
288
|
-
repeated string roles = 6;
|
|
289
|
-
// Reserved: 7=role, 8=is_verified, 9=two_factor_type, 10=two_factor_enabled,
|
|
290
|
-
// 11=balance. Dropped in contracts 1.51.0 — clients read 2FA flags from
|
|
291
|
-
// AuthResult / /account/settings, balance from /payments/wallet.
|
|
292
|
-
reserved 7, 8, 9, 10, 11;
|
|
293
|
-
reserved "role", "is_verified", "two_factor_type", "two_factor_enabled", "balance";
|
|
294
|
-
string avatar_border = 12;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// Unified result for login/register/createCode/verifyCode/refresh. Which fields
|
|
298
|
-
// are populated depends on the flow:
|
|
299
|
-
// - fully authenticated → access_token + refresh_token + expires_in + user
|
|
300
|
-
// - 2FA required / pending confirm → message + two_factor_required + two_factor_type + user (no tokens)
|
|
301
|
-
// - totp_generate → secret + otpauth + qr (+ user)
|
|
302
|
-
// - totp_activate → backup_codes (+ tokens/user)
|
|
303
|
-
message AuthResult {
|
|
304
|
-
string access_token = 1;
|
|
305
|
-
string refresh_token = 2;
|
|
306
|
-
int32 expires_in = 3;
|
|
307
|
-
AuthUser user = 4;
|
|
308
|
-
|
|
309
|
-
string message = 5;
|
|
310
|
-
// Renamed from `requires_2fa` in 1.52.0: the digit-after-underscore broke
|
|
311
|
-
// the grpc proto-loader's camelCase pass (`_2` isn't `_<letter>`), so the
|
|
312
|
-
// wire key stayed snake_case and never matched the camelCase handler output
|
|
313
|
-
// → always serialised false. `two_factor_required` camelCases cleanly to
|
|
314
|
-
// `twoFactorRequired` on every layer. Field number 6 is unchanged (wire-
|
|
315
|
-
// compatible).
|
|
316
|
-
bool two_factor_required = 6;
|
|
317
|
-
TwoFactorType two_factor_type = 7;
|
|
318
|
-
|
|
319
|
-
// TOTP setup extras
|
|
320
|
-
string secret = 8;
|
|
321
|
-
string otpauth = 9;
|
|
322
|
-
string qr = 10; // data URL (PNG)
|
|
323
|
-
repeated string backup_codes = 11;
|
|
324
|
-
string challenge_id = 12;
|
|
325
|
-
string trusted_device_token = 13;
|
|
326
|
-
string trusted_device_expires_at = 14;
|
|
327
|
-
bool security_setup_required = 15;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
message TwoFactorStatusResponse {
|
|
331
|
-
TwoFactorType two_factor_type = 1;
|
|
332
|
-
bool has_2fa = 2;
|
|
333
|
-
bool is_verified = 3;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
message Empty {}
|
|
337
|
-
|
|
338
|
-
message LogoutCurrentRequest {
|
|
339
|
-
string refresh_token = 1;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
message LogoutAllRequest {
|
|
343
|
-
string user_id = 1;
|
|
344
|
-
// Current session's refresh token — excluded from the wipe so "log out
|
|
345
|
-
// everywhere" keeps THIS device signed in. Empty = revoke every session.
|
|
346
|
-
string refresh_token = 2;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
message LogoutResponse {
|
|
350
|
-
bool ok = 1;
|
|
351
|
-
int32 removed = 2; // number of refresh-token rows deleted
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
message ResetUserTwoFactorResponse {
|
|
355
|
-
bool ok = 1;
|
|
356
|
-
TwoFactorType previous_type = 2;
|
|
357
|
-
int32 revoked_sessions = 3;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
message PasskeyOptionsResponse {
|
|
361
|
-
// PublicKeyCredentialCreationOptionsJSON or PublicKeyCredentialRequestOptionsJSON.
|
|
362
|
-
string options_json = 1;
|
|
363
|
-
string challenge_id = 2;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
message PasskeyInfo {
|
|
367
|
-
string id = 1;
|
|
368
|
-
string name = 2;
|
|
369
|
-
string created_at = 3;
|
|
370
|
-
string last_used_at = 4;
|
|
371
|
-
string device_type = 5;
|
|
372
|
-
bool backed_up = 6;
|
|
373
|
-
repeated string transports = 7;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
message PasskeyRegistrationResponse {
|
|
377
|
-
bool ok = 1;
|
|
378
|
-
PasskeyInfo passkey = 2;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
message ListPasskeysResponse {
|
|
382
|
-
repeated PasskeyInfo items = 1;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
message DeletePasskeyResponse {
|
|
386
|
-
bool ok = 1;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
message RestoreLoginRequest {
|
|
390
|
-
string credentials = 1; // email or username
|
|
391
|
-
string password = 2;
|
|
392
|
-
string user_agent = 3;
|
|
393
|
-
string ip = 4;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
message ListLoginHistoryRequest {
|
|
397
|
-
string user_id = 1;
|
|
398
|
-
int32 page = 2;
|
|
399
|
-
int32 limit = 3;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
message LoginEventRow {
|
|
403
|
-
string id = 1;
|
|
404
|
-
string type = 2; // LOGIN | LOGOUT | REFRESH | TWO_FA_FAIL | PASSWORD_FAIL | BLOCKED | RESTORE
|
|
405
|
-
bool success = 3;
|
|
406
|
-
string reason = 4;
|
|
407
|
-
string ip = 5;
|
|
408
|
-
string user_agent = 6;
|
|
409
|
-
string created_at = 7;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
message ListLoginHistoryResponse {
|
|
413
|
-
repeated LoginEventRow items = 1;
|
|
414
|
-
int32 total = 2;
|
|
415
|
-
int32 page = 3;
|
|
416
|
-
int32 limit = 4;
|
|
417
|
-
}
|
|
1
|
+
syntax = "proto3";
|
|
2
|
+
|
|
3
|
+
package auth.v1;
|
|
4
|
+
|
|
5
|
+
// Ported from legacy auth-service (@MessagePattern → @GrpcMethod).
|
|
6
|
+
// Tokens are HMAC primitives from @aepstore-dev/passport:
|
|
7
|
+
// - access token: short TTL, carries userId; the gateway validates it
|
|
8
|
+
// locally via PassportAuthGuard (no round-trip here).
|
|
9
|
+
// - refresh token: long TTL HMAC + a RefreshToken DB row (device list +
|
|
10
|
+
// revocation). Refresh verifies the HMAC AND that the row still exists.
|
|
11
|
+
service AuthService {
|
|
12
|
+
rpc Login(LoginRequest) returns (AuthResult);
|
|
13
|
+
rpc Register(RegisterRequest) returns (AuthResult);
|
|
14
|
+
rpc CreateCode(CreateCodeRequest) returns (AuthResult);
|
|
15
|
+
rpc VerifyCode(VerifyCodeRequest) returns (AuthResult);
|
|
16
|
+
rpc CheckToken(CheckTokenRequest) returns (AuthUser);
|
|
17
|
+
rpc RefreshToken(RefreshTokenRequest) returns (AuthResult);
|
|
18
|
+
rpc Get2faStatus(Get2faStatusRequest) returns (TwoFactorStatusResponse);
|
|
19
|
+
rpc GetProfile(GetProfileRequest) returns (AuthUser);
|
|
20
|
+
rpc CleanupExpiredTotpSetups(Empty) returns (Empty);
|
|
21
|
+
rpc ResetUserTwoFactor(ResetUserTwoFactorRequest) returns (ResetUserTwoFactorResponse);
|
|
22
|
+
rpc GeneratePasskeyRegistrationOptions(GeneratePasskeyRegistrationOptionsRequest) returns (PasskeyOptionsResponse);
|
|
23
|
+
rpc VerifyPasskeyRegistration(VerifyPasskeyRegistrationRequest) returns (PasskeyRegistrationResponse);
|
|
24
|
+
rpc ListPasskeys(ListPasskeysRequest) returns (ListPasskeysResponse);
|
|
25
|
+
rpc DeletePasskey(DeletePasskeyRequest) returns (DeletePasskeyResponse);
|
|
26
|
+
rpc GeneratePasskeyAuthenticationOptions(GeneratePasskeyAuthenticationOptionsRequest) returns (PasskeyOptionsResponse);
|
|
27
|
+
rpc VerifyPasskeyAuthentication(VerifyPasskeyAuthenticationRequest) returns (AuthResult);
|
|
28
|
+
|
|
29
|
+
// First-party OAuth 2.0 provider. Authorization codes use PKCE S256;
|
|
30
|
+
// access/refresh tokens are opaque, scoped and independently revocable.
|
|
31
|
+
rpc ValidateOAuthAuthorizationRequest(ValidateOAuthAuthorizationRequestInput) returns (OAuthAuthorizationRequestInfo);
|
|
32
|
+
rpc CreateOAuthAuthorizationCode(CreateOAuthAuthorizationCodeRequest) returns (CreateOAuthAuthorizationCodeResponse);
|
|
33
|
+
rpc ExchangeOAuthToken(ExchangeOAuthTokenRequest) returns (OAuthTokenResponse);
|
|
34
|
+
rpc GetOAuthUserInfo(OAuthResourceRequest) returns (OAuthUserInfoResponse);
|
|
35
|
+
rpc ListOAuthProducts(OAuthResourceRequest) returns (OAuthProductsResponse);
|
|
36
|
+
rpc ListOAuthAuthorizations(ListOAuthAuthorizationsRequest) returns (ListOAuthAuthorizationsResponse);
|
|
37
|
+
rpc RevokeOAuthAuthorization(RevokeOAuthAuthorizationRequest) returns (RevokeOAuthAuthorizationResponse);
|
|
38
|
+
|
|
39
|
+
// Logout — kill refresh tokens. LogoutCurrent kills only the one whose
|
|
40
|
+
// HMAC matches; LogoutAll wipes every row for the user.
|
|
41
|
+
rpc LogoutCurrent(LogoutCurrentRequest) returns (LogoutResponse);
|
|
42
|
+
rpc LogoutAll(LogoutAllRequest) returns (LogoutResponse);
|
|
43
|
+
|
|
44
|
+
// Self-service restore. Verifies credentials + password against a
|
|
45
|
+
// soft-deleted user, clears deletedAt/scheduledForHardDelete, and issues
|
|
46
|
+
// fresh tokens — the one auth path that DOES read deletedAt accounts.
|
|
47
|
+
rpc RestoreLogin(RestoreLoginRequest) returns (AuthResult);
|
|
48
|
+
|
|
49
|
+
// Login history. Read-only audit feed for the settings page; rows come
|
|
50
|
+
// from LoginEvent. Internal alternative: tasks-service GC.
|
|
51
|
+
rpc ListLoginHistory(ListLoginHistoryRequest) returns (ListLoginHistoryResponse);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
enum TwoFactorType {
|
|
55
|
+
NONE = 0;
|
|
56
|
+
APP = 1;
|
|
57
|
+
EMAIL = 2;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
// Requests
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
|
|
64
|
+
// Login by username OR email (one of the two must be set).
|
|
65
|
+
message LoginRequest {
|
|
66
|
+
string password = 1;
|
|
67
|
+
string credentials = 2; // username OR email — resolved by the service
|
|
68
|
+
// Gateway-supplied audit context. LoginEvent rows for LOGIN /
|
|
69
|
+
// PASSWORD_FAIL get the same ip/user-agent that REFRESH and RESTORE
|
|
70
|
+
// already carry; the gRPC layer has no transport-level access to
|
|
71
|
+
// either, so the gateway extracts them from the HTTP request.
|
|
72
|
+
string user_agent = 3;
|
|
73
|
+
string ip = 4;
|
|
74
|
+
string trusted_device_token = 5;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
message RegisterRequest {
|
|
78
|
+
string email = 1;
|
|
79
|
+
string username = 2;
|
|
80
|
+
string password = 3;
|
|
81
|
+
string ip = 4; // optional, attached by gateway from req
|
|
82
|
+
string user_agent = 5; // optional, attached by gateway from req
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// type ∈ { twofa, reset, totp_generate, confirm } (legacy strings)
|
|
86
|
+
message CreateCodeRequest {
|
|
87
|
+
string email = 1;
|
|
88
|
+
string type = 2;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// type ∈ { twofa, twofa_activate, twofa_deactivate, reset, totp, totp_activate,
|
|
92
|
+
// totp_deactivate, backup, regenerate_backup, confirm }
|
|
93
|
+
// regenerate_backup expects a current TOTP code, not an existing backup code.
|
|
94
|
+
// new_password is only used by the 'reset' flow.
|
|
95
|
+
message VerifyCodeRequest {
|
|
96
|
+
string email = 1;
|
|
97
|
+
string code = 2;
|
|
98
|
+
string type = 3;
|
|
99
|
+
string new_password = 4; // optional
|
|
100
|
+
string challenge_id = 5;
|
|
101
|
+
bool remember_device = 6;
|
|
102
|
+
string user_agent = 7;
|
|
103
|
+
string ip = 8;
|
|
104
|
+
// Internal service-to-service confirmation for sensitive account actions.
|
|
105
|
+
// Public login completions must use challenge_id instead.
|
|
106
|
+
bool account_verification = 9;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
message CheckTokenRequest {
|
|
110
|
+
string token = 1;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
message RefreshTokenRequest {
|
|
114
|
+
string refresh_token = 1;
|
|
115
|
+
string user_agent = 2; // optional
|
|
116
|
+
string ip = 3; // optional
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
message Get2faStatusRequest {
|
|
120
|
+
string username = 1;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
message GetProfileRequest {
|
|
124
|
+
string user_id = 1;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
message ResetUserTwoFactorRequest {
|
|
128
|
+
string target_user_id = 1;
|
|
129
|
+
string admin_id = 2;
|
|
130
|
+
string reason = 3;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
message GeneratePasskeyRegistrationOptionsRequest {
|
|
134
|
+
string user_id = 1;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
message VerifyPasskeyRegistrationRequest {
|
|
138
|
+
string user_id = 1;
|
|
139
|
+
string challenge_id = 2;
|
|
140
|
+
// Raw JSON returned by @simplewebauthn/browser startRegistration().
|
|
141
|
+
string response_json = 3;
|
|
142
|
+
string name = 4;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
message ListPasskeysRequest {
|
|
146
|
+
string user_id = 1;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
message DeletePasskeyRequest {
|
|
150
|
+
string user_id = 1;
|
|
151
|
+
string passkey_id = 2;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
message GeneratePasskeyAuthenticationOptionsRequest {
|
|
155
|
+
reserved 1;
|
|
156
|
+
reserved "credentials";
|
|
157
|
+
string user_agent = 2;
|
|
158
|
+
string ip = 3;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
message VerifyPasskeyAuthenticationRequest {
|
|
162
|
+
string challenge_id = 1;
|
|
163
|
+
// Raw JSON returned by @simplewebauthn/browser startAuthentication().
|
|
164
|
+
string response_json = 2;
|
|
165
|
+
string user_agent = 3;
|
|
166
|
+
string ip = 4;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
message CreateOAuthAuthorizationCodeRequest {
|
|
170
|
+
string user_id = 1;
|
|
171
|
+
string response_type = 2;
|
|
172
|
+
string client_id = 3;
|
|
173
|
+
string redirect_uri = 4;
|
|
174
|
+
repeated string scopes = 5;
|
|
175
|
+
string code_challenge = 6;
|
|
176
|
+
string code_challenge_method = 7;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
message ValidateOAuthAuthorizationRequestInput {
|
|
180
|
+
string response_type = 1;
|
|
181
|
+
string client_id = 2;
|
|
182
|
+
string redirect_uri = 3;
|
|
183
|
+
repeated string scopes = 4;
|
|
184
|
+
string code_challenge = 5;
|
|
185
|
+
string code_challenge_method = 6;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
message OAuthAuthorizationRequestInfo {
|
|
189
|
+
string client_id = 1;
|
|
190
|
+
string client_name = 2;
|
|
191
|
+
string redirect_uri = 3;
|
|
192
|
+
repeated string scopes = 4;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
message CreateOAuthAuthorizationCodeResponse {
|
|
196
|
+
string code = 1;
|
|
197
|
+
string redirect_uri = 2;
|
|
198
|
+
int32 expires_in = 3;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
message ExchangeOAuthTokenRequest {
|
|
202
|
+
string grant_type = 1;
|
|
203
|
+
string code = 2;
|
|
204
|
+
string refresh_token = 3;
|
|
205
|
+
string client_id = 4;
|
|
206
|
+
string client_secret = 5;
|
|
207
|
+
string redirect_uri = 6;
|
|
208
|
+
string code_verifier = 7;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
message OAuthTokenResponse {
|
|
212
|
+
string access_token = 1;
|
|
213
|
+
string token_type = 2;
|
|
214
|
+
int32 expires_in = 3;
|
|
215
|
+
string refresh_token = 4;
|
|
216
|
+
string scope = 5;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
message OAuthResourceRequest {
|
|
220
|
+
string access_token = 1;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
message OAuthPremiumInfo {
|
|
224
|
+
bool active = 1;
|
|
225
|
+
string expires_at = 2;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
message OAuthUserInfoResponse {
|
|
229
|
+
string id = 1;
|
|
230
|
+
string email = 2;
|
|
231
|
+
string username = 3;
|
|
232
|
+
string full_name = 4;
|
|
233
|
+
string avatar_url = 5;
|
|
234
|
+
OAuthPremiumInfo premium = 6;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
message OAuthProduct {
|
|
238
|
+
string id = 1;
|
|
239
|
+
string name = 2;
|
|
240
|
+
string description = 3;
|
|
241
|
+
string preview = 4;
|
|
242
|
+
string price = 5;
|
|
243
|
+
string currency = 6;
|
|
244
|
+
string public_url = 7;
|
|
245
|
+
string moderation_status = 8;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
message OAuthProductsResponse {
|
|
249
|
+
repeated OAuthProduct items = 1;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
message ListOAuthAuthorizationsRequest {
|
|
253
|
+
string user_id = 1;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
message OAuthAuthorization {
|
|
257
|
+
string client_id = 1;
|
|
258
|
+
string client_name = 2;
|
|
259
|
+
repeated string scopes = 3;
|
|
260
|
+
string granted_at = 4;
|
|
261
|
+
string last_used_at = 5;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
message ListOAuthAuthorizationsResponse {
|
|
265
|
+
repeated OAuthAuthorization items = 1;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
message RevokeOAuthAuthorizationRequest {
|
|
269
|
+
string user_id = 1;
|
|
270
|
+
string client_id = 2;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
message RevokeOAuthAuthorizationResponse {
|
|
274
|
+
bool revoked = 1;
|
|
275
|
+
int32 revoked_tokens = 2;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
// Responses
|
|
280
|
+
// ---------------------------------------------------------------------------
|
|
281
|
+
|
|
282
|
+
message AuthUser {
|
|
283
|
+
string id = 1;
|
|
284
|
+
string username = 2;
|
|
285
|
+
string email = 3;
|
|
286
|
+
string avatar_url = 4;
|
|
287
|
+
string banner_url = 5;
|
|
288
|
+
repeated string roles = 6;
|
|
289
|
+
// Reserved: 7=role, 8=is_verified, 9=two_factor_type, 10=two_factor_enabled,
|
|
290
|
+
// 11=balance. Dropped in contracts 1.51.0 — clients read 2FA flags from
|
|
291
|
+
// AuthResult / /account/settings, balance from /payments/wallet.
|
|
292
|
+
reserved 7, 8, 9, 10, 11;
|
|
293
|
+
reserved "role", "is_verified", "two_factor_type", "two_factor_enabled", "balance";
|
|
294
|
+
string avatar_border = 12;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Unified result for login/register/createCode/verifyCode/refresh. Which fields
|
|
298
|
+
// are populated depends on the flow:
|
|
299
|
+
// - fully authenticated → access_token + refresh_token + expires_in + user
|
|
300
|
+
// - 2FA required / pending confirm → message + two_factor_required + two_factor_type + user (no tokens)
|
|
301
|
+
// - totp_generate → secret + otpauth + qr (+ user)
|
|
302
|
+
// - totp_activate → backup_codes (+ tokens/user)
|
|
303
|
+
message AuthResult {
|
|
304
|
+
string access_token = 1;
|
|
305
|
+
string refresh_token = 2;
|
|
306
|
+
int32 expires_in = 3;
|
|
307
|
+
AuthUser user = 4;
|
|
308
|
+
|
|
309
|
+
string message = 5;
|
|
310
|
+
// Renamed from `requires_2fa` in 1.52.0: the digit-after-underscore broke
|
|
311
|
+
// the grpc proto-loader's camelCase pass (`_2` isn't `_<letter>`), so the
|
|
312
|
+
// wire key stayed snake_case and never matched the camelCase handler output
|
|
313
|
+
// → always serialised false. `two_factor_required` camelCases cleanly to
|
|
314
|
+
// `twoFactorRequired` on every layer. Field number 6 is unchanged (wire-
|
|
315
|
+
// compatible).
|
|
316
|
+
bool two_factor_required = 6;
|
|
317
|
+
TwoFactorType two_factor_type = 7;
|
|
318
|
+
|
|
319
|
+
// TOTP setup extras
|
|
320
|
+
string secret = 8;
|
|
321
|
+
string otpauth = 9;
|
|
322
|
+
string qr = 10; // data URL (PNG)
|
|
323
|
+
repeated string backup_codes = 11;
|
|
324
|
+
string challenge_id = 12;
|
|
325
|
+
string trusted_device_token = 13;
|
|
326
|
+
string trusted_device_expires_at = 14;
|
|
327
|
+
bool security_setup_required = 15;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
message TwoFactorStatusResponse {
|
|
331
|
+
TwoFactorType two_factor_type = 1;
|
|
332
|
+
bool has_2fa = 2;
|
|
333
|
+
bool is_verified = 3;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
message Empty {}
|
|
337
|
+
|
|
338
|
+
message LogoutCurrentRequest {
|
|
339
|
+
string refresh_token = 1;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
message LogoutAllRequest {
|
|
343
|
+
string user_id = 1;
|
|
344
|
+
// Current session's refresh token — excluded from the wipe so "log out
|
|
345
|
+
// everywhere" keeps THIS device signed in. Empty = revoke every session.
|
|
346
|
+
string refresh_token = 2;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
message LogoutResponse {
|
|
350
|
+
bool ok = 1;
|
|
351
|
+
int32 removed = 2; // number of refresh-token rows deleted
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
message ResetUserTwoFactorResponse {
|
|
355
|
+
bool ok = 1;
|
|
356
|
+
TwoFactorType previous_type = 2;
|
|
357
|
+
int32 revoked_sessions = 3;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
message PasskeyOptionsResponse {
|
|
361
|
+
// PublicKeyCredentialCreationOptionsJSON or PublicKeyCredentialRequestOptionsJSON.
|
|
362
|
+
string options_json = 1;
|
|
363
|
+
string challenge_id = 2;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
message PasskeyInfo {
|
|
367
|
+
string id = 1;
|
|
368
|
+
string name = 2;
|
|
369
|
+
string created_at = 3;
|
|
370
|
+
string last_used_at = 4;
|
|
371
|
+
string device_type = 5;
|
|
372
|
+
bool backed_up = 6;
|
|
373
|
+
repeated string transports = 7;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
message PasskeyRegistrationResponse {
|
|
377
|
+
bool ok = 1;
|
|
378
|
+
PasskeyInfo passkey = 2;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
message ListPasskeysResponse {
|
|
382
|
+
repeated PasskeyInfo items = 1;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
message DeletePasskeyResponse {
|
|
386
|
+
bool ok = 1;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
message RestoreLoginRequest {
|
|
390
|
+
string credentials = 1; // email or username
|
|
391
|
+
string password = 2;
|
|
392
|
+
string user_agent = 3;
|
|
393
|
+
string ip = 4;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
message ListLoginHistoryRequest {
|
|
397
|
+
string user_id = 1;
|
|
398
|
+
int32 page = 2;
|
|
399
|
+
int32 limit = 3;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
message LoginEventRow {
|
|
403
|
+
string id = 1;
|
|
404
|
+
string type = 2; // LOGIN | LOGOUT | REFRESH | TWO_FA_FAIL | PASSWORD_FAIL | BLOCKED | RESTORE
|
|
405
|
+
bool success = 3;
|
|
406
|
+
string reason = 4;
|
|
407
|
+
string ip = 5;
|
|
408
|
+
string user_agent = 6;
|
|
409
|
+
string created_at = 7;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
message ListLoginHistoryResponse {
|
|
413
|
+
repeated LoginEventRow items = 1;
|
|
414
|
+
int32 total = 2;
|
|
415
|
+
int32 page = 3;
|
|
416
|
+
int32 limit = 4;
|
|
417
|
+
}
|