@aurabase/aurabase-js 0.3.0 → 0.3.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.
Files changed (258) hide show
  1. package/package.json +4 -4
  2. package/packages/ai/node_modules/.bin/esbuild +0 -19
  3. package/packages/ai/node_modules/.bin/tsc +0 -22
  4. package/packages/ai/node_modules/.bin/tsserver +0 -22
  5. package/packages/ai/node_modules/.bin/tsup +0 -22
  6. package/packages/ai/node_modules/.bin/tsup-node +0 -22
  7. package/packages/ai/node_modules/.bin/vite +0 -22
  8. package/packages/ai/node_modules/.bin/vitest +0 -22
  9. package/packages/ai/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  10. package/packages/ai/src/AiService.ts +0 -226
  11. package/packages/ai/src/index.ts +0 -18
  12. package/packages/ai/src/sse.ts +0 -141
  13. package/packages/ai/src/types.ts +0 -30
  14. package/packages/ai/tests/chat-stream.test.ts +0 -151
  15. package/packages/ai/tests/rag-namespaces.test.ts +0 -54
  16. package/packages/ai/tests/sse.test.ts +0 -69
  17. package/packages/ai/tsconfig.json +0 -5
  18. package/packages/ai/tsup.config.ts +0 -11
  19. package/packages/aurabase/node_modules/.bin/esbuild +0 -19
  20. package/packages/aurabase/node_modules/.bin/tsc +0 -22
  21. package/packages/aurabase/node_modules/.bin/tsserver +0 -22
  22. package/packages/aurabase/node_modules/.bin/tsup +0 -22
  23. package/packages/aurabase/node_modules/.bin/tsup-node +0 -22
  24. package/packages/aurabase/node_modules/.bin/vite +0 -22
  25. package/packages/aurabase/node_modules/.bin/vitest +0 -22
  26. package/packages/aurabase/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  27. package/packages/aurabase/src/AuraClient.ts +0 -237
  28. package/packages/aurabase/src/index.ts +0 -152
  29. package/packages/aurabase/src/ssr.ts +0 -156
  30. package/packages/aurabase/tests/ai-streaming-rag-e2e.test.ts +0 -82
  31. package/packages/aurabase/tests/ai.test.ts +0 -111
  32. package/packages/aurabase/tests/auth-admin.test.ts +0 -515
  33. package/packages/aurabase/tests/auth-e2e.test.ts +0 -135
  34. package/packages/aurabase/tests/auth-hardening.test.ts +0 -206
  35. package/packages/aurabase/tests/auth.test.ts +0 -947
  36. package/packages/aurabase/tests/database.test.ts +0 -230
  37. package/packages/aurabase/tests/db-types-e2e.test.ts +0 -217
  38. package/packages/aurabase/tests/dispose.test.ts +0 -23
  39. package/packages/aurabase/tests/foreign-token.e2e.test.ts +0 -129
  40. package/packages/aurabase/tests/functions.test.ts +0 -107
  41. package/packages/aurabase/tests/integration.test.ts +0 -413
  42. package/packages/aurabase/tests/live-production-validation.js +0 -241
  43. package/packages/aurabase/tests/live-sdk-production-validation.js +0 -293
  44. package/packages/aurabase/tests/mocks.ts +0 -139
  45. package/packages/aurabase/tests/notifications.test.ts +0 -314
  46. package/packages/aurabase/tests/observability-backup.test.ts +0 -186
  47. package/packages/aurabase/tests/observability-hook.test.ts +0 -130
  48. package/packages/aurabase/tests/production-robustness.test.ts +0 -268
  49. package/packages/aurabase/tests/public-api-surface.test.ts +0 -53
  50. package/packages/aurabase/tests/query-builder.test.ts +0 -329
  51. package/packages/aurabase/tests/readme-smoke-e2e.test.ts +0 -231
  52. package/packages/aurabase/tests/realtime-filter-e2e.test.ts +0 -344
  53. package/packages/aurabase/tests/refresh-locks.test.ts +0 -210
  54. package/packages/aurabase/tests/retry-option.test.ts +0 -17
  55. package/packages/aurabase/tests/rpc-e2e.test.ts +0 -254
  56. package/packages/aurabase/tests/rs256-local-e2e.test.ts +0 -114
  57. package/packages/aurabase/tests/rt-alias-public-e2e.test.ts +0 -235
  58. package/packages/aurabase/tests/rt-http-broadcast-e2e.test.ts +0 -124
  59. package/packages/aurabase/tests/service-role-guard.test.ts +0 -99
  60. package/packages/aurabase/tests/ssr.test.ts +0 -91
  61. package/packages/aurabase/tests/storage-backend-e2e.test.ts +0 -481
  62. package/packages/aurabase/tests/storage-sdk-parity-e2e.test.ts +0 -104
  63. package/packages/aurabase/tests/storage-transform-e2e.test.ts +0 -684
  64. package/packages/aurabase/tests/storage.test.ts +0 -55
  65. package/packages/aurabase/tests/types/client-generic.test-d.ts +0 -79
  66. package/packages/aurabase/tests/types/docs-snippets.test-d.ts +0 -571
  67. package/packages/aurabase/tests/types/error-code.test-d.ts +0 -53
  68. package/packages/aurabase/tsconfig.json +0 -5
  69. package/packages/aurabase/tsconfig.test-d.json +0 -5
  70. package/packages/aurabase/tsup.config.ts +0 -11
  71. package/packages/aurabase/vitest.config.ts +0 -16
  72. package/packages/auth/node_modules/.bin/esbuild +0 -19
  73. package/packages/auth/node_modules/.bin/tsc +0 -22
  74. package/packages/auth/node_modules/.bin/tsserver +0 -22
  75. package/packages/auth/node_modules/.bin/tsup +0 -22
  76. package/packages/auth/node_modules/.bin/tsup-node +0 -22
  77. package/packages/auth/node_modules/.bin/vite +0 -22
  78. package/packages/auth/node_modules/.bin/vitest +0 -22
  79. package/packages/auth/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  80. package/packages/auth/src/AuthAdminService.ts +0 -149
  81. package/packages/auth/src/AuthService.ts +0 -1166
  82. package/packages/auth/src/SessionManager.ts +0 -92
  83. package/packages/auth/src/index.ts +0 -17
  84. package/packages/auth/src/jwks.ts +0 -337
  85. package/packages/auth/src/pkce.ts +0 -27
  86. package/packages/auth/src/types.ts +0 -89
  87. package/packages/auth/tests/auth-lifecycle.test.ts +0 -149
  88. package/packages/auth/tests/detect-session.test.ts +0 -361
  89. package/packages/auth/tests/getclaims.test.ts +0 -780
  90. package/packages/auth/tests/is-mfa-challenge.test.ts +0 -27
  91. package/packages/auth/tests/password-recovery.test.ts +0 -124
  92. package/packages/auth/tests/pkce.test.ts +0 -192
  93. package/packages/auth/tests/session-manager.test.ts +0 -103
  94. package/packages/auth/tests/set-session.test.ts +0 -139
  95. package/packages/auth/tests/verify-otp.test.ts +0 -153
  96. package/packages/auth/tsconfig.json +0 -5
  97. package/packages/auth/tsup.config.ts +0 -11
  98. package/packages/core/node_modules/.bin/esbuild +0 -22
  99. package/packages/core/node_modules/.bin/tsc +0 -22
  100. package/packages/core/node_modules/.bin/tsserver +0 -22
  101. package/packages/core/node_modules/.bin/tsup +0 -22
  102. package/packages/core/node_modules/.bin/tsup-node +0 -22
  103. package/packages/core/node_modules/.bin/vite +0 -22
  104. package/packages/core/node_modules/.bin/vitest +0 -22
  105. package/packages/core/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  106. package/packages/core/src/AuraError.ts +0 -89
  107. package/packages/core/src/BaseService.ts +0 -44
  108. package/packages/core/src/client.ts +0 -34
  109. package/packages/core/src/cookie-utils.ts +0 -42
  110. package/packages/core/src/fetch.ts +0 -435
  111. package/packages/core/src/index.ts +0 -22
  112. package/packages/core/src/retry.ts +0 -63
  113. package/packages/core/src/serialize.ts +0 -6
  114. package/packages/core/src/stores/BaseAuthStore.ts +0 -164
  115. package/packages/core/src/stores/LocalAuthStore.ts +0 -199
  116. package/packages/core/src/types.ts +0 -1042
  117. package/packages/core/tests/auth-store.test.ts +0 -300
  118. package/packages/core/tests/error-code.test.ts +0 -61
  119. package/packages/core/tests/error.test.ts +0 -24
  120. package/packages/core/tests/fetch.test.ts +0 -286
  121. package/packages/core/tests/mocks.ts +0 -139
  122. package/packages/core/tests/observability.test.ts +0 -86
  123. package/packages/core/tests/refresh-hardening.test.ts +0 -164
  124. package/packages/core/tests/refresh-observability.test.ts +0 -111
  125. package/packages/core/tests/retry.test.ts +0 -106
  126. package/packages/core/tests/serialize.test.ts +0 -12
  127. package/packages/core/tests/timeout.test.ts +0 -79
  128. package/packages/core/tsconfig.json +0 -5
  129. package/packages/core/tsup.config.ts +0 -11
  130. package/packages/db/node_modules/.bin/esbuild +0 -19
  131. package/packages/db/node_modules/.bin/tsc +0 -22
  132. package/packages/db/node_modules/.bin/tsserver +0 -22
  133. package/packages/db/node_modules/.bin/tsup +0 -22
  134. package/packages/db/node_modules/.bin/tsup-node +0 -22
  135. package/packages/db/node_modules/.bin/vite +0 -22
  136. package/packages/db/node_modules/.bin/vitest +0 -22
  137. package/packages/db/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  138. package/packages/db/src/DatabaseService.ts +0 -170
  139. package/packages/db/src/QueryBuilder.ts +0 -830
  140. package/packages/db/src/index.ts +0 -2
  141. package/packages/db/src/pgrst-types/common/common.ts +0 -86
  142. package/packages/db/src/pgrst-types/common/rpc.ts +0 -151
  143. package/packages/db/src/pgrst-types/feature-flags.ts +0 -20
  144. package/packages/db/src/pgrst-types/types.ts +0 -134
  145. package/packages/db/src/select-query-parser/parser.ts +0 -479
  146. package/packages/db/src/select-query-parser/result.ts +0 -553
  147. package/packages/db/src/select-query-parser/types.ts +0 -132
  148. package/packages/db/src/select-query-parser/utils.ts +0 -707
  149. package/packages/db/tests/filters.test.ts +0 -81
  150. package/packages/db/tests/mutations-filtered.e2e.test.ts +0 -132
  151. package/packages/db/tests/mutations-filtered.test.ts +0 -188
  152. package/packages/db/tests/order.test.ts +0 -45
  153. package/packages/db/tests/rpc.test.ts +0 -41
  154. package/packages/db/tests/scale/build-large-schema.ts +0 -94
  155. package/packages/db/tests/scale/scale-compile.test.ts +0 -167
  156. package/packages/db/tests/schema.test.ts +0 -77
  157. package/packages/db/tests/single-accept.e2e.test.ts +0 -123
  158. package/packages/db/tests/single.test.ts +0 -211
  159. package/packages/db/tests/types/filters.test-d.ts +0 -52
  160. package/packages/db/tests/types/fixtures.ts +0 -40
  161. package/packages/db/tests/types/from-views.test-d.ts +0 -18
  162. package/packages/db/tests/types/mutations.test-d.ts +0 -23
  163. package/packages/db/tests/types/rpc.test-d.ts +0 -60
  164. package/packages/db/tests/types/schema-shape.test-d.ts +0 -8
  165. package/packages/db/tests/types/select-inference.test-d.ts +0 -38
  166. package/packages/db/tests/vendored/fixtures.ts +0 -83
  167. package/packages/db/tests/vendored/get-result.test-d.ts +0 -75
  168. package/packages/db/tsconfig.json +0 -5
  169. package/packages/db/tsconfig.test-d.json +0 -5
  170. package/packages/db/tsup.config.ts +0 -11
  171. package/packages/db/vitest.config.ts +0 -8
  172. package/packages/functions/node_modules/.bin/esbuild +0 -19
  173. package/packages/functions/node_modules/.bin/tsc +0 -22
  174. package/packages/functions/node_modules/.bin/tsserver +0 -22
  175. package/packages/functions/node_modules/.bin/tsup +0 -22
  176. package/packages/functions/node_modules/.bin/tsup-node +0 -22
  177. package/packages/functions/node_modules/.bin/vite +0 -22
  178. package/packages/functions/node_modules/.bin/vitest +0 -22
  179. package/packages/functions/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  180. package/packages/functions/src/FunctionsService.ts +0 -188
  181. package/packages/functions/src/errors.ts +0 -70
  182. package/packages/functions/src/index.ts +0 -6
  183. package/packages/functions/tests/invoke.test.ts +0 -97
  184. package/packages/functions/tests/response-type-errors.test.ts +0 -135
  185. package/packages/functions/tsconfig.json +0 -5
  186. package/packages/functions/tsup.config.ts +0 -11
  187. package/packages/gen/node_modules/.bin/esbuild +0 -19
  188. package/packages/gen/node_modules/.bin/tsc +0 -22
  189. package/packages/gen/node_modules/.bin/tsserver +0 -22
  190. package/packages/gen/node_modules/.bin/tsup +0 -22
  191. package/packages/gen/node_modules/.bin/tsup-node +0 -22
  192. package/packages/gen/node_modules/.bin/vite +0 -22
  193. package/packages/gen/node_modules/.bin/vitest +0 -22
  194. package/packages/gen/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  195. package/packages/gen/src/cli.ts +0 -67
  196. package/packages/gen/src/generate.ts +0 -0
  197. package/packages/gen/src/index.ts +0 -2
  198. package/packages/gen/tests/compile.test.ts +0 -213
  199. package/packages/gen/tests/e2e.test.ts +0 -130
  200. package/packages/gen/tests/generate.test.ts +0 -396
  201. package/packages/gen/tsconfig.json +0 -5
  202. package/packages/gen/tsup.config.ts +0 -11
  203. package/packages/notifications/node_modules/.bin/esbuild +0 -19
  204. package/packages/notifications/node_modules/.bin/tsc +0 -22
  205. package/packages/notifications/node_modules/.bin/tsserver +0 -22
  206. package/packages/notifications/node_modules/.bin/tsup +0 -22
  207. package/packages/notifications/node_modules/.bin/tsup-node +0 -22
  208. package/packages/notifications/node_modules/.bin/vite +0 -22
  209. package/packages/notifications/node_modules/.bin/vitest +0 -22
  210. package/packages/notifications/src/NotificationsService.ts +0 -230
  211. package/packages/notifications/src/index.ts +0 -19
  212. package/packages/notifications/tsconfig.json +0 -5
  213. package/packages/notifications/tsup.config.ts +0 -11
  214. package/packages/realtime/node_modules/.bin/esbuild +0 -19
  215. package/packages/realtime/node_modules/.bin/tsc +0 -22
  216. package/packages/realtime/node_modules/.bin/tsserver +0 -22
  217. package/packages/realtime/node_modules/.bin/tsup +0 -22
  218. package/packages/realtime/node_modules/.bin/tsup-node +0 -22
  219. package/packages/realtime/node_modules/.bin/vite +0 -22
  220. package/packages/realtime/node_modules/.bin/vitest +0 -22
  221. package/packages/realtime/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  222. package/packages/realtime/src/AuraChannel.ts +0 -485
  223. package/packages/realtime/src/HeartbeatManager.ts +0 -73
  224. package/packages/realtime/src/RealtimeService.ts +0 -505
  225. package/packages/realtime/src/columnFilter.ts +0 -301
  226. package/packages/realtime/src/index.ts +0 -4
  227. package/packages/realtime/tests/ack-routing.test.ts +0 -81
  228. package/packages/realtime/tests/column-filter.test.ts +0 -144
  229. package/packages/realtime/tests/dispatch.test.ts +0 -191
  230. package/packages/realtime/tests/heartbeat.test.ts +0 -67
  231. package/packages/realtime/tests/http-broadcast.test.ts +0 -68
  232. package/packages/realtime/tests/realtime-token.test.ts +0 -43
  233. package/packages/realtime/tests/reconnect-race.test.ts +0 -149
  234. package/packages/realtime/tests/ref-id.test.ts +0 -34
  235. package/packages/realtime/tests/set-auth.test.ts +0 -70
  236. package/packages/realtime/tsconfig.json +0 -5
  237. package/packages/realtime/tsup.config.ts +0 -11
  238. package/packages/storage/node_modules/.bin/esbuild +0 -19
  239. package/packages/storage/node_modules/.bin/tsc +0 -22
  240. package/packages/storage/node_modules/.bin/tsserver +0 -22
  241. package/packages/storage/node_modules/.bin/tsup +0 -22
  242. package/packages/storage/node_modules/.bin/tsup-node +0 -22
  243. package/packages/storage/node_modules/.bin/vite +0 -22
  244. package/packages/storage/node_modules/.bin/vitest +0 -22
  245. package/packages/storage/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  246. package/packages/storage/src/DownloadBuilder.ts +0 -60
  247. package/packages/storage/src/StorageService.ts +0 -323
  248. package/packages/storage/src/index.ts +0 -2
  249. package/packages/storage/src/path.ts +0 -35
  250. package/packages/storage/src/transform.ts +0 -15
  251. package/packages/storage/tests/download.test.ts +0 -64
  252. package/packages/storage/tests/parity.test.ts +0 -154
  253. package/packages/storage/tests/path.test.ts +0 -87
  254. package/packages/storage/tests/transform.test.ts +0 -79
  255. package/packages/storage/tsconfig.json +0 -5
  256. package/packages/storage/tsup.config.ts +0 -11
  257. package/pnpm-workspace.yaml +0 -24
  258. package/tsconfig.base.json +0 -15
@@ -1,92 +0,0 @@
1
- export interface SessionManagerOptions {
2
- channelName: string
3
- enabled: boolean
4
- onTick: () => void
5
- isRefreshDue: () => boolean
6
- onRemoteMessage: (data: unknown) => void
7
- tickMs?: number
8
- }
9
-
10
- /**
11
- * Primitive de cycle de vie de session (timers + BroadcastChannel + visibilité).
12
- * Aucune logique métier auth : `AuthService` fournit les callbacks et pilote `setActive`.
13
- * Sûr en Node/SSR/RN — tous les globals sont gardés (`typeof … !== 'undefined'`).
14
- */
15
- export class SessionManager {
16
- private readonly opts: SessionManagerOptions & { tickMs: number }
17
- private _interval: ReturnType<typeof setInterval> | null = null
18
- private _channel: BroadcastChannel | null = null
19
- private _active = false
20
- private _visHandler: (() => void) | null = null
21
-
22
- constructor(opts: SessionManagerOptions) {
23
- this.opts = { tickMs: 30_000, ...opts }
24
- }
25
-
26
- get isActive(): boolean {
27
- return this._active
28
- }
29
-
30
- start(): void {
31
- if (!this.opts.enabled) return
32
- if (typeof BroadcastChannel !== 'undefined' && !this._channel) {
33
- this._channel = new BroadcastChannel(this.opts.channelName)
34
- this._channel.onmessage = (e: MessageEvent) => this.opts.onRemoteMessage(e.data)
35
- }
36
- if (typeof document !== 'undefined' && !this._visHandler) {
37
- this._visHandler = () => {
38
- if (document.hidden) {
39
- this._stopInterval()
40
- } else if (this._active) {
41
- this._startInterval()
42
- if (this.opts.isRefreshDue()) this.opts.onTick()
43
- }
44
- }
45
- document.addEventListener('visibilitychange', this._visHandler)
46
- }
47
- }
48
-
49
- setActive(active: boolean): void {
50
- this._active = active
51
- if (!this.opts.enabled) return
52
- const hidden = typeof document !== 'undefined' && document.hidden
53
- if (active && !hidden) this._startInterval()
54
- else this._stopInterval()
55
- }
56
-
57
- broadcast(data: unknown): void {
58
- this._channel?.postMessage(data)
59
- }
60
-
61
- stop(): void {
62
- this._stopInterval()
63
- this._active = false
64
- if (this._channel) {
65
- try {
66
- this._channel.close()
67
- } catch {
68
- /* ignore */
69
- }
70
- this._channel = null
71
- }
72
- if (this._visHandler && typeof document !== 'undefined') {
73
- document.removeEventListener('visibilitychange', this._visHandler)
74
- this._visHandler = null
75
- }
76
- }
77
-
78
- private _startInterval(): void {
79
- if (this._interval) return
80
- this._interval = setInterval(() => {
81
- if (this.opts.isRefreshDue()) this.opts.onTick()
82
- }, this.opts.tickMs)
83
- ;(this._interval as { unref?: () => void }).unref?.()
84
- }
85
-
86
- private _stopInterval(): void {
87
- if (this._interval) {
88
- clearInterval(this._interval)
89
- this._interval = null
90
- }
91
- }
92
- }
@@ -1,17 +0,0 @@
1
- export { AuthService, isMfaChallenge } from './AuthService'
2
- export { AuthAdminService } from './AuthAdminService'
3
- export { SessionManager } from './SessionManager'
4
- export type { SessionManagerOptions } from './SessionManager'
5
- export type {
6
- VerifyOtpParams,
7
- EmailOtpType,
8
- MobileOtpType,
9
- VerifySignupOtpParams,
10
- VerifyMagiclinkOtpParams,
11
- VerifyEmailOtpParams,
12
- VerifySmsOtpParams,
13
- VerifyEmailChangeOtpParams,
14
- VerifyRecoveryOtpParams,
15
- VerifyInviteOtpParams,
16
- VerifyPhoneChangeOtpParams,
17
- } from './types'
@@ -1,337 +0,0 @@
1
- /**
2
- * Vérification JWT locale via JWKS (WebCrypto).
3
- *
4
- * Contrainte anti-alg-confusion (CRITIQUE) : la vérification locale n'accepte
5
- * QUE `alg ∈ {RS256, ES256}` (clés asymétriques). Tout autre `alg` (HS256, none,
6
- * ou JWKS sans clé correspondante) ne donne JAMAIS lieu à une vérification locale
7
- * avec un secret : l'appelant retombe sur `getUser()` (validation côté serveur).
8
- */
9
-
10
- interface CachedJwks {
11
- keys: JsonWebKey[]
12
- fetchedAt: number
13
- maxAgeMs: number
14
- }
15
-
16
- /**
17
- * État de robustesse JWKS, aligné sur `jose` `createRemoteJWKSet` :
18
- * - dédup in-flight des fetch concurrents (cf. `fetch.ts:31` single-flight refresh),
19
- * - cooldown sur refetch forcé (kid inconnu), défaut 30s comme jose `cooldownDuration`,
20
- * - negative-cache court sur échec de fetch (anti-tempête pendant une panne),
21
- * - plafond `max-age` (pas de cache figé illimité).
22
- *
23
- * SEC-F4 : l'état est CLIENT-SCOPED via un `WeakMap<scope, JwksState>` (même pattern
24
- * que `fetch.ts` `inflightRefreshes: WeakMap<AuraClientLike, …>`), et non plus des
25
- * `Map` module-level process-global. Chaque `AuraClient` porte donc son propre cache
26
- * (comme une instance `jose.createRemoteJWKSet`, qui embarque son cache par instance) :
27
- * - pas de fuite mémoire SSR multi-tenant (l'état est GC'd avec le client, WeakMap),
28
- * - isolation stricte entre clients (deux clients distincts ne partagent RIEN),
29
- * - le `scope` reste un `object` opaque → `jwks.ts` n'a AUCUNE dépendance vers `core`.
30
- */
31
- const MAX_AGE_CAP_MS = 86_400_000 // 24h — borne haute d'un `Cache-Control: max-age`.
32
- const FORCED_REFETCH_COOLDOWN_MS = 30_000 // aligné jose `cooldownDuration` (30s).
33
- const NEGATIVE_CACHE_TTL_MS = 10_000 // fenêtre anti-retry pendant une panne de fetch.
34
- const DEFAULT_MAX_AGE_MS = 600_000 // défaut quand aucun `Cache-Control: max-age`.
35
-
36
- /** État JWKS d'UN client (caches par baseUrl, cf. supra). */
37
- interface JwksState {
38
- cache: Map<string, CachedJwks>
39
- inflight: Map<string, Promise<JsonWebKey[]>>
40
- lastFailedAt: Map<string, number>
41
- lastForcedFetchAt: Map<string, number>
42
- }
43
-
44
- /**
45
- * État JWKS par client (identité d'objet). `WeakMap` → l'entrée est libérée avec le
46
- * client (pas de fuite mémoire, pas d'invalidation manuelle nécessaire).
47
- */
48
- const clientStates = new WeakMap<object, JwksState>()
49
-
50
- /** Récupère (ou crée paresseusement) l'état JWKS du `scope` (le client). */
51
- function stateFor(scope: object): JwksState {
52
- let s = clientStates.get(scope)
53
- if (!s) {
54
- s = {
55
- cache: new Map(),
56
- inflight: new Map(),
57
- lastFailedAt: new Map(),
58
- lastForcedFetchAt: new Map(),
59
- }
60
- clientStates.set(scope, s)
61
- }
62
- return s
63
- }
64
-
65
- /**
66
- * @deprecated SEC-F4 : le cache JWKS est désormais CLIENT-SCOPED (`WeakMap` par client)
67
- * — plus aucun état process-global à vider. Conservé en NO-OP pour compatibilité des
68
- * appelants existants (chaque test/instance de client a déjà son cache isolé). À
69
- * retirer une fois les appels supprimés.
70
- */
71
- export function __resetJwksCache(): void {
72
- // no-op : plus d'état global (voir stateFor / clientStates).
73
- }
74
-
75
- interface DecodedJwt {
76
- header: { alg?: string; kid?: string; typ?: string; [k: string]: unknown }
77
- payload: { exp?: number; nbf?: number; [k: string]: unknown }
78
- signingInput: string
79
- signature: Uint8Array
80
- }
81
-
82
- function b64urlToBytes(s: string): Uint8Array {
83
- const b64 = s.replace(/-/g, '+').replace(/_/g, '/') + '='.repeat((4 - (s.length % 4)) % 4)
84
- const bin = atob(b64)
85
- const out = new Uint8Array(bin.length)
86
- for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i)
87
- return out
88
- }
89
-
90
- export function decodeJwt(jwt: string): DecodedJwt {
91
- const [h, p, s] = jwt.split('.')
92
- if (!h || !p || !s) throw new Error('malformed jwt')
93
- const dec = new TextDecoder()
94
- return {
95
- header: JSON.parse(dec.decode(b64urlToBytes(h))),
96
- payload: JSON.parse(dec.decode(b64urlToBytes(p))),
97
- signingInput: `${h}.${p}`,
98
- signature: b64urlToBytes(s),
99
- }
100
- }
101
-
102
- function parseMaxAge(cc: string | null): number | null {
103
- const m = cc?.match(/max-age=(\d+)/)
104
- return m ? Number(m[1]) * 1000 : null
105
- }
106
-
107
- /**
108
- * Fetch réseau réel du JWKS, DÉDUPLIQUÉ par baseUrl (single-flight, même idée que
109
- * `refreshOnce` dans `fetch.ts`). En cas d'échec (réseau ou HTTP non-2xx), arme le
110
- * negative-cache et jette `jwks_fetch_failed`. En cas de succès, peuple le cache
111
- * (max-age plafonné) et purge le negative-cache.
112
- */
113
- function fetchJwksDeduped(
114
- state: JwksState,
115
- fetchFn: typeof globalThis.fetch,
116
- baseUrl: string,
117
- ): Promise<JsonWebKey[]> {
118
- const existing = state.inflight.get(baseUrl)
119
- if (existing) return existing
120
- const p = (async () => {
121
- try {
122
- const res = await fetchFn(`${baseUrl}/.well-known/jwks.json`)
123
- if (!res.ok) throw new Error('jwks_fetch_failed')
124
- const body = (await res.json()) as { keys?: JsonWebKey[] }
125
- const parsed = parseMaxAge(res.headers.get('Cache-Control')) ?? DEFAULT_MAX_AGE_MS
126
- const maxAge = Math.min(parsed, MAX_AGE_CAP_MS) // cap : pas de cache figé illimité.
127
- const keys = body.keys ?? []
128
- state.cache.set(baseUrl, { keys, fetchedAt: Date.now(), maxAgeMs: maxAge })
129
- state.lastFailedAt.delete(baseUrl)
130
- return keys
131
- } catch {
132
- state.lastFailedAt.set(baseUrl, Date.now())
133
- throw new Error('jwks_fetch_failed')
134
- }
135
- })().finally(() => state.inflight.delete(baseUrl))
136
- state.inflight.set(baseUrl, p)
137
- return p
138
- }
139
-
140
- /**
141
- * Chargement non forcé : cache-first (max-age plafonné), gardé par le negative-cache
142
- * (pas de re-fetch en boucle pendant une panne), déduplication des appels concurrents.
143
- */
144
- async function loadJwks(
145
- state: JwksState,
146
- fetchFn: typeof globalThis.fetch,
147
- baseUrl: string,
148
- ): Promise<JsonWebKey[]> {
149
- const now = Date.now()
150
- const c = state.cache.get(baseUrl)
151
- if (c && now - c.fetchedAt < c.maxAgeMs) return c.keys
152
- const failedAt = state.lastFailedAt.get(baseUrl)
153
- if (failedAt !== undefined && now - failedAt < NEGATIVE_CACHE_TTL_MS) {
154
- throw new Error('jwks_fetch_failed')
155
- }
156
- return fetchJwksDeduped(state, fetchFn, baseUrl)
157
- }
158
-
159
- /**
160
- * Refetch FORCÉ (kid inconnu → possible rotation). Borné par un cooldown : dans la
161
- * fenêtre `FORCED_REFETCH_COOLDOWN_MS`, on NE refetch PAS (retourne `null` → l'appelant
162
- * retombe sur `no_matching_key` sans réseau). Anti-amplification : un token à `kid`
163
- * aléatoire ne peut pas provoquer un fetch JWKS par appel.
164
- */
165
- async function forcedRefetchJwks(
166
- state: JwksState,
167
- fetchFn: typeof globalThis.fetch,
168
- baseUrl: string,
169
- ): Promise<JsonWebKey[] | null> {
170
- const now = Date.now()
171
- const last = state.lastForcedFetchAt.get(baseUrl)
172
- if (last !== undefined && now - last < FORCED_REFETCH_COOLDOWN_MS) return null
173
- state.lastForcedFetchAt.set(baseUrl, now)
174
- const failedAt = state.lastFailedAt.get(baseUrl)
175
- if (failedAt !== undefined && now - failedAt < NEGATIVE_CACHE_TTL_MS) {
176
- throw new Error('jwks_fetch_failed')
177
- }
178
- return fetchJwksDeduped(state, fetchFn, baseUrl)
179
- }
180
-
181
- interface AlgParams {
182
- importAlg: RsaHashedImportParams | EcKeyImportParams
183
- verifyAlg: AlgorithmIdentifier | EcdsaParams
184
- }
185
-
186
- // alg → paramètres WebCrypto import/verify. `null` = pas de vérif locale (fallback).
187
- function algParams(alg: string | undefined): AlgParams | null {
188
- if (alg === 'RS256') {
189
- return {
190
- importAlg: { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' },
191
- verifyAlg: { name: 'RSASSA-PKCS1-v1_5' },
192
- }
193
- }
194
- if (alg === 'ES256') {
195
- return {
196
- importAlg: { name: 'ECDSA', namedCurve: 'P-256' },
197
- verifyAlg: { name: 'ECDSA', hash: 'SHA-256' },
198
- }
199
- }
200
- return null // HS256 / none / autre → jamais de vérif locale avec un secret
201
- }
202
-
203
- export type VerifyResult =
204
- | { ok: true; claims: Record<string, unknown>; header: { alg: string; kid?: string; typ?: string } }
205
- | { ok: false; code: string }
206
-
207
- export async function verifyJwtLocal(
208
- /**
209
- * SEC-F4 : clé d'isolation du cache JWKS (identité d'objet). L'appelant passe son
210
- * `client` (n'importe quel `object` opaque) → l'état JWKS est porté par ce client
211
- * via `WeakMap` (jamais process-global). Garde `jwks.ts` sans dépendance vers `core`.
212
- */
213
- scope: object,
214
- fetchFn: typeof globalThis.fetch,
215
- baseUrl: string,
216
- jwt: string,
217
- opts: {
218
- allowExpired?: boolean
219
- /**
220
- * Callback d'observabilité (LOT 3, finding I8), appelé à chaque échec de fetch
221
- * JWKS (réseau ou HTTP non-2xx). Volontairement non typé sur `AuraObservabilityEvent`
222
- * (core) — `jwks.ts` reste sans dépendance vers `@aurabase/core` ; c'est `AuthService`
223
- * qui fournit ce callback en le reliant à `emitAuraEvent(client.onEvent, client.debug,
224
- * {kind:'jwks-fetch-failed', baseUrl})`. Ne doit jamais throw (appelé au mieux-effort).
225
- */
226
- onEvent?: (baseUrl: string) => void
227
- } = {},
228
- ): Promise<VerifyResult> {
229
- let d: DecodedJwt
230
- try {
231
- d = decodeJwt(jwt)
232
- } catch {
233
- return { ok: false, code: 'invalid_jwt' }
234
- }
235
-
236
- const params = algParams(d.header.alg)
237
- if (!params) return { ok: false, code: 'unsupported_alg' } // → l'appelant fait le fallback getUser
238
-
239
- const state = stateFor(scope)
240
-
241
- // Le kty doit correspondre à l'alg (RS256→RSA, ES256→EC) — y compris sur le
242
- // match par kid : deux clés peuvent partager un kid après rotation, on ne doit
243
- // jamais sélectionner une clé EC pour un token RS256 (défense en profondeur).
244
- const matchesAlg = (k: JsonWebKey): boolean =>
245
- d.header.alg === 'RS256' ? k.kty === 'RSA' : k.kty === 'EC'
246
- // Candidats à essayer, du bon `kty` :
247
- // - AVEC `kid` : on ne retient QUE les clés du kid demandé. Matcher une autre
248
- // clé « par kty seul » ferait échouer verify() → `signature_invalid` SANS
249
- // fallback (seul `no_matching_key` déclenche le fallback getUser) ; en rotation
250
- // (kid absent du JWKS), un token pourtant valide serait rejeté durement.
251
- // - SANS `kid` : on retient TOUTES les clés du bon `kty` et on tente verify sur
252
- // chacune (comme jose). En rotation multi-clés sans kid, la 2e clé peut être la
253
- // bonne → plus de faux `signature_invalid` en ne testant que la première.
254
- const candidateKeys = (keys: JsonWebKey[]): JsonWebKey[] =>
255
- d.header.kid
256
- ? keys.filter((k) => (k as { kid?: string }).kid === d.header.kid && matchesAlg(k))
257
- : keys.filter((k) => matchesAlg(k))
258
-
259
- let keys: JsonWebKey[]
260
- try {
261
- keys = await loadJwks(state, fetchFn, baseUrl)
262
- } catch {
263
- try {
264
- opts.onEvent?.(baseUrl)
265
- } catch {
266
- // le callback ne doit jamais throw
267
- }
268
- return { ok: false, code: 'jwks_fetch_failed' }
269
- }
270
- let candidates = candidateKeys(keys)
271
-
272
- // Rotation de clés : si aucune clé ne matche le kid demandé, on force UN refetch
273
- // (borné par cooldown). Le cooldown peut renvoyer `null` → pas de réseau, on
274
- // retombe sur `no_matching_key` (→ fallback getUser côté appelant).
275
- if (candidates.length === 0 && d.header.kid) {
276
- let refetched: JsonWebKey[] | null
277
- try {
278
- refetched = await forcedRefetchJwks(state, fetchFn, baseUrl)
279
- } catch {
280
- try {
281
- opts.onEvent?.(baseUrl)
282
- } catch {
283
- // le callback ne doit jamais throw
284
- }
285
- return { ok: false, code: 'jwks_fetch_failed' }
286
- }
287
- if (refetched) {
288
- keys = refetched
289
- candidates = candidateKeys(keys)
290
- }
291
- }
292
- if (candidates.length === 0) return { ok: false, code: 'no_matching_key' }
293
-
294
- // JWK issu du réseau : un JWK malformé (ou incompatible avec l'algo) fait *jeter*
295
- // importKey/verify (DataError). On échoue fermé (signature_invalid) — jamais de
296
- // rejet de promesse (contrat AuraResponse), jamais de fallback qui masquerait un
297
- // JWKS corrompu. On tente chaque candidat ; le premier verify() vrai l'emporte.
298
- const signingBytes = new TextEncoder().encode(d.signingInput)
299
- let valid = false
300
- for (const jwk of candidates) {
301
- try {
302
- const key = await crypto.subtle.importKey('jwk', jwk, params.importAlg, false, ['verify'])
303
- if (
304
- await crypto.subtle.verify(
305
- params.verifyAlg,
306
- key,
307
- d.signature as unknown as BufferSource,
308
- signingBytes,
309
- )
310
- ) {
311
- valid = true
312
- break
313
- }
314
- } catch {
315
- // clé malformée / incompatible → on tente le candidat suivant.
316
- }
317
- }
318
- if (!valid) return { ok: false, code: 'signature_invalid' }
319
-
320
- const now = Math.floor(Date.now() / 1000)
321
- if (!opts.allowExpired && typeof d.payload.exp === 'number' && d.payload.exp < now) {
322
- return { ok: false, code: 'token_expired' }
323
- }
324
- if (typeof d.payload.nbf === 'number' && d.payload.nbf > now + 60) {
325
- return { ok: false, code: 'token_not_yet_valid' }
326
- }
327
-
328
- return {
329
- ok: true,
330
- claims: d.payload,
331
- header: {
332
- alg: d.header.alg as string,
333
- kid: d.header.kid,
334
- typ: d.header.typ,
335
- },
336
- }
337
- }
@@ -1,27 +0,0 @@
1
- // PKCE (RFC 7636) — génération du `code_verifier` et calcul du `code_challenge`
2
- // S256 pour le flux OAuth `signInWithOAuth(..., { flowType: 'pkce' })`.
3
-
4
- function b64url(bytes: Uint8Array): string {
5
- let s = ''
6
- for (const b of bytes) s += String.fromCharCode(b)
7
- return btoa(s).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
8
- }
9
-
10
- /**
11
- * Génère un `code_verifier` aléatoire haute entropie (64 octets → ~86
12
- * caractères base64url), dans la plage [43, 128] imposée par RFC 7636.
13
- */
14
- export function generateCodeVerifier(): string {
15
- const bytes = new Uint8Array(64)
16
- crypto.getRandomValues(bytes)
17
- return b64url(bytes)
18
- }
19
-
20
- /**
21
- * Calcule `code_challenge = base64url(SHA-256(verifier))` sans padding
22
- * (méthode `S256`), tel qu'attendu par le backend aura-auth (oauth.rs).
23
- */
24
- export async function codeChallengeS256(verifier: string): Promise<string> {
25
- const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier))
26
- return b64url(new Uint8Array(digest))
27
- }
@@ -1,89 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // Types du package @aurabase/auth : façade `verifyOtp` (parité @supabase/auth-js).
3
- // ---------------------------------------------------------------------------
4
-
5
- /**
6
- * Types d'OTP « email » (parité `EmailOtpType` de supabase-js). Tous ne sont pas
7
- * exercables côté backend Aurabase : `invite` n'a aucun endpoint (→ `verifyOtp`
8
- * lève `otp_type_unsupported`). Conservé dans l'union pour la parité de surface.
9
- */
10
- export type EmailOtpType = 'signup' | 'invite' | 'magiclink' | 'recovery' | 'email_change' | 'email'
11
-
12
- /**
13
- * Types d'OTP « mobile » (parité `MobileOtpType` de supabase-js). `phone_change`
14
- * n'a aucun endpoint backend (→ `otp_type_unsupported`).
15
- */
16
- export type MobileOtpType = 'sms' | 'phone_change'
17
-
18
- export interface VerifySignupOtpParams {
19
- type: 'signup'
20
- /** Jeton reçu par email (lien de confirmation d'inscription). */
21
- token: string
22
- }
23
-
24
- export interface VerifyMagiclinkOtpParams {
25
- type: 'magiclink'
26
- /** Jeton du magic link. */
27
- token: string
28
- }
29
-
30
- export interface VerifyEmailOtpParams {
31
- type: 'email'
32
- email: string
33
- /** Code OTP à 6 chiffres reçu par email (mappé sur `code` côté backend). */
34
- token: string
35
- }
36
-
37
- export interface VerifySmsOtpParams {
38
- type: 'sms'
39
- phone: string
40
- /** Code OTP reçu par SMS (mappé sur `code` côté backend). */
41
- token: string
42
- }
43
-
44
- export interface VerifyEmailChangeOtpParams {
45
- type: 'email_change'
46
- /** Jeton de confirmation de changement d'email. */
47
- token: string
48
- }
49
-
50
- export interface VerifyRecoveryOtpParams {
51
- type: 'recovery'
52
- /** Jeton de récupération reçu par email. */
53
- token: string
54
- /**
55
- * Nouveau mot de passe. REQUIS : le backend `reset-password` fusionne
56
- * consommation du token + changement de mot de passe (divergence documentée
57
- * avec supabase-js qui renvoie une session puis attend un `updateUser`).
58
- */
59
- password: string
60
- }
61
-
62
- /** Type de surface (parité) sans endpoint backend → `otp_type_unsupported`. */
63
- export interface VerifyInviteOtpParams {
64
- type: 'invite'
65
- token: string
66
- }
67
-
68
- /** Type de surface (parité) sans endpoint backend → `otp_type_unsupported`. */
69
- export interface VerifyPhoneChangeOtpParams {
70
- type: 'phone_change'
71
- phone: string
72
- token: string
73
- }
74
-
75
- /**
76
- * Union discriminée par `type` de la façade `verifyOtp` (parité surface
77
- * `@supabase/auth-js`). Chaque variante route vers l'endpoint historique
78
- * correspondant. `invite`/`phone_change` restent dans l'union pour la parité
79
- * mais lèvent `otp_type_unsupported` tant que le backend ne les expose pas.
80
- */
81
- export type VerifyOtpParams =
82
- | VerifySignupOtpParams
83
- | VerifyMagiclinkOtpParams
84
- | VerifyEmailOtpParams
85
- | VerifySmsOtpParams
86
- | VerifyEmailChangeOtpParams
87
- | VerifyRecoveryOtpParams
88
- | VerifyInviteOtpParams
89
- | VerifyPhoneChangeOtpParams