@corgelabs/corge 0.0.1 → 1.0.0

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.
Files changed (341) hide show
  1. package/dist/ai/index.d.ts +3 -0
  2. package/dist/ai/index.d.ts.map +1 -0
  3. package/dist/ai/index.js +3 -0
  4. package/dist/ai/index.js.map +1 -0
  5. package/dist/ai/schema.d.ts +83 -0
  6. package/dist/ai/schema.d.ts.map +1 -0
  7. package/dist/ai/schema.js +19 -0
  8. package/dist/ai/schema.js.map +1 -0
  9. package/dist/ai/service.d.ts +14 -0
  10. package/dist/ai/service.d.ts.map +1 -0
  11. package/dist/ai/service.js +266 -0
  12. package/dist/ai/service.js.map +1 -0
  13. package/dist/ai/utils.d.ts +10 -0
  14. package/dist/ai/utils.d.ts.map +1 -0
  15. package/dist/ai/utils.js +27 -0
  16. package/dist/ai/utils.js.map +1 -0
  17. package/dist/attachments/index.d.ts +4 -0
  18. package/dist/attachments/index.d.ts.map +1 -0
  19. package/dist/attachments/index.js +4 -0
  20. package/dist/attachments/index.js.map +1 -0
  21. package/dist/attachments/routes.d.ts +75 -0
  22. package/dist/attachments/routes.d.ts.map +1 -0
  23. package/dist/attachments/routes.js +18 -0
  24. package/dist/attachments/routes.js.map +1 -0
  25. package/dist/attachments/schema.d.ts +61 -0
  26. package/dist/attachments/schema.d.ts.map +1 -0
  27. package/dist/attachments/schema.js +30 -0
  28. package/dist/attachments/schema.js.map +1 -0
  29. package/dist/attachments/service.d.ts +27 -0
  30. package/dist/attachments/service.d.ts.map +1 -0
  31. package/dist/attachments/service.js +224 -0
  32. package/dist/attachments/service.js.map +1 -0
  33. package/dist/attachments/utils.d.ts +9 -0
  34. package/dist/attachments/utils.d.ts.map +1 -0
  35. package/dist/attachments/utils.js +80 -0
  36. package/dist/attachments/utils.js.map +1 -0
  37. package/dist/auth/index.d.ts +4 -0
  38. package/dist/auth/index.d.ts.map +1 -0
  39. package/dist/auth/index.js +4 -0
  40. package/dist/auth/index.js.map +1 -0
  41. package/dist/auth/oidc.d.ts +25 -0
  42. package/dist/auth/oidc.d.ts.map +1 -0
  43. package/dist/auth/oidc.js +298 -0
  44. package/dist/auth/oidc.js.map +1 -0
  45. package/dist/auth/recovery.d.ts +41 -0
  46. package/dist/auth/recovery.d.ts.map +1 -0
  47. package/dist/auth/recovery.js +250 -0
  48. package/dist/auth/recovery.js.map +1 -0
  49. package/dist/auth/routes.d.ts +226 -0
  50. package/dist/auth/routes.d.ts.map +1 -0
  51. package/dist/auth/routes.js +96 -0
  52. package/dist/auth/routes.js.map +1 -0
  53. package/dist/auth/schema.d.ts +158 -0
  54. package/dist/auth/schema.d.ts.map +1 -0
  55. package/dist/auth/schema.js +82 -0
  56. package/dist/auth/schema.js.map +1 -0
  57. package/dist/auth/service.d.ts +96 -0
  58. package/dist/auth/service.d.ts.map +1 -0
  59. package/dist/auth/service.js +129 -0
  60. package/dist/auth/service.js.map +1 -0
  61. package/dist/auth/session.d.ts +51 -0
  62. package/dist/auth/session.d.ts.map +1 -0
  63. package/dist/auth/session.js +344 -0
  64. package/dist/auth/session.js.map +1 -0
  65. package/dist/auth/utils.d.ts +17 -0
  66. package/dist/auth/utils.d.ts.map +1 -0
  67. package/dist/auth/utils.js +96 -0
  68. package/dist/auth/utils.js.map +1 -0
  69. package/dist/bin/corge.js +547 -0
  70. package/dist/chat/context.d.ts +10 -0
  71. package/dist/chat/context.d.ts.map +1 -0
  72. package/dist/chat/context.js +221 -0
  73. package/dist/chat/context.js.map +1 -0
  74. package/dist/chat/index.d.ts +4 -0
  75. package/dist/chat/index.d.ts.map +1 -0
  76. package/dist/chat/index.js +4 -0
  77. package/dist/chat/index.js.map +1 -0
  78. package/dist/chat/routes.d.ts +160 -0
  79. package/dist/chat/routes.d.ts.map +1 -0
  80. package/dist/chat/routes.js +210 -0
  81. package/dist/chat/routes.js.map +1 -0
  82. package/dist/chat/schema.d.ts +285 -0
  83. package/dist/chat/schema.d.ts.map +1 -0
  84. package/dist/chat/schema.js +74 -0
  85. package/dist/chat/schema.js.map +1 -0
  86. package/dist/chat/service.d.ts +64 -0
  87. package/dist/chat/service.d.ts.map +1 -0
  88. package/dist/chat/service.js +279 -0
  89. package/dist/chat/service.js.map +1 -0
  90. package/dist/chat/stream.d.ts +53 -0
  91. package/dist/chat/stream.d.ts.map +1 -0
  92. package/dist/chat/stream.js +339 -0
  93. package/dist/chat/stream.js.map +1 -0
  94. package/dist/chat/utils.d.ts +61 -0
  95. package/dist/chat/utils.d.ts.map +1 -0
  96. package/dist/chat/utils.js +285 -0
  97. package/dist/chat/utils.js.map +1 -0
  98. package/dist/cli/builder.d.ts +6 -0
  99. package/dist/cli/builder.d.ts.map +1 -0
  100. package/dist/cli/builder.js +91 -0
  101. package/dist/cli/builder.js.map +1 -0
  102. package/dist/cli/deployer.d.ts +2 -0
  103. package/dist/cli/deployer.d.ts.map +1 -0
  104. package/dist/cli/deployer.js +152 -0
  105. package/dist/cli/deployer.js.map +1 -0
  106. package/dist/cli/dev-server.d.ts +2 -0
  107. package/dist/cli/dev-server.d.ts.map +1 -0
  108. package/dist/cli/dev-server.js +70 -0
  109. package/dist/cli/dev-server.js.map +1 -0
  110. package/dist/cli/env.d.ts +4 -0
  111. package/dist/cli/env.d.ts.map +1 -0
  112. package/dist/cli/env.js +68 -0
  113. package/dist/cli/env.js.map +1 -0
  114. package/dist/cli/init.d.ts +6 -0
  115. package/dist/cli/init.d.ts.map +1 -0
  116. package/dist/cli/init.js +103 -0
  117. package/dist/cli/init.js.map +1 -0
  118. package/dist/config.d.ts +262 -0
  119. package/dist/config.d.ts.map +1 -0
  120. package/dist/config.js +212 -0
  121. package/dist/config.js.map +1 -0
  122. package/dist/db/index.d.ts +3 -0
  123. package/dist/db/index.d.ts.map +1 -0
  124. package/dist/db/index.js +3 -0
  125. package/dist/db/index.js.map +1 -0
  126. package/dist/db/schema.d.ts +410 -0
  127. package/dist/db/schema.d.ts.map +1 -0
  128. package/dist/db/schema.js +294 -0
  129. package/dist/db/schema.js.map +1 -0
  130. package/dist/db/service.d.ts +42 -0
  131. package/dist/db/service.d.ts.map +1 -0
  132. package/dist/db/service.js +372 -0
  133. package/dist/db/service.js.map +1 -0
  134. package/dist/db/utils.d.ts +25 -0
  135. package/dist/db/utils.d.ts.map +1 -0
  136. package/dist/db/utils.js +188 -0
  137. package/dist/db/utils.js.map +1 -0
  138. package/dist/emails/index.d.ts +4 -0
  139. package/dist/emails/index.d.ts.map +1 -0
  140. package/dist/emails/index.js +4 -0
  141. package/dist/emails/index.js.map +1 -0
  142. package/dist/emails/routes.d.ts +191 -0
  143. package/dist/emails/routes.d.ts.map +1 -0
  144. package/dist/emails/routes.js +39 -0
  145. package/dist/emails/routes.js.map +1 -0
  146. package/dist/emails/schema.d.ts +237 -0
  147. package/dist/emails/schema.d.ts.map +1 -0
  148. package/dist/emails/schema.js +98 -0
  149. package/dist/emails/schema.js.map +1 -0
  150. package/dist/emails/service.d.ts +22 -0
  151. package/dist/emails/service.d.ts.map +1 -0
  152. package/dist/emails/service.js +337 -0
  153. package/dist/emails/service.js.map +1 -0
  154. package/dist/emails/utils.d.ts +49 -0
  155. package/dist/emails/utils.d.ts.map +1 -0
  156. package/dist/emails/utils.js +341 -0
  157. package/dist/emails/utils.js.map +1 -0
  158. package/dist/files/index.d.ts +4 -0
  159. package/dist/files/index.d.ts.map +1 -0
  160. package/dist/files/index.js +4 -0
  161. package/dist/files/index.js.map +1 -0
  162. package/dist/files/routes.d.ts +72 -0
  163. package/dist/files/routes.d.ts.map +1 -0
  164. package/dist/files/routes.js +38 -0
  165. package/dist/files/routes.js.map +1 -0
  166. package/dist/files/schema.d.ts +57 -0
  167. package/dist/files/schema.d.ts.map +1 -0
  168. package/dist/files/schema.js +39 -0
  169. package/dist/files/schema.js.map +1 -0
  170. package/dist/files/service.d.ts +27 -0
  171. package/dist/files/service.d.ts.map +1 -0
  172. package/dist/files/service.js +175 -0
  173. package/dist/files/service.js.map +1 -0
  174. package/dist/files/utils.d.ts +3 -0
  175. package/dist/files/utils.d.ts.map +1 -0
  176. package/dist/files/utils.js +63 -0
  177. package/dist/files/utils.js.map +1 -0
  178. package/dist/index.d.ts +875 -0
  179. package/dist/index.d.ts.map +1 -0
  180. package/dist/index.js +9919 -0
  181. package/dist/index.js.map +7 -0
  182. package/dist/payments/billing.d.ts +29 -0
  183. package/dist/payments/billing.d.ts.map +1 -0
  184. package/dist/payments/billing.js +378 -0
  185. package/dist/payments/billing.js.map +1 -0
  186. package/dist/payments/index.d.ts +4 -0
  187. package/dist/payments/index.d.ts.map +1 -0
  188. package/dist/payments/index.js +4 -0
  189. package/dist/payments/index.js.map +1 -0
  190. package/dist/payments/routes.d.ts +340 -0
  191. package/dist/payments/routes.d.ts.map +1 -0
  192. package/dist/payments/routes.js +56 -0
  193. package/dist/payments/routes.js.map +1 -0
  194. package/dist/payments/schema.d.ts +412 -0
  195. package/dist/payments/schema.d.ts.map +1 -0
  196. package/dist/payments/schema.js +260 -0
  197. package/dist/payments/schema.js.map +1 -0
  198. package/dist/payments/service.d.ts +31 -0
  199. package/dist/payments/service.d.ts.map +1 -0
  200. package/dist/payments/service.js +322 -0
  201. package/dist/payments/service.js.map +1 -0
  202. package/dist/payments/utils.d.ts +61 -0
  203. package/dist/payments/utils.d.ts.map +1 -0
  204. package/dist/payments/utils.js +369 -0
  205. package/dist/payments/utils.js.map +1 -0
  206. package/dist/router/guard.d.ts +19 -0
  207. package/dist/router/guard.d.ts.map +1 -0
  208. package/dist/router/guard.js +243 -0
  209. package/dist/router/guard.js.map +1 -0
  210. package/dist/router/index.d.ts +3 -0
  211. package/dist/router/index.d.ts.map +1 -0
  212. package/dist/router/index.js +3 -0
  213. package/dist/router/index.js.map +1 -0
  214. package/dist/router/schema.d.ts +103 -0
  215. package/dist/router/schema.d.ts.map +1 -0
  216. package/dist/router/schema.js +282 -0
  217. package/dist/router/schema.js.map +1 -0
  218. package/dist/router/service.d.ts +25 -0
  219. package/dist/router/service.d.ts.map +1 -0
  220. package/dist/router/service.js +339 -0
  221. package/dist/router/service.js.map +1 -0
  222. package/dist/tasks/index.d.ts +4 -0
  223. package/dist/tasks/index.d.ts.map +1 -0
  224. package/dist/tasks/index.js +4 -0
  225. package/dist/tasks/index.js.map +1 -0
  226. package/dist/tasks/routes.d.ts +54 -0
  227. package/dist/tasks/routes.d.ts.map +1 -0
  228. package/dist/tasks/routes.js +195 -0
  229. package/dist/tasks/routes.js.map +1 -0
  230. package/dist/tasks/schema.d.ts +261 -0
  231. package/dist/tasks/schema.d.ts.map +1 -0
  232. package/dist/tasks/schema.js +35 -0
  233. package/dist/tasks/schema.js.map +1 -0
  234. package/dist/tasks/service.d.ts +32 -0
  235. package/dist/tasks/service.d.ts.map +1 -0
  236. package/dist/tasks/service.js +201 -0
  237. package/dist/tasks/service.js.map +1 -0
  238. package/dist/tasks/steps.d.ts +18 -0
  239. package/dist/tasks/steps.d.ts.map +1 -0
  240. package/dist/tasks/steps.js +365 -0
  241. package/dist/tasks/steps.js.map +1 -0
  242. package/dist/tasks/utils.d.ts +75 -0
  243. package/dist/tasks/utils.d.ts.map +1 -0
  244. package/dist/tasks/utils.js +311 -0
  245. package/dist/tasks/utils.js.map +1 -0
  246. package/dist/tasks/watcher.d.ts +13 -0
  247. package/dist/tasks/watcher.d.ts.map +1 -0
  248. package/dist/tasks/watcher.js +255 -0
  249. package/dist/tasks/watcher.js.map +1 -0
  250. package/dist/tasks/worker.d.ts +28 -0
  251. package/dist/tasks/worker.d.ts.map +1 -0
  252. package/dist/tasks/worker.js +326 -0
  253. package/dist/tasks/worker.js.map +1 -0
  254. package/dist/utils/index.d.ts +3 -0
  255. package/dist/utils/index.d.ts.map +1 -0
  256. package/dist/utils/index.js +3 -0
  257. package/dist/utils/index.js.map +1 -0
  258. package/dist/utils/schema.d.ts +79 -0
  259. package/dist/utils/schema.d.ts.map +1 -0
  260. package/dist/utils/schema.js +41 -0
  261. package/dist/utils/schema.js.map +1 -0
  262. package/dist/utils/service.d.ts +32 -0
  263. package/dist/utils/service.d.ts.map +1 -0
  264. package/dist/utils/service.js +384 -0
  265. package/dist/utils/service.js.map +1 -0
  266. package/docs/SDK_SPEC.md +1645 -0
  267. package/infra/firestore.base.indexes.json +138 -0
  268. package/infra/firestore.base.rules +152 -0
  269. package/infra/storage.base.rules +8 -0
  270. package/package.json +59 -13
  271. package/src/ai/index.ts +2 -0
  272. package/src/ai/schema.ts +64 -0
  273. package/src/ai/service.ts +317 -0
  274. package/src/ai/utils.ts +38 -0
  275. package/src/attachments/index.ts +3 -0
  276. package/src/attachments/routes.ts +28 -0
  277. package/src/attachments/schema.ts +45 -0
  278. package/src/attachments/service.ts +315 -0
  279. package/src/attachments/utils.ts +115 -0
  280. package/src/auth/index.ts +3 -0
  281. package/src/auth/oidc.ts +419 -0
  282. package/src/auth/recovery.ts +365 -0
  283. package/src/auth/routes.ts +142 -0
  284. package/src/auth/schema.ts +181 -0
  285. package/src/auth/service.ts +183 -0
  286. package/src/auth/session.ts +414 -0
  287. package/src/auth/utils.ts +106 -0
  288. package/src/chat/context.ts +310 -0
  289. package/src/chat/index.ts +3 -0
  290. package/src/chat/routes.ts +264 -0
  291. package/src/chat/schema.ts +295 -0
  292. package/src/chat/service.ts +360 -0
  293. package/src/chat/stream.ts +481 -0
  294. package/src/chat/utils.ts +370 -0
  295. package/src/cli/builder.ts +93 -0
  296. package/src/cli/deployer.ts +184 -0
  297. package/src/cli/dev-server.ts +77 -0
  298. package/src/cli/env.ts +89 -0
  299. package/src/cli/init.ts +125 -0
  300. package/src/config.ts +447 -0
  301. package/src/db/index.ts +2 -0
  302. package/src/db/schema.ts +409 -0
  303. package/src/db/service.ts +477 -0
  304. package/src/db/utils.ts +250 -0
  305. package/src/emails/index.ts +3 -0
  306. package/src/emails/routes.ts +64 -0
  307. package/src/emails/schema.ts +239 -0
  308. package/src/emails/service.ts +488 -0
  309. package/src/emails/utils.ts +449 -0
  310. package/src/files/index.ts +3 -0
  311. package/src/files/routes.ts +44 -0
  312. package/src/files/schema.ts +76 -0
  313. package/src/files/service.ts +238 -0
  314. package/src/files/utils.ts +77 -0
  315. package/src/index.ts +425 -0
  316. package/src/payments/billing.ts +488 -0
  317. package/src/payments/index.ts +3 -0
  318. package/src/payments/routes.ts +92 -0
  319. package/src/payments/schema.ts +401 -0
  320. package/src/payments/service.ts +445 -0
  321. package/src/payments/utils.ts +472 -0
  322. package/src/router/guard.ts +319 -0
  323. package/src/router/index.ts +2 -0
  324. package/src/router/schema.ts +458 -0
  325. package/src/router/service.ts +453 -0
  326. package/src/tasks/index.ts +11 -0
  327. package/src/tasks/routes.ts +230 -0
  328. package/src/tasks/schema.ts +310 -0
  329. package/src/tasks/service.ts +254 -0
  330. package/src/tasks/steps.ts +472 -0
  331. package/src/tasks/utils.ts +445 -0
  332. package/src/tasks/watcher.ts +307 -0
  333. package/src/tasks/worker.ts +461 -0
  334. package/src/utils/index.ts +2 -0
  335. package/src/utils/schema.ts +69 -0
  336. package/src/utils/service.ts +461 -0
  337. package/tests/e2e.test.ts +2531 -0
  338. package/tsconfig.base.json +12 -0
  339. package/README.md +0 -2
  340. package/index.d.ts +0 -1
  341. package/index.js +0 -1
@@ -0,0 +1,96 @@
1
+ import { type EntryId } from '../db';
2
+ import type { Core } from '../index';
3
+ import type { StepRunner } from '../tasks';
4
+ import { type AuthUser, type CompleteAccountRecoveryInput, type EraseUserInput, type EraseUserOutput, type ForgotPasswordInput, type InitiateAccountRecoveryInput, type ResetPasswordInput, type SetRecoveryEmailInput, type SocialSignInInput, type VerifyEmailInput, type VerifyRecoveryEmailInput } from './schema';
5
+ import { hashToken, resolveUserRole } from './utils';
6
+ export declare class AuthService {
7
+ #private;
8
+ constructor(coreClient: Core);
9
+ signInSocial: (raw: SocialSignInInput) => Promise<{
10
+ user: AuthUser;
11
+ sessionCookie: string;
12
+ }>;
13
+ sendVerificationEmail: (userId?: EntryId) => Promise<{
14
+ sent: true;
15
+ expiresInMinutes: number;
16
+ }>;
17
+ verifyEmail: (raw: VerifyEmailInput) => Promise<{
18
+ verified: true;
19
+ userId: string;
20
+ }>;
21
+ forgotPassword: (raw: ForgotPasswordInput) => Promise<{
22
+ sent: true;
23
+ }>;
24
+ resetPassword: (raw: ResetPasswordInput) => Promise<{
25
+ reset: true;
26
+ }>;
27
+ setRecoveryEmail: (raw: SetRecoveryEmailInput, userId?: EntryId) => Promise<{
28
+ recoveryEmail: string;
29
+ recoveryEmailVerified: false;
30
+ sent: true;
31
+ }>;
32
+ verifyRecoveryEmail: (raw: VerifyRecoveryEmailInput, userId?: EntryId) => Promise<{
33
+ recoveryEmail: string;
34
+ recoveryEmailVerified: true;
35
+ verified: true;
36
+ }>;
37
+ initiateAccountRecovery: (raw: InitiateAccountRecoveryInput) => Promise<{
38
+ initiated: true;
39
+ }>;
40
+ completeAccountRecovery: (raw: CompleteAccountRecoveryInput) => Promise<{
41
+ user: AuthUser;
42
+ sessionCookie: string;
43
+ }>;
44
+ getUser: (uid: EntryId) => Promise<AuthUser | undefined>;
45
+ setClaims: (uid: EntryId, claims: Record<string, unknown> | null) => Promise<void>;
46
+ listUsers: (includeDeleted?: boolean) => Promise<AuthUser[]>;
47
+ blockUser: (userId?: EntryId, blocked?: boolean) => Promise<{
48
+ userId: EntryId;
49
+ blocked: boolean;
50
+ deleted: boolean;
51
+ }>;
52
+ eraseUser: (raw: EraseUserInput, step?: StepRunner) => Promise<EraseUserOutput>;
53
+ get internals(): {
54
+ verifyToken: (token: string, isCookie: boolean, checkRevoked: boolean, isDev?: boolean) => Promise<{
55
+ uid: EntryId;
56
+ role: import("../config").DbRole;
57
+ emailVerified: boolean;
58
+ }>;
59
+ hashToken: typeof hashToken;
60
+ resolveUserRole: typeof resolveUserRole;
61
+ tokenCache: Map<string, import("./schema").CachedTokenEntry>;
62
+ setTokenCache: (token: string, uid: EntryId, role?: import("../config").DbRole, exp?: number, strictVerified?: boolean, emailVerified?: boolean) => void;
63
+ recordRevocation: (uid: EntryId, isDev?: boolean) => Promise<number>;
64
+ syncRevocations: (isDev?: boolean, force?: boolean) => Promise<Record<string, number>>;
65
+ getLastDevEmail: (to: string, purpose: import("./schema").AuthEmailPurpose) => import("./schema").TransactionalEmailPayload | undefined;
66
+ registerTestOidcPublicKey: (jwk: (import("crypto").JsonWebKey & {
67
+ kid?: string;
68
+ }) | null) => void;
69
+ readonly sessionCookie: string;
70
+ readonly authWarm: Promise<unknown>;
71
+ mintCustomToken: (uid?: string) => Promise<{
72
+ uid: string;
73
+ customToken: string;
74
+ }>;
75
+ createSession: (idToken: string, profile?: {
76
+ email?: string;
77
+ name?: string;
78
+ avatarUrl?: string;
79
+ emailVerified?: boolean;
80
+ }) => Promise<{
81
+ user: AuthUser;
82
+ sessionCookie: string;
83
+ }>;
84
+ signUpEmail: (email: string, password: string, name?: string) => Promise<{
85
+ user: AuthUser;
86
+ sessionCookie: string;
87
+ }>;
88
+ signInEmail: (email: string, password: string) => Promise<{
89
+ user: AuthUser;
90
+ sessionCookie: string;
91
+ }>;
92
+ revokeSession: (sessionCookie: string, deleteUser?: boolean) => Promise<void>;
93
+ setSessionCookie: (c: import("hono").Context<import("../config").AppEnv>, sessionCookie: string) => void;
94
+ };
95
+ }
96
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/auth/service.ts"],"names":[],"mappings":"AACA,OAAO,EAAgC,KAAK,OAAO,EAAE,MAAM,OAAO,CAAA;AAClE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AACpC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAG1C,OAAO,EAGL,KAAK,QAAQ,EACb,KAAK,4BAA4B,EACjC,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,4BAA4B,EACjC,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC9B,MAAM,UAAU,CAAA;AAEjB,OAAO,EAAE,SAAS,EAAiB,eAAe,EAAE,MAAM,SAAS,CAAA;AAEnE,qBAAa,WAAW;;IAMtB,YAAY,UAAU,EAAE,IAAI,EAK3B;IAED,YAAY,QAAS,iBAAiB,KAAG,OAAO,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC,CAC7D;IAE9B,qBAAqB,YAAa,OAAO,KAAG,OAAO,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,CAAC,CAC/C;IAE9C,WAAW,QAAS,gBAAgB,KAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CACjD;IAEjC,cAAc,QAAS,mBAAmB,KAAG,OAAO,CAAC;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,CAAC,CAAsC;IAE1G,aAAa,QAAS,kBAAkB,KAAG,OAAO,CAAC;QAAE,KAAK,EAAE,IAAI,CAAA;KAAE,CAAC,CAAqC;IAExG,gBAAgB,QACT,qBAAqB,WACjB,OAAO,KACf,OAAO,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,qBAAqB,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,IAAI,CAAA;KAAE,CAAC,CACjC;IAE9C,mBAAmB,QACZ,wBAAwB,WACpB,OAAO,KACf,OAAO,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,qBAAqB,EAAE,IAAI,CAAC;QAAC,QAAQ,EAAE,IAAI,CAAA;KAAE,CAAC,CACjC;IAEjD,uBAAuB,QAAS,4BAA4B,KAAG,OAAO,CAAC;QAAE,SAAS,EAAE,IAAI,CAAA;KAAE,CAAC,CAC9C;IAE7C,uBAAuB,QAAS,4BAA4B,KAAG,OAAO,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC,CACpE;IAE7C,OAAO,QAAe,OAAO,KAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAU5D;IAED,SAAS,QAAe,OAAO,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,KAAG,OAAO,CAAC,IAAI,CAAC,CAItF;IAED,SAAS,gCAAmC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAG9D;IAED,SAAS,YACC,OAAO,wBAEd,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAWlE;IAuBD,SAAS,QAAe,cAAc,SAAQ,UAAU,KAAqB,OAAO,CAAC,eAAe,CAAC,CA0BpG;IAED,IAAI,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAyBZ;CACF"}
@@ -0,0 +1,129 @@
1
+ import { CORE_CONFIG } from '../config';
2
+ import { getRegisteredCollectionNames } from '../db';
3
+ import { AuthOidcEngine } from './oidc';
4
+ import { AuthRecoveryEngine } from './recovery';
5
+ import { eraseUserInput, eraseUserOutput } from './schema';
6
+ import { AuthSessionEngine, tokenCache } from './session';
7
+ import { hashToken, mapUserRecord, resolveUserRole } from './utils';
8
+ export class AuthService {
9
+ #core;
10
+ #session;
11
+ #oidc;
12
+ #recovery;
13
+ constructor(coreClient) {
14
+ this.#core = coreClient;
15
+ this.#session = new AuthSessionEngine(coreClient);
16
+ this.#oidc = new AuthOidcEngine(coreClient, this.#session);
17
+ this.#recovery = new AuthRecoveryEngine(coreClient, this.#session);
18
+ }
19
+ signInSocial = (raw) => this.#oidc.signInSocial(raw);
20
+ sendVerificationEmail = (userId) => this.#recovery.sendVerificationEmail(userId);
21
+ verifyEmail = (raw) => this.#recovery.verifyEmail(raw);
22
+ forgotPassword = (raw) => this.#recovery.forgotPassword(raw);
23
+ resetPassword = (raw) => this.#recovery.resetPassword(raw);
24
+ setRecoveryEmail = (raw, userId) => this.#recovery.setRecoveryEmail(raw, userId);
25
+ verifyRecoveryEmail = (raw, userId) => this.#recovery.verifyRecoveryEmail(raw, userId);
26
+ initiateAccountRecovery = (raw) => this.#recovery.initiateAccountRecovery(raw);
27
+ completeAccountRecovery = (raw) => this.#recovery.completeAccountRecovery(raw);
28
+ getUser = async (uid) => {
29
+ try {
30
+ const [u, meta] = await Promise.all([
31
+ this.#session.getAuth().getUser(uid),
32
+ this.#session.getUserAuthMeta(uid, this.#core.env.isDev)
33
+ ]);
34
+ return mapUserRecord(u, meta);
35
+ }
36
+ catch {
37
+ return undefined;
38
+ }
39
+ };
40
+ setClaims = async (uid, claims) => {
41
+ await this.#session.getAuth().setCustomUserClaims(uid, claims);
42
+ this.#session.evictUserTokens(uid);
43
+ await this.#session.recordRevocation(uid, this.#core.env.isDev);
44
+ };
45
+ listUsers = async (includeDeleted = false) => {
46
+ const { users } = await this.#session.getAuth().listUsers(1000);
47
+ return users.map((u) => mapUserRecord(u)).filter((u) => includeDeleted || !u.deleted);
48
+ };
49
+ blockUser = async (userId = this.#core.userId, blocked = true) => {
50
+ const auth = this.#session.getAuth();
51
+ this.#session.evictUserTokens(userId);
52
+ await Promise.all([
53
+ blocked
54
+ ? this.#session.recordRevocation(userId, this.#core.env.isDev)
55
+ : this.#session.clearUserRevocation(userId, this.#core.env.isDev),
56
+ ...(blocked ? [auth.revokeRefreshTokens(userId).catch(() => { })] : []),
57
+ auth.updateUser(userId, { disabled: blocked }).catch(() => { })
58
+ ]);
59
+ return { userId, blocked, deleted: blocked };
60
+ };
61
+ #triggerFirestoreBackup = async (userId) => {
62
+ const projectId = this.#core.config.gcpProject;
63
+ const dbId = this.#core.env.isDev ? this.#core.config.firestoreDbs.dev : this.#core.config.firestoreDbs.prod;
64
+ const bucketName = this.#core.env.isDev
65
+ ? this.#core.config.storageBuckets.dev
66
+ : this.#core.config.storageBuckets.prod;
67
+ const outputUriPrefix = `gs://${bucketName}/backups/${dbId}-${userId}-${Date.now()}`;
68
+ const accessToken = await this.#core.internals.registry.getGcpAccessToken();
69
+ const res = await fetch(`https://firestore.googleapis.com/v1/projects/${projectId}/databases/${dbId}:exportDocuments`, {
70
+ method: 'POST',
71
+ headers: { Authorization: `Bearer ${accessToken}`, 'content-type': 'application/json' },
72
+ body: JSON.stringify({ outputUriPrefix, collectionIds: getRegisteredCollectionNames() })
73
+ });
74
+ if (!res.ok)
75
+ throw new Error(`Firestore exportDocuments failed (${res.status}): ${await res.text()}`);
76
+ const data = (await res.json());
77
+ return data.name ?? outputUriPrefix;
78
+ };
79
+ eraseUser = async (raw, step = this.#core.step) => {
80
+ const { userId, backupBeforeErase } = eraseUserInput.parse(raw);
81
+ const backupOperation = backupBeforeErase
82
+ ? await step('backup', () => this.#triggerFirestoreBackup(userId))
83
+ : undefined;
84
+ const { erasedFiles, erasedChats, erasedCollections } = await this.#core.internals.registry.cascadeEraseUserCollections(userId, step);
85
+ const erasedUser = await step('erase-user', async () => {
86
+ this.#session.evictUserTokens(userId);
87
+ await Promise.all([
88
+ this.#session.recordRevocation(userId, this.#core.env.isDev),
89
+ this.#session.getAuth().deleteUser(userId).catch(() => { })
90
+ ]);
91
+ return true;
92
+ });
93
+ return eraseUserOutput.parse({
94
+ userId,
95
+ ...(backupOperation ? { backupOperation } : {}),
96
+ erasedFiles,
97
+ erasedChats,
98
+ ...(Object.keys(erasedCollections).length ? { erasedCollections } : {}),
99
+ erasedUser
100
+ });
101
+ };
102
+ get internals() {
103
+ const getAuthWarm = this.#session.getAuthWarm;
104
+ return {
105
+ verifyToken: this.#session.verifyToken,
106
+ hashToken,
107
+ resolveUserRole,
108
+ tokenCache,
109
+ setTokenCache: this.#session.setTokenCache,
110
+ recordRevocation: this.#session.recordRevocation,
111
+ syncRevocations: this.#session.syncRevocations,
112
+ getLastDevEmail: this.#recovery.getLastDevEmail,
113
+ registerTestOidcPublicKey: this.#oidc.registerTestOidcPublicKey,
114
+ get sessionCookie() {
115
+ return CORE_CONFIG.auth.sessionCookie;
116
+ },
117
+ get authWarm() {
118
+ return getAuthWarm();
119
+ },
120
+ mintCustomToken: this.#session.mintCustomToken,
121
+ createSession: this.#session.createSession,
122
+ signUpEmail: this.#oidc.signUpEmail,
123
+ signInEmail: this.#oidc.signInEmail,
124
+ revokeSession: this.#session.revokeSession,
125
+ setSessionCookie: this.#session.setSessionCookie
126
+ };
127
+ }
128
+ }
129
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/auth/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import { type Auth } from 'firebase-admin/auth';
2
+ import type { Context } from 'hono';
3
+ import { type AppEnv, type DbRole } from '../config';
4
+ import type { EntryId } from '../db';
5
+ import type { Core } from '../index';
6
+ import type { AuthUser, CachedTokenEntry, UserAuthMetaRecord } from './schema';
7
+ export declare const tokenCache: Map<string, CachedTokenEntry>;
8
+ export declare class AuthSessionEngine {
9
+ #private;
10
+ constructor(coreClient: Core);
11
+ getAuth: () => Auth;
12
+ getAuthWarm: () => Promise<unknown>;
13
+ resolveDefaultIsDev: (isDev?: boolean) => boolean;
14
+ setTokenCache: (token: string, uid: EntryId, role?: DbRole, exp?: number, strictVerified?: boolean, emailVerified?: boolean) => void;
15
+ evictUserTokens: (uid: EntryId, revokedAt?: number) => void;
16
+ recordRevocation: (uid: EntryId, isDev?: boolean) => Promise<number>;
17
+ clearUserRevocation: (uid: EntryId, isDev?: boolean) => Promise<void>;
18
+ syncRevocations: (isDev?: boolean, force?: boolean) => Promise<Record<string, number>>;
19
+ verifyToken: (token: string, isCookie: boolean, checkRevoked: boolean, isDev?: boolean) => Promise<{
20
+ uid: EntryId;
21
+ role: DbRole;
22
+ emailVerified: boolean;
23
+ }>;
24
+ getUserAuthMeta: (uid: EntryId, isDev?: boolean) => Promise<UserAuthMetaRecord | undefined>;
25
+ upsertUserAuthMeta: (uid: EntryId, patch: Partial<UserAuthMetaRecord>, isDev?: boolean) => Promise<UserAuthMetaRecord>;
26
+ setSessionCookie: (c: Context<AppEnv>, sessionCookie: string) => void;
27
+ mintCustomToken: (uid?: string) => Promise<{
28
+ uid: string;
29
+ customToken: string;
30
+ }>;
31
+ createSession: (idToken: string, profile?: {
32
+ email?: string;
33
+ name?: string;
34
+ avatarUrl?: string;
35
+ emailVerified?: boolean;
36
+ }) => Promise<{
37
+ user: AuthUser;
38
+ sessionCookie: string;
39
+ }>;
40
+ mintSessionForUid: (uid: EntryId, profile?: {
41
+ email?: string;
42
+ name?: string;
43
+ avatarUrl?: string;
44
+ emailVerified?: boolean;
45
+ }) => Promise<{
46
+ user: AuthUser;
47
+ sessionCookie: string;
48
+ }>;
49
+ revokeSession: (sessionCookie: string, deleteUser?: boolean) => Promise<void>;
50
+ }
51
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/auth/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAExD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACnC,OAAO,EAAe,KAAK,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,WAAW,CAAA;AACjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AACpC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AACpC,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAS9E,eAAO,MAAM,UAAU,+BAAsC,CAAA;AAc7D,qBAAa,iBAAiB;;IAG5B,YAAY,UAAU,EAAE,IAAI,EAE3B;IAED,OAAO,QAAO,IAAI,CAGjB;IAED,WAAW,QAAO,OAAO,CAAC,OAAO,CAAC,CAcjC;IAED,mBAAmB,WAAY,OAAO,KAAG,OAAO,CAAiC;IAuBjF,aAAa,UACJ,MAAM,OACR,OAAO,SACN,MAAM,sEAIX,IAAI,CAcN;IAED,eAAe,QAAS,OAAO,cAAc,MAAM,KAAG,IAAI,CAMzD;IAED,gBAAgB,QAAe,OAAO,UAAU,OAAO,KAAG,OAAO,CAAC,MAAM,CAAC,CA8BxE;IAED,mBAAmB,QAAe,OAAO,UAAU,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC,CAkBzE;IAED,eAAe,WAAkB,OAAO,sBAAkB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAyBxF;IAED,WAAW,UACF,MAAM,YACH,OAAO,gBACH,OAAO,UACb,OAAO,KACd,OAAO,CAAC;QAAE,GAAG,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,OAAO,CAAA;KAAE,CAAC,CAqCjE;IAED,eAAe,QAAe,OAAO,UAAU,OAAO,KAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CA+B/F;IAED,kBAAkB,QACX,OAAO,SACL,OAAO,CAAC,kBAAkB,CAAC,UAC1B,OAAO,KACd,OAAO,CAAC,kBAAkB,CAAC,CAkD7B;IAED,gBAAgB,MAAO,OAAO,CAAC,MAAM,CAAC,iBAAiB,MAAM,KAAG,IAAI,CAQnE;IAED,eAAe,oBAEZ,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAG9C;IAEF,aAAa,YACF,MAAM,YACL;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,KACvF,OAAO,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC,CAwCpD;IAED,iBAAiB,QACV,OAAO,YACF;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,KACvF,OAAO,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC,CAYpD;IAED,aAAa,kBAAyB,MAAM,2BAAuB,OAAO,CAAC,IAAI,CAAC,CAU/E;CACF"}
@@ -0,0 +1,344 @@
1
+ import { getAuth } from 'firebase-admin/auth';
2
+ import { setCookie } from 'hono/cookie';
3
+ import { CORE_CONFIG } from '../config';
4
+ import { fetchIdentityToolkit, normalizeDate, parseLinkedProviders, resolveTokenRole } from './utils';
5
+ let authWarmPromise;
6
+ const REVOCATION_SYNC_TTL_MS = 3_000;
7
+ const AUTH_REVOCATIONS_DOC_PATH = '_system/auth_revocations';
8
+ export const tokenCache = new Map();
9
+ const revocationWatermarks = [
10
+ { lastSyncedAt: 0, revokedUsers: {} },
11
+ { lastSyncedAt: 0, revokedUsers: {} }
12
+ ];
13
+ let bgSyncTimer = null;
14
+ export class AuthSessionEngine {
15
+ #core;
16
+ constructor(coreClient) {
17
+ this.#core = coreClient;
18
+ }
19
+ getAuth = () => {
20
+ this.#core.internals.registry.ensureFirebaseApp();
21
+ return getAuth();
22
+ };
23
+ getAuthWarm = () => {
24
+ if (!authWarmPromise) {
25
+ const auth = this.getAuth();
26
+ const rawAuth = auth;
27
+ authWarmPromise = Promise.all([
28
+ rawAuth.idTokenVerifier?.signatureVerifier?.keyFetcher?.fetchPublicKeys?.(),
29
+ rawAuth.sessionCookieVerifier?.signatureVerifier?.keyFetcher?.fetchPublicKeys?.(),
30
+ auth.getUser(CORE_CONFIG.auth.adminUserId).catch(() => { })
31
+ ]).catch(() => { });
32
+ }
33
+ return authWarmPromise;
34
+ };
35
+ resolveDefaultIsDev = (isDev) => isDev ?? this.#core.env.isDev;
36
+ #ensureBackgroundRevocationSync = () => {
37
+ if (bgSyncTimer)
38
+ return;
39
+ bgSyncTimer = setInterval(() => {
40
+ if (tokenCache.size === 0) {
41
+ if (bgSyncTimer) {
42
+ clearInterval(bgSyncTimer);
43
+ bgSyncTimer = null;
44
+ }
45
+ return;
46
+ }
47
+ const defaultIsDev = this.#core.env.isDev;
48
+ for (const isDevSlot of [false, true]) {
49
+ const idx = isDevSlot ? 1 : 0;
50
+ if (isDevSlot === defaultIsDev || revocationWatermarks[idx].lastSyncedAt > 0) {
51
+ void this.syncRevocations(isDevSlot, true);
52
+ }
53
+ }
54
+ }, 2_000);
55
+ bgSyncTimer.unref?.();
56
+ };
57
+ setTokenCache = (token, uid, role = uid === CORE_CONFIG.auth.adminUserId ? 'admin' : 'user', exp = Date.now() + CORE_CONFIG.auth.tokenCacheTtlMs, strictVerified = false, emailVerified = false) => {
58
+ const existing = tokenCache.get(token);
59
+ if (!existing && tokenCache.size >= CORE_CONFIG.auth.tokenCacheMaxSize) {
60
+ tokenCache.delete(tokenCache.keys().next().value);
61
+ }
62
+ tokenCache.set(token, {
63
+ uid,
64
+ role,
65
+ exp,
66
+ cachedAt: Date.now(),
67
+ strictVerified: Boolean(strictVerified || existing?.strictVerified),
68
+ emailVerified: Boolean(emailVerified || existing?.emailVerified)
69
+ });
70
+ this.#ensureBackgroundRevocationSync();
71
+ };
72
+ evictUserTokens = (uid, revokedAt) => {
73
+ for (const [k, v] of tokenCache) {
74
+ if (v.uid === uid && (revokedAt === undefined || v.cachedAt <= revokedAt)) {
75
+ tokenCache.delete(k);
76
+ }
77
+ }
78
+ };
79
+ recordRevocation = async (uid, isDev) => {
80
+ let revokedAt = Date.now();
81
+ this.evictUserTokens(uid);
82
+ const ttlMs = CORE_CONFIG.auth.tokenCacheTtlMs;
83
+ const targetIsDev = this.resolveDefaultIsDev(isDev);
84
+ const localState = revocationWatermarks[targetIsDev ? 1 : 0];
85
+ localState.revokedUsers[uid] = revokedAt;
86
+ localState.lastSyncedAt = revokedAt;
87
+ const db = this.#core.db.firestore(targetIsDev);
88
+ const docRef = db.doc(AUTH_REVOCATIONS_DOC_PATH);
89
+ try {
90
+ await db.runTransaction(async (tx) => {
91
+ const snap = await tx.get(docRef);
92
+ const now = Date.now();
93
+ revokedAt = now;
94
+ const data = snap.data();
95
+ const existing = data?.revokedUsers ?? {};
96
+ const pruned = {};
97
+ const cutoff = now - ttlMs;
98
+ for (const [k, ts] of Object.entries(existing)) {
99
+ if (typeof ts === 'number' && ts > cutoff)
100
+ pruned[k] = ts;
101
+ }
102
+ pruned[uid] = now;
103
+ tx.set(docRef, { revokedUsers: pruned, updatedAt: now });
104
+ });
105
+ localState.revokedUsers[uid] = revokedAt;
106
+ localState.lastSyncedAt = revokedAt;
107
+ }
108
+ catch { }
109
+ return revokedAt;
110
+ };
111
+ clearUserRevocation = async (uid, isDev) => {
112
+ const targetIsDev = this.resolveDefaultIsDev(isDev);
113
+ const localState = revocationWatermarks[targetIsDev ? 1 : 0];
114
+ delete localState.revokedUsers[uid];
115
+ localState.lastSyncedAt = Date.now();
116
+ const db = this.#core.db.firestore(targetIsDev);
117
+ const docRef = db.doc(AUTH_REVOCATIONS_DOC_PATH);
118
+ try {
119
+ await db.runTransaction(async (tx) => {
120
+ const snap = await tx.get(docRef);
121
+ const data = snap.data();
122
+ if (!data?.revokedUsers || !(uid in data.revokedUsers))
123
+ return;
124
+ const next = { ...data.revokedUsers };
125
+ delete next[uid];
126
+ tx.set(docRef, { revokedUsers: next, updatedAt: Date.now() });
127
+ });
128
+ }
129
+ catch { }
130
+ };
131
+ syncRevocations = async (isDev, force = false) => {
132
+ const targetIsDev = this.resolveDefaultIsDev(isDev);
133
+ const state = revocationWatermarks[targetIsDev ? 1 : 0];
134
+ const now = Date.now();
135
+ if (!force && state.lastSyncedAt > 0 && now - state.lastSyncedAt < REVOCATION_SYNC_TTL_MS) {
136
+ return state.revokedUsers;
137
+ }
138
+ return this.#core.internals.resilience.singleflight(`auth:revocations:${targetIsDev ? 'dev' : 'prod'}`, async () => {
139
+ try {
140
+ const snap = await this.#core.db.firestore(targetIsDev).doc(AUTH_REVOCATIONS_DOC_PATH).get();
141
+ const remote = snap.data()?.revokedUsers ?? {};
142
+ state.revokedUsers = remote;
143
+ state.lastSyncedAt = Date.now();
144
+ for (const [uid, revokedAt] of Object.entries(remote)) {
145
+ if (typeof revokedAt === 'number')
146
+ this.evictUserTokens(uid, revokedAt);
147
+ }
148
+ }
149
+ catch {
150
+ state.lastSyncedAt = Date.now();
151
+ }
152
+ return state.revokedUsers;
153
+ }, { scope: 'global' });
154
+ };
155
+ verifyToken = async (token, isCookie, checkRevoked, isDev) => {
156
+ const targetIsDev = this.resolveDefaultIsDev(isDev);
157
+ const state = revocationWatermarks[targetIsDev ? 1 : 0];
158
+ let hit = tokenCache.get(token);
159
+ if (hit && hit.exp > Date.now()) {
160
+ if (Date.now() - state.lastSyncedAt >= REVOCATION_SYNC_TTL_MS) {
161
+ void this.syncRevocations(targetIsDev);
162
+ }
163
+ const revokedAt = state.revokedUsers[hit.uid];
164
+ if (typeof revokedAt === 'number' && revokedAt >= hit.cachedAt) {
165
+ this.evictUserTokens(hit.uid, revokedAt);
166
+ hit = undefined;
167
+ }
168
+ }
169
+ if (hit && hit.exp > Date.now() && (!checkRevoked || hit.strictVerified)) {
170
+ return { uid: hit.uid, role: hit.role, emailVerified: Boolean(hit.emailVerified) };
171
+ }
172
+ return this.#core.internals.resilience.singleflight(`auth:${isCookie ? 'c' : 'b'}:${checkRevoked ? '1' : '0'}:${token}`, async () => {
173
+ const auth = this.getAuth();
174
+ const d = isCookie
175
+ ? await auth.verifySessionCookie(token, checkRevoked)
176
+ : await auth.verifyIdToken(token, checkRevoked);
177
+ const role = resolveTokenRole(d, d.uid);
178
+ const emailVerified = Boolean(d.email_verified);
179
+ this.setTokenCache(token, d.uid, role, Math.min(d.exp * 1000, Date.now() + CORE_CONFIG.auth.tokenCacheTtlMs), checkRevoked, emailVerified);
180
+ return { uid: d.uid, role, emailVerified };
181
+ });
182
+ };
183
+ getUserAuthMeta = async (uid, isDev) => {
184
+ if (!uid)
185
+ return undefined;
186
+ try {
187
+ const snap = await this.#core.db
188
+ .firestore(this.resolveDefaultIsDev(isDev))
189
+ .collection('user_auth_meta')
190
+ .doc(uid)
191
+ .get();
192
+ if (!snap.exists)
193
+ return undefined;
194
+ const raw = snap.data();
195
+ if (!raw || raw.deleted === true)
196
+ return undefined;
197
+ const linkedProviders = parseLinkedProviders(raw.linkedProviders);
198
+ return {
199
+ ...(typeof raw.email === 'string' || raw.email === null ? { email: raw.email } : {}),
200
+ ...(typeof raw.emailVerified === 'boolean' ? { emailVerified: raw.emailVerified } : {}),
201
+ ...(typeof raw.name === 'string' || raw.name === null ? { name: raw.name } : {}),
202
+ ...(typeof raw.avatarUrl === 'string' || raw.avatarUrl === null ? { avatarUrl: raw.avatarUrl } : {}),
203
+ ...(typeof raw.recoveryEmail === 'string' || raw.recoveryEmail === null
204
+ ? { recoveryEmail: raw.recoveryEmail }
205
+ : {}),
206
+ ...(typeof raw.recoveryEmailVerified === 'boolean'
207
+ ? { recoveryEmailVerified: raw.recoveryEmailVerified }
208
+ : {}),
209
+ ...(linkedProviders.length > 0 ? { linkedProviders } : {}),
210
+ ...(Array.isArray(raw.providerKeys) ? { providerKeys: raw.providerKeys.map(String) } : {}),
211
+ createdAt: normalizeDate(raw.createdAt),
212
+ updatedAt: normalizeDate(raw.updatedAt)
213
+ };
214
+ }
215
+ catch {
216
+ return undefined;
217
+ }
218
+ };
219
+ upsertUserAuthMeta = async (uid, patch, isDev) => {
220
+ const db = this.#core.db.firestore(this.resolveDefaultIsDev(isDev));
221
+ const docRef = db.collection('user_auth_meta').doc(uid);
222
+ const now = new Date();
223
+ let merged = { ...patch, updatedAt: now };
224
+ await db.runTransaction(async (tx) => {
225
+ const snap = await tx.get(docRef);
226
+ const existing = snap.exists ? snap.data() : undefined;
227
+ const createdAt = existing?.createdAt ? normalizeDate(existing.createdAt, now) : now;
228
+ const existingProviders = parseLinkedProviders(existing?.linkedProviders, now);
229
+ const nextProviders = patch.linkedProviders ?? existingProviders;
230
+ const providerKeys = Array.from(new Set([
231
+ ...(Array.isArray(existing?.providerKeys) ? existing.providerKeys.map(String) : []),
232
+ ...(patch.providerKeys ?? []),
233
+ ...nextProviders.map((p) => `${p.provider}:${p.providerUserId}`)
234
+ ]));
235
+ const nextDoc = {
236
+ id: uid,
237
+ deleted: false,
238
+ email: patch.email !== undefined ? patch.email : (existing?.email ?? null),
239
+ emailVerified: patch.emailVerified !== undefined ? patch.emailVerified : Boolean(existing?.emailVerified),
240
+ name: patch.name !== undefined ? patch.name : (existing?.name ?? null),
241
+ avatarUrl: patch.avatarUrl !== undefined ? patch.avatarUrl : (existing?.avatarUrl ?? null),
242
+ recoveryEmail: patch.recoveryEmail !== undefined ? patch.recoveryEmail : (existing?.recoveryEmail ?? null),
243
+ recoveryEmailVerified: patch.recoveryEmailVerified !== undefined
244
+ ? patch.recoveryEmailVerified
245
+ : Boolean(existing?.recoveryEmailVerified),
246
+ linkedProviders: nextProviders,
247
+ providerKeys,
248
+ createdAt,
249
+ updatedAt: now
250
+ };
251
+ tx.set(docRef, nextDoc, { merge: true });
252
+ merged = {
253
+ email: nextDoc.email,
254
+ emailVerified: nextDoc.emailVerified,
255
+ name: nextDoc.name,
256
+ avatarUrl: nextDoc.avatarUrl,
257
+ recoveryEmail: nextDoc.recoveryEmail,
258
+ recoveryEmailVerified: nextDoc.recoveryEmailVerified,
259
+ linkedProviders: nextProviders,
260
+ providerKeys,
261
+ createdAt,
262
+ updatedAt: now
263
+ };
264
+ });
265
+ return merged;
266
+ };
267
+ setSessionCookie = (c, sessionCookie) => {
268
+ setCookie(c, CORE_CONFIG.auth.sessionCookie, sessionCookie, {
269
+ httpOnly: true,
270
+ secure: c.req.header('x-forwarded-proto') === 'https' || c.req.url.startsWith('https://'),
271
+ path: '/',
272
+ sameSite: 'Lax',
273
+ maxAge: Math.floor(CORE_CONFIG.auth.sessionExpiresInMs / 1000)
274
+ });
275
+ };
276
+ mintCustomToken = async (uid = `anon_${crypto.randomUUID().replace(/-/g, '').slice(0, 16)}`) => ({
277
+ uid,
278
+ customToken: await this.getAuth().createCustomToken(uid)
279
+ });
280
+ createSession = async (idToken, profile) => {
281
+ const auth = this.getAuth();
282
+ const cacheTtl = CORE_CONFIG.auth.tokenCacheTtlMs;
283
+ const sessionExpiresIn = CORE_CONFIG.auth.sessionExpiresInMs;
284
+ const now = new Date();
285
+ const [{ decoded, meta }, sessionCookie] = await Promise.all([
286
+ auth.verifyIdToken(idToken, true).then(async (d) => {
287
+ const role = resolveTokenRole(d, d.uid);
288
+ const emailVerified = Boolean(d.email_verified || profile?.emailVerified);
289
+ this.setTokenCache(idToken, d.uid, role, Math.min(d.exp * 1000, Date.now() + cacheTtl), true, emailVerified);
290
+ const updates = {};
291
+ if (profile?.name && d.name !== profile.name)
292
+ updates.displayName = profile.name;
293
+ if (profile?.avatarUrl && d.picture !== profile.avatarUrl)
294
+ updates.photoURL = profile.avatarUrl;
295
+ const [m] = await Promise.all([
296
+ this.getUserAuthMeta(d.uid, this.#core.env.isDev),
297
+ Object.keys(updates).length > 0 ? auth.updateUser(d.uid, updates).catch(() => { }) : Promise.resolve()
298
+ ]);
299
+ return { decoded: d, meta: m };
300
+ }),
301
+ auth.createSessionCookie(idToken, { expiresIn: sessionExpiresIn })
302
+ ]);
303
+ const role = resolveTokenRole(decoded, decoded.uid);
304
+ const emailVerified = Boolean(decoded.email_verified || profile?.emailVerified || meta?.emailVerified);
305
+ const avatarUrl = profile?.avatarUrl ?? decoded.picture ?? meta?.avatarUrl;
306
+ const user = {
307
+ id: decoded.uid,
308
+ email: decoded.email ?? profile?.email ?? meta?.email ?? null,
309
+ emailVerified,
310
+ name: profile?.name ?? decoded.name ?? meta?.name ?? null,
311
+ ...(avatarUrl !== undefined ? { avatarUrl } : {}),
312
+ ...(meta?.recoveryEmail !== undefined ? { recoveryEmail: meta.recoveryEmail } : {}),
313
+ ...(meta?.recoveryEmailVerified !== undefined ? { recoveryEmailVerified: meta.recoveryEmailVerified } : {}),
314
+ ...(meta?.linkedProviders?.length ? { linkedProviders: meta.linkedProviders } : {}),
315
+ ...(decoded.role || decoded.admin ? { customClaims: { role } } : {}),
316
+ deleted: false,
317
+ createdAt: meta?.createdAt ?? now,
318
+ updatedAt: now
319
+ };
320
+ this.setTokenCache(sessionCookie, user.id, role, Date.now() + cacheTtl, true, emailVerified);
321
+ return { user, sessionCookie };
322
+ };
323
+ mintSessionForUid = async (uid, profile) => {
324
+ const customToken = await this.getAuth().createCustomToken(uid);
325
+ const { ok, data } = await fetchIdentityToolkit('accounts:signInWithCustomToken', this.#core.env.WEB_API_KEY, { token: customToken, returnSecureToken: true });
326
+ if (!ok || !data.idToken) {
327
+ const msg = data.error?.message ?? 'CUSTOM_TOKEN_EXCHANGE_FAILED';
328
+ return this.#core.errors.httpError(401, msg, msg);
329
+ }
330
+ return this.createSession(data.idToken, profile);
331
+ };
332
+ revokeSession = async (sessionCookie, deleteUser = false) => {
333
+ const auth = this.getAuth();
334
+ const uid = tokenCache.get(sessionCookie)?.uid ?? (await auth.verifySessionCookie(sessionCookie)).sub;
335
+ this.evictUserTokens(uid);
336
+ tokenCache.delete(sessionCookie);
337
+ await Promise.all([
338
+ this.recordRevocation(uid, this.#core.env.isDev),
339
+ auth.revokeRefreshTokens(uid).catch(() => { }),
340
+ ...(deleteUser ? [auth.updateUser(uid, { disabled: true }).catch(() => { })] : [])
341
+ ]);
342
+ };
343
+ }
344
+ //# sourceMappingURL=session.js.map