better-supabase 0.4.0 → 0.5.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 (180) hide show
  1. package/README.md +135 -16
  2. package/dist/actor-DaJjqD5R.d.ts +43 -0
  3. package/dist/channel-FQW-CnGR.d.ts +70 -0
  4. package/dist/cli/bin.js +1 -1
  5. package/dist/cli/codemod-DqV7612m.js +388 -0
  6. package/dist/cli/{config-D9R0o1LH.js → config-CPVpXP5I.js} +78 -8
  7. package/dist/cli/{config-SSKSTUl2.js → config-dtoekM0v.js} +1 -1
  8. package/dist/cli/{read-sets-CMa29t9a.js → diff-SjkO5rNr.js} +1 -220
  9. package/dist/cli/{dist-CFgGknmZ.js → dist-DBPdlPYK.js} +4 -4
  10. package/dist/cli/{dist-B1MvLv-M.js → dist-DreZ24Sz.js} +1 -1
  11. package/dist/cli/{dist-Du7VnEUG.js → dist-xn4wlboc.js} +112 -1
  12. package/dist/cli/{doctor-BOym3mbL.js → doctor-C_A-KEAz.js} +533 -50
  13. package/dist/cli/{env-BZ0uy8XK.js → env-DmKv_G4A.js} +1 -1
  14. package/dist/cli/gen-CIdSQZad.js +2 -0
  15. package/dist/cli/{gen-Ccn_p90L.js → gen-CjElD1Vw.js} +321 -88
  16. package/dist/cli/index.d.ts +1 -1
  17. package/dist/cli/index.js +4 -4
  18. package/dist/cli/{init-ClnxRYBF.js → init-DMa6M7hV.js} +2 -2
  19. package/dist/cli/{introspect-DxqfkVIv.js → introspect-BKlaIu_M.js} +2 -2
  20. package/dist/cli/{openapi-8WHjxiTJ.js → openapi-Cp5Fyta-.js} +1 -1
  21. package/dist/cli/read-sets-VQcPgxU9.js +436 -0
  22. package/dist/cli/{run-CP20LKk_.js → run-Bo_NLT5n.js} +16 -12
  23. package/dist/cli/{seed-5J6eu_Xg.js → seed-CUlqWh-8.js} +1 -1
  24. package/dist/cli/sql-CVx-1O8G.js +373 -0
  25. package/dist/cli/{version-5mW_8sY1.js → version-BCtlgDQx.js} +1 -1
  26. package/dist/client/index.d.ts +1 -1
  27. package/dist/client/index.js +3 -10
  28. package/dist/clone-BfgmLU90.js +21 -0
  29. package/dist/{compiler-DB3aSFOA.d.ts → compiler-BXH_aZ7N.d.ts} +2 -2
  30. package/dist/config/index.d.ts +4 -4
  31. package/dist/config/index.js +4 -4
  32. package/dist/{config-C1CYcm6o.d.ts → config-Bv7gvfzC.d.ts} +185 -11
  33. package/dist/{config-CbvFmGD8.js → config-DreERlKo.js} +1 -1
  34. package/dist/{define-CRS2MRV3.d.ts → define-Bp_BZa5h.d.ts} +11 -7
  35. package/dist/{define-Bh0AqTik.js → define-cNKzqwL_.js} +202 -16
  36. package/dist/edge/index.d.ts +16 -5
  37. package/dist/edge/index.js +10 -7
  38. package/dist/{entitlements-Dm-FHpNH.d.ts → entitlements-BiJZ4t49.d.ts} +1 -1
  39. package/dist/env/index.d.ts +2 -2
  40. package/dist/env/index.js +34 -1
  41. package/dist/{errors-L0xK41y_.js → errors-DtwXa6b8.js} +1 -0
  42. package/dist/events/index.d.ts +3 -2
  43. package/dist/events/index.js +65 -12
  44. package/dist/events-aIO7vsIk.d.ts +230 -0
  45. package/dist/{result-CqEsbgYs.d.ts → executor-BunPOO-k.d.ts} +200 -1
  46. package/dist/{executor-CZ7ImRiD.d.ts → executor-Cghdstwu.d.ts} +1 -2
  47. package/dist/{executor-CVt6dD0B.js → executor-XycESQPH.js} +3 -3
  48. package/dist/hono/index.d.ts +17 -6
  49. package/dist/hono/index.js +40 -5
  50. package/dist/impersonation-BgSHAYLf.js +133 -0
  51. package/dist/{resolve-BAqQcwMW.d.ts → impersonation-BmePsuxz.d.ts} +36 -6
  52. package/dist/{index-BhHEC04r.d.ts → index-C7f8cOBM.d.ts} +2 -2
  53. package/dist/{index-Dy6kuF0P.d.ts → index-CLg87OBW.d.ts} +6 -1
  54. package/dist/{index-Cf-D2jk1.d.ts → index-CWMDdEr4.d.ts} +2 -2
  55. package/dist/{index-D5IfUIDh.d.ts → index-DOESKG27.d.ts} +33 -8
  56. package/dist/{index-DFmOpBGC.d.ts → index-DgILJRXj.d.ts} +35 -9
  57. package/dist/{index-RlLXd8dL.d.ts → index-DmXSxbLi.d.ts} +4 -4
  58. package/dist/{index-BBdvo-5d.d.ts → index-Dp2VDwog.d.ts} +49 -6
  59. package/dist/{index-528Ugmyp.d.ts → index-SaTsEfGP.d.ts} +76 -8
  60. package/dist/{index-BAy4tsAP.d.ts → index-fag8VJZ2.d.ts} +3 -4
  61. package/dist/index.d.ts +30 -13
  62. package/dist/index.js +10 -9
  63. package/dist/jobs/index.d.ts +147 -101
  64. package/dist/jobs/index.js +744 -237
  65. package/dist/{json-schema-DP6V7cbr.js → json-schema-m1fiwKgN.js} +22 -1
  66. package/dist/kit-events-CTFDfSwb.js +60 -0
  67. package/dist/kit-transport-B82k1djG.d.ts +33 -0
  68. package/dist/kit-transport-DJlHQUBU.js +55 -0
  69. package/dist/{config-BpxDfnbg.js → kits-CGLLrNPd.js} +37 -9
  70. package/dist/list/index.d.ts +1 -1
  71. package/dist/{live-BHakSWWo.d.ts → live-D9W2M5aO.d.ts} +6 -5
  72. package/dist/mcp/index.d.ts +25 -8
  73. package/dist/mcp/index.js +23 -14
  74. package/dist/{mfa-C7MNQ1Ob.d.ts → mfa-Cu96oJdw.d.ts} +2 -16
  75. package/dist/next/index.d.ts +31 -10
  76. package/dist/next/index.js +136 -27
  77. package/dist/notifications/index.d.ts +162 -0
  78. package/dist/notifications/index.js +264 -0
  79. package/dist/openapi/index.d.ts +1 -1
  80. package/dist/openapi/index.js +2 -2
  81. package/dist/orgs/index.d.ts +132 -0
  82. package/dist/orgs/index.js +245 -0
  83. package/dist/orpc/index.d.ts +28 -8
  84. package/dist/orpc/index.js +16 -3
  85. package/dist/otel/index.d.ts +21 -2
  86. package/dist/otel/index.js +50 -9
  87. package/dist/permdock-sql-C2Inc6Xc.d.ts +29 -0
  88. package/dist/permdock-sql-DgOfeixi.js +51 -0
  89. package/dist/plugin-DwARMuQp.js +59 -0
  90. package/dist/{plugin-bNhvJwRh.d.ts → plugin-o144f322.d.ts} +17 -5
  91. package/dist/plugins/actor/index.d.ts +5 -2
  92. package/dist/plugins/actor/index.js +22 -8
  93. package/dist/plugins/rules/index.d.ts +2 -2
  94. package/dist/plugins/rules/index.js +15 -10
  95. package/dist/plugins/soft-delete/index.d.ts +3 -3
  96. package/dist/plugins/soft-delete/index.js +14 -5
  97. package/dist/plugins/tenant/index.d.ts +2 -2
  98. package/dist/plugins/tenant/index.js +38 -20
  99. package/dist/plugins/timestamps/index.d.ts +1 -1
  100. package/dist/plugins/timestamps/index.js +4 -3
  101. package/dist/plugins/validation/index.d.ts +2 -2
  102. package/dist/plugins/validation/index.js +26 -6
  103. package/dist/{pool-DFwEQwmN.d.ts → pool-C9voM4Kw.d.ts} +17 -6
  104. package/dist/postgres/index.d.ts +5 -5
  105. package/dist/postgres/index.js +20 -11
  106. package/dist/{postgrest-Bc-0Xw62.d.ts → postgrest-CruYKAvV.d.ts} +1 -1
  107. package/dist/{problem-BihjPR0t.js → problem-BW1KhzSG.js} +2 -1
  108. package/dist/{problem-U8UEKccv.d.ts → problem-Blxe8S31.d.ts} +1 -1
  109. package/dist/query/index.d.ts +2 -2
  110. package/dist/query/index.js +3 -3
  111. package/dist/{query-BMMSWbI7.js → query-CCbo44lG.js} +2 -2
  112. package/dist/queue-BYUCjr59.d.ts +252 -0
  113. package/dist/react/index.d.ts +8 -7
  114. package/dist/react/index.js +4 -3
  115. package/dist/react/server.d.ts +14 -3
  116. package/dist/react/server.js +10 -2
  117. package/dist/react/session.d.ts +7 -1
  118. package/dist/react/session.js +9 -1
  119. package/dist/{react-CQHMaESR.js → react-C_s7kiNz.js} +103 -11
  120. package/dist/{read-set-FWK8qQ58.js → read-set-DQFt1N_Y.js} +22 -1
  121. package/dist/realtime/index.d.ts +3 -3
  122. package/dist/realtime/index.js +5 -4
  123. package/dist/{refresh-BwYkyNOQ.d.ts → refresh-CFPX0Qft.d.ts} +1 -1
  124. package/dist/{resource-BJcaIfxi.d.ts → resource-DNRFP7KR.d.ts} +5 -5
  125. package/dist/{resource-My_y-Syh.js → resource-mqfJW4YF.js} +22 -7
  126. package/dist/respond-BR1fJWOB.d.ts +377 -0
  127. package/dist/{result-Bj6yt33D.js → result-BKiliPY7.js} +1 -1
  128. package/dist/server/index.d.ts +15 -12
  129. package/dist/server/index.js +11 -17
  130. package/dist/{server-BA75B0mT.js → server-B1mZ7CgQ.js} +259 -37
  131. package/dist/{shared-DnoCdMDr.js → shared-D1dRUrAg.js} +16 -2
  132. package/dist/signers-Cc6r98SW.d.ts +162 -0
  133. package/dist/{simplify-Cqvfr9dj.js → simplify-_0oUKqCd.js} +4 -115
  134. package/dist/sql/index.d.ts +283 -11
  135. package/dist/sql/index.js +8705 -775
  136. package/dist/{sql-B34HU2DI.js → sql-Coh6n4cC.js} +9 -2
  137. package/dist/ssr/index.d.ts +4 -4
  138. package/dist/ssr/index.js +1 -2
  139. package/dist/{standard-BRyBGTtp.js → standard-D7r6dMUu.js} +6 -3
  140. package/dist/{standard-BsaCYQJc.d.ts → standard-J4YgMOLm.d.ts} +1 -1
  141. package/dist/{stats-C_YxA2r1.js → stats-Bqob3WqT.js} +4 -4
  142. package/dist/storage/index.d.ts +4 -4
  143. package/dist/storage/index.js +155 -26
  144. package/dist/support-CEPwlw2G.d.ts +89 -0
  145. package/dist/support-view-B8SlToQX.d.ts +17 -0
  146. package/dist/support-view-g4YLBeqX.js +18 -0
  147. package/dist/support-wHnK6zp-.js +293 -0
  148. package/dist/{permdock-sql-C4KFzLc9.js → template-TxrGI5jR.js} +2 -31
  149. package/dist/{temporal-BwshQk0W.js → temporal-CVlIV2DZ.js} +17 -4
  150. package/dist/{temporal-required-CBNHT6ni.js → temporal-required-CAt4Dc9Z.js} +2 -2
  151. package/dist/testing/index.d.ts +132 -10
  152. package/dist/testing/index.js +476 -8
  153. package/dist/{types-DONv9SHN.d.ts → types-Dnf_wRDz.d.ts} +26 -3
  154. package/dist/user-change-CHFEUro1.js +49 -0
  155. package/dist/{webhooks-Bh_Jf_-l.js → verify-Ce49ETPz.js} +5 -5
  156. package/dist/{version-Bmf7_FzM.js → version-DOYTYwHP.js} +1 -1
  157. package/dist/{mfa-byfjruR9.js → view-Bn6HNKUe.js} +97 -98
  158. package/dist/{view-B64o81wp.d.ts → view-CbgObAeb.d.ts} +22 -31
  159. package/dist/webhooks/index.d.ts +135 -4
  160. package/dist/webhooks/index.js +588 -2
  161. package/dist/wire-D2dT86vi.js +35 -0
  162. package/package.json +27 -19
  163. package/schemas/config-v1.json +131 -1
  164. package/schemas/doctor-report-v1.json +11 -0
  165. package/skills/better-supabase/SKILL.md +9 -6
  166. package/skills/better-supabase/references/plugins.md +6 -3
  167. package/skills/better-supabase/references/troubleshooting.md +1 -0
  168. package/skills/better-supabase-api/SKILL.md +9 -2
  169. package/skills/better-supabase-api/references/adapters.md +11 -8
  170. package/skills/better-supabase-auth/SKILL.md +18 -7
  171. package/skills/better-supabase-auth/references/permdock.md +78 -11
  172. package/dist/cli/gen-D5cLCULx.js +0 -2
  173. package/dist/cli/sql-D4VbqmXi.js +0 -199
  174. package/dist/events-B21UOhvP.d.ts +0 -84
  175. package/dist/executor-B5IoUxLE.d.ts +0 -195
  176. package/dist/invalidate-CgxmRamI.js +0 -24
  177. package/dist/permdock-sql-DImJULY-.d.ts +0 -17
  178. package/dist/plugin-BqR6wKMB.js +0 -23
  179. package/dist/respond-DgIbdrt8.d.ts +0 -194
  180. package/dist/view-BrJI2LKp.js +0 -45
@@ -1,87 +1,9 @@
1
- import { n as dbError } from "./errors-L0xK41y_.js";
1
+ import { n as dbError } from "./errors-DtwXa6b8.js";
2
2
  import { t as consoleLogger } from "./logger-glM28NVN.js";
3
3
  import { n as decodeJwtPayload } from "./base64-D2gsioCY.js";
4
+ import { a as delegationOf, i as actorOf, n as impersonatorOf, r as userContext } from "./impersonation-BgSHAYLf.js";
4
5
  import { DEFAULT_COOKIE_OPTIONS, createChunks, isChunkLike, parseCookieHeader, serializeCookieHeader, stringFromBase64URL, stringToBase64URL } from "@supabase/ssr";
5
6
  import { extractCredentials, verifyCredentials } from "@supabase/server/core";
6
- //#region src/auth/impersonation.ts
7
- /** The `act` claim for an impersonated session. */
8
- function actClaim(options) {
9
- return {
10
- sub: options.actor,
11
- reason: options.reason
12
- };
13
- }
14
- /** The impersonator in `claims.act`, or `undefined` for a normal session. */
15
- function impersonatorOf(claims) {
16
- const act = claims["act"];
17
- if (typeof act !== "object" || act === null) return void 0;
18
- const { sub, reason } = act;
19
- if (typeof sub !== "string" || sub === "") return void 0;
20
- return typeof reason === "string" ? {
21
- id: sub,
22
- reason
23
- } : { id: sub };
24
- }
25
- //#endregion
26
- //#region src/auth/actor.ts
27
- function isRecord(value) {
28
- return typeof value === "object" && value !== null && !Array.isArray(value);
29
- }
30
- function copyAct(level) {
31
- const entries = Object.entries(level).map(([key, value]) => [key, key === "act" && isRecord(value) ? copyAct(value) : value]);
32
- return Object.fromEntries(entries);
33
- }
34
- /**
35
- * Reads only `act` and `client_id`, the way PermDock's `actorOf` does. An
36
- * `act` that is not a chain of objects each with a non-empty `sub` is
37
- * `{ ok: false }`: the session must not pass as the user alone.
38
- */
39
- function actorOf(claims) {
40
- const outer = claims["act"];
41
- if (outer !== void 0) {
42
- let level = outer;
43
- while (level !== void 0) {
44
- if (!isRecord(level)) return {
45
- ok: false,
46
- reason: "invalid-chain"
47
- };
48
- const sub = level["sub"];
49
- if (typeof sub !== "string" || sub === "") return {
50
- ok: false,
51
- reason: "invalid-chain"
52
- };
53
- level = level["act"];
54
- }
55
- if (!isRecord(outer) || typeof outer["sub"] !== "string") return {
56
- ok: false,
57
- reason: "invalid-chain"
58
- };
59
- return {
60
- ok: true,
61
- actor: {
62
- id: outer["sub"],
63
- kind: "oauth-client",
64
- chain: copyAct(outer)
65
- }
66
- };
67
- }
68
- const client = claims["client_id"];
69
- if (typeof client === "string" && client !== "") return {
70
- ok: true,
71
- actor: {
72
- id: client,
73
- kind: "oauth-client"
74
- }
75
- };
76
- return { ok: true };
77
- }
78
- /** The OAuth `scope` claim (a space-separated string or a list); `undefined` when empty. */
79
- function delegationOf(claims) {
80
- const scope = claims["scope"];
81
- const scopes = typeof scope === "string" ? scope.split(/\s+/u).filter(Boolean) : Array.isArray(scope) ? scope.filter((item) => typeof item === "string") : [];
82
- return scopes.length > 0 ? { scopes } : void 0;
83
- }
84
- //#endregion
85
7
  //#region src/auth/refresh.ts
86
8
  /**
87
9
  * How long a finished refresh is reused for requests still carrying the old
@@ -284,7 +206,7 @@ function serverEnv(options) {
284
206
  url: env.url,
285
207
  publishableKeys: { default: env.publishableKey },
286
208
  secretKeys: env.secretKeys ?? (env.secretKey ? { default: env.secretKey } : {}),
287
- jwks: options.jwks ?? env.jwksUrl
209
+ jwks: options.jwks ?? env.jwks ?? env.jwksUrl
288
210
  };
289
211
  }
290
212
  const MEMO_SIZE = 256;
@@ -295,7 +217,7 @@ let memoByJwks = /* @__PURE__ */ new WeakMap();
295
217
  * and island resolves the same token again; this skips the signature check.
296
218
  */
297
219
  function memoFor(options) {
298
- const jwks = options.jwks;
220
+ const jwks = options.jwks ?? options.env.jwks;
299
221
  if (jwks && typeof jwks === "object" && !(jwks instanceof URL)) {
300
222
  let memo = memoByJwks.get(jwks);
301
223
  if (!memo) memoByJwks.set(jwks, memo = /* @__PURE__ */ new Map());
@@ -311,6 +233,42 @@ function memoFor(options) {
311
233
  if (!memo) memoByUrl.set(key, memo = /* @__PURE__ */ new Map());
312
234
  return memo;
313
235
  }
236
+ function sameJson(a, b) {
237
+ if (a === b) return true;
238
+ if (typeof a !== "object" || typeof b !== "object" || !a || !b) return false;
239
+ if (Array.isArray(a) !== Array.isArray(b)) return false;
240
+ const left = Object.entries(a);
241
+ const right = new Map(Object.entries(b));
242
+ return left.length === right.size && left.every(([key, value]) => right.has(key) && sameJson(value, right.get(key)));
243
+ }
244
+ /**
245
+ * Records a token that `@supabase/server` verified for this request, so the
246
+ * next `resolveAuth` with these options doesn't verify it again. Only when
247
+ * `claims` is the token's own payload, it hasn't expired, and its `iss` and
248
+ * `aud` pass the checks these options would apply; otherwise returns false
249
+ * and the token is verified as usual.
250
+ */
251
+ function rememberVerified(options, verified) {
252
+ const { token, claims, user } = verified;
253
+ const now = Math.floor((options.now ?? Date.now)() / 1e3);
254
+ const expiresAt = typeof claims.exp === "number" ? claims.exp : null;
255
+ if (expiresAt === null || expiresAt <= now) return false;
256
+ if (!sameJson(decodeJwtPayload(token), claims)) return false;
257
+ const issuers = [options.issuer ?? `${options.env.url}/auth/v1`].flat();
258
+ if (typeof claims.iss !== "string" || !issuers.includes(claims.iss)) return false;
259
+ const audiences = [options.audience ?? "authenticated"].flat();
260
+ const aud = claims.aud;
261
+ const given = Array.isArray(aud) ? aud : [aud];
262
+ if (!audiences.some((audience) => given.includes(audience))) return false;
263
+ remember(memoFor(options), token, {
264
+ kind: "user",
265
+ token,
266
+ claims,
267
+ user,
268
+ expiresAt
269
+ }, expiresAt);
270
+ return true;
271
+ }
314
272
  function remembered(memo, token, now) {
315
273
  const hit = memo.get(token);
316
274
  if (!hit) return void 0;
@@ -385,7 +343,7 @@ async function checkClaims(state, options) {
385
343
  if (!actorOf(state.claims).ok) return {
386
344
  kind: "invalid",
387
345
  reason: "actor",
388
- error: dbError("unauthorized", "The token's act claim is not a chain of actors with a sub", { code: "ACTOR_INVALID" })
346
+ error: dbError("unauthorized", "The token's act claim is not a chain of actors with a sub, or has a kind other than support or impersonation", { code: "ACTOR_INVALID" })
389
347
  };
390
348
  if (!options.claims) return state;
391
349
  let outcome = options.claims["~standard"].validate(state.claims);
@@ -444,7 +402,7 @@ function base64url(text) {
444
402
  * fetch it as before.
445
403
  */
446
404
  function prefetchJwks(options) {
447
- if (options.jwks !== void 0) return Promise.resolve();
405
+ if (options.jwks !== void 0 || options.env.jwks !== void 0) return Promise.resolve();
448
406
  return verifyCredentials({
449
407
  token: PREFETCH_TOKEN,
450
408
  apikey: null
@@ -546,6 +504,10 @@ async function resolveAuth(request, options) {
546
504
  token: null,
547
505
  apikey: credentials.apikey
548
506
  }, options.secret === true ? ["secret"] : options.secret.map((name) => `secret:${name}`), options, "bearer"), cookies);
507
+ if (options.cookies === false) return resolution({
508
+ kind: "anon",
509
+ reason: "none"
510
+ }, cookies);
549
511
  const name = options.cookie?.name ?? sessionCookieName(options.env.url);
550
512
  const session = readSession(cookies(), name);
551
513
  if (!session) {
@@ -611,19 +573,7 @@ async function resolveAuth(request, options) {
611
573
  /** The repository context (`actor`, `claims`) for an auth state. */
612
574
  function authContext(auth) {
613
575
  switch (auth.kind) {
614
- case "user": {
615
- const impersonator = impersonatorOf(auth.claims);
616
- return {
617
- actor: {
618
- id: auth.user.id,
619
- kind: "user",
620
- ...auth.user.role === void 0 ? {} : { role: auth.user.role },
621
- ...auth.user.email === void 0 ? {} : { email: auth.user.email },
622
- ...impersonator ? { impersonator: impersonator.id } : {}
623
- },
624
- claims: auth.claims
625
- };
626
- }
576
+ case "user": return userContext(auth.user, auth.claims);
627
577
  case "service": return {
628
578
  actor: {
629
579
  id: `service:${auth.keyName}`,
@@ -682,4 +632,53 @@ function checkAal(auth, required) {
682
632
  });
683
633
  }
684
634
  //#endregion
685
- export { delegationOf as _, clientIp as a, AUTH_CACHE_HEADERS as c, readSession as d, serializeCookie as f, actorOf as g, refreshSession as h, authContext as i, applyCookieWrites as l, writeSession as m, amrOf as n, prefetchJwks as o, sessionCookieName as p, checkAal as r, resolveAuth as s, aalOf as t, parseCookies as u, actClaim as v, impersonatorOf as y };
635
+ //#region src/auth/view.ts
636
+ /** Whether the token belongs to an anonymous user (`signInAnonymously()`). */
637
+ function isAnonymousUser(claims) {
638
+ return "is_anonymous" in claims && claims.is_anonymous === true;
639
+ }
640
+ /** Drops the token from an `AuthState`, leaving only serializable fields. */
641
+ function toSession(auth) {
642
+ switch (auth.kind) {
643
+ case "user": {
644
+ const impersonator = impersonatorOf(auth.claims);
645
+ const outcome = actorOf(auth.claims);
646
+ const actor = outcome.ok ? outcome.actor : void 0;
647
+ const client = actor?.kind === "oauth-client" ? actor : void 0;
648
+ const scopes = client ? delegationOf(auth.claims)?.scopes : void 0;
649
+ const delegation = client && (scopes || client.chain) ? {
650
+ scopes: scopes ?? [],
651
+ ...client.chain ? { chain: client.chain } : {}
652
+ } : void 0;
653
+ return {
654
+ kind: "user",
655
+ user: auth.user,
656
+ claims: auth.claims,
657
+ expiresAt: auth.expiresAt,
658
+ ...auth.profile === void 0 ? {} : { profile: auth.profile },
659
+ aal: aalOf(auth.claims),
660
+ anonymous: isAnonymousUser(auth.claims),
661
+ amr: amrOf(auth.claims),
662
+ ...impersonator ? { impersonator } : {},
663
+ ...actor ? { actor } : {},
664
+ ...delegation ? { delegation } : {}
665
+ };
666
+ }
667
+ case "service": return {
668
+ kind: "service",
669
+ keyName: auth.keyName
670
+ };
671
+ case "anon": return {
672
+ kind: "anon",
673
+ reason: auth.reason
674
+ };
675
+ case "invalid": return {
676
+ kind: "invalid",
677
+ reason: auth.reason,
678
+ error: auth.error
679
+ };
680
+ default: return auth;
681
+ }
682
+ }
683
+ //#endregion
684
+ export { writeSession as _, checkAal as a, prefetchJwks as c, AUTH_CACHE_HEADERS as d, applyCookieWrites as f, sessionCookieName as g, serializeCookie as h, amrOf as i, rememberVerified as l, readSession as m, toSession as n, authContext as o, parseCookies as p, aalOf as r, clientIp as s, isAnonymousUser as t, resolveAuth as u, refreshSession as v };
@@ -1,30 +1,8 @@
1
- import { p as DbError } from "./result-CqEsbgYs.js";
2
- import { n as AmrEntry, s as Impersonator, t as Aal } from "./mfa-C7MNQ1Ob.js";
3
- import { i as InvalidReason, r as AuthState } from "./resolve-BAqQcwMW.js";
1
+ import { _ as DbError } from "./executor-BunPOO-k.js";
2
+ import { n as Impersonator, o as AuthState, s as InvalidReason } from "./impersonation-BmePsuxz.js";
3
+ import { n as AmrEntry, t as Aal } from "./mfa-Cu96oJdw.js";
4
+ import { n as SessionActor, r as SessionDelegation } from "./actor-DaJjqD5R.js";
4
5
  import { JWTClaims, UserClaims } from "@supabase/server";
5
- //#region src/auth/actor.d.ts
6
- /** One level of an RFC 8693 `act` chain: who acts, and who acted before it. */
7
- interface ActClaim {
8
- readonly sub: string;
9
- readonly act?: ActClaim;
10
- readonly [claim: string]: unknown;
11
- }
12
- /**
13
- * The app acting for the user: the outermost `sub` of an RFC 8693 `act`
14
- * chain (prior actors stay on `chain`), else the OAuth `client_id` of a
15
- * Supabase OAuth server token.
16
- */
17
- interface SessionActor {
18
- readonly id: string;
19
- readonly kind: "oauth-client";
20
- readonly chain?: ActClaim;
21
- }
22
- /** What the user delegated to the actor: the token's OAuth `scope`. */
23
- interface SessionDelegation {
24
- readonly scopes: readonly string[];
25
- readonly chain?: ActClaim;
26
- }
27
- //#endregion
28
6
  //#region src/auth/view.d.ts
29
7
  /**
30
8
  * The verified caller as plain data: no token, no clients. Safe to return
@@ -48,16 +26,29 @@ type AuthSession<C = unknown, P = unknown> = {
48
26
  readonly profile?: P;
49
27
  /** `aal2` once the user verified a second factor in this session. */
50
28
  readonly aal: Aal;
29
+ /**
30
+ * Signed in with `signInAnonymously()` (the `is_anonymous` claim). Guards
31
+ * refuse these users unless `allow` lists `'anonymous'`; `'anon'` means
32
+ * no session and never admits them.
33
+ */
34
+ readonly anonymous: boolean;
51
35
  /** How the user signed in (`password`, `totp`, `sso/saml`, ...). */
52
36
  readonly amr: readonly AmrEntry[];
53
- /** Set when an admin acts as this user (the `act` claim), for a banner. */
37
+ /**
38
+ * Set when an admin acts as this user in a support session or an
39
+ * impersonated session (`act.kind`), for a banner. Matches `actor`.
40
+ */
54
41
  readonly impersonator?: Impersonator;
55
42
  /**
56
- * The OAuth client or agent acting for the user (`client_id`, or the
57
- * outermost `sub` of the `act` chain), as PermDock's `actorOf` reads it.
43
+ * Who acts for the user: an OAuth client or agent (`client_id`, or an
44
+ * `act` chain without `kind`), a support session or an impersonated
45
+ * session, as PermDock's `actorOf` reads it.
58
46
  */
59
47
  readonly actor?: SessionActor;
60
- /** The scopes the user granted `actor`, plus its `act` chain. Set only with `actor`. */
48
+ /**
49
+ * The scopes the user granted an `oauth-client` actor, plus its `act`
50
+ * chain. Never set for a support or impersonated session.
51
+ */
61
52
  readonly delegation?: SessionDelegation;
62
53
  } | {
63
54
  readonly kind: "service";
@@ -76,4 +67,4 @@ type AnonReason = Extract<AuthState, {
76
67
  /** Drops the token from an `AuthState`, leaving only serializable fields. */
77
68
  declare function toSession<C, P>(auth: AuthState<C, P>): AuthSession<C, P>;
78
69
  //#endregion
79
- export { SessionDelegation as a, SessionActor as i, toSession as n, ActClaim as r, AuthSession as t };
70
+ export { toSession as n, AuthSession as t };
@@ -1,7 +1,12 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { N as TableKey, O as Row, n as AnyModels, t as AnyFunctions } from "../types-DONv9SHN.js";
3
- import { o as Result } from "../result-CqEsbgYs.js";
4
- import { t as BetterSupabase } from "../define-CRS2MRV3.js";
2
+ import { P as TableKey, k as Row, n as AnyFunctions, r as AnyModels } from "../types-Dnf_wRDz.js";
3
+ import { S as ErrorMapper, a as AsyncResult, u as Result } from "../executor-BunPOO-k.js";
4
+ import { a as EventHub } from "../events-aIO7vsIk.js";
5
+ import { t as BetterSupabase } from "../define-Bp_BZa5h.js";
6
+ import { g as RequestContext } from "../plugin-o144f322.js";
7
+ import { r as EventSink } from "../index-DOESKG27.js";
8
+ import { i as sqlTransport, n as RpcClient, r as rpcTransport, t as KitTransport } from "../kit-transport-B82k1djG.js";
9
+ import { _ as PublicUrlOptions, a as hmacSigner, b as publicUrl, c as WebhookSecretStore, d as WebhookPolicyError, f as WebhookRequest, g as AllowUrl, h as fetchTransport, i as WebhookSigner, l as sqlSecretStore, m as WebhookTransport, n as StandardWebhooksOptions, o as standardWebhooks, p as WebhookResponse, r as WebhookSignInput, s as RotateSecretOptions, t as HmacSignerOptions, u as FetchTransportOptions, v as ResolveHost, y as isPublicAddress } from "../signers-Cc6r98SW.js";
5
10
  //#region src/webhooks/verify.d.ts
6
11
  interface VerifiedWebhook<T = unknown> {
7
12
  readonly id: string;
@@ -73,6 +78,8 @@ interface AuthHooks {
73
78
  readonly site_url: string;
74
79
  readonly token_new: string;
75
80
  readonly token_hash_new: string;
81
+ /** Auth adds fields over time (`old_email`, `factor_type`, ...). */
82
+ readonly [key: string]: unknown;
76
83
  };
77
84
  };
78
85
  output: Record<never, never>;
@@ -151,4 +158,128 @@ export declare function isDatabaseWebhook(value: unknown): value is DatabaseWebh
151
158
  */
152
159
  export declare function databaseChange<M extends AnyModels, D, F extends AnyFunctions, E, T extends TableKey<M>>(betterSupabase: BetterSupabase<M, D, F, E>, table: T, payload: unknown): DatabaseChange<Row<M, T>> | null;
153
160
  //#endregion
154
- export type { AuthHookError, AuthHookKind, AuthHooks, DatabaseChange, DatabaseWebhookPayload, VerifiedWebhook, VerifyOptions, WebhookInput };
161
+ //#region src/webhooks/outgoing.d.ts
162
+ /** One claimed delivery, as `shouldDeliver`, `transform` and `headers` see it. */
163
+ interface WebhookDelivery {
164
+ readonly id: string;
165
+ readonly endpointId: string;
166
+ readonly url: string;
167
+ readonly type: string;
168
+ readonly payload: unknown;
169
+ /** 1 on the first try. Counted when the delivery is claimed. */
170
+ readonly attempt: number;
171
+ readonly tenant: string | null;
172
+ readonly eventId: string | null;
173
+ readonly runId: string | null;
174
+ readonly createdAt: Temporal.Instant;
175
+ }
176
+ interface RetryPolicy {
177
+ /** Attempts before a delivery is dead-lettered. Defaults to 8. */
178
+ readonly maxAttempts?: number;
179
+ /**
180
+ * Seconds before the next attempt. Defaults to 5 seconds, 5 minutes, 30
181
+ * minutes, 2 hours, 5 hours, then 10 hours, each with full jitter. A
182
+ * receiver's `Retry-After` wins when it asks for longer, up to a day.
183
+ */
184
+ readonly backoff?: (attempt: number) => number;
185
+ /** Statuses worth retrying. Defaults to 408, 429 and 5xx; network errors always retry. */
186
+ readonly retryable?: (status: number) => boolean;
187
+ }
188
+ interface WebhooksOptions {
189
+ /** `sqlTransport(postgres.admin)` for the worker, or the user's connection to manage. */
190
+ readonly transport: KitTransport;
191
+ /** `kits.webhooks-out.schema`. Defaults to `better_supabase`. */
192
+ readonly schema?: string;
193
+ /** Defaults to `fetchTransport({ allowUrl })`. */
194
+ readonly http?: WebhookTransport;
195
+ /** Used by the default `http`. Defaults to `publicUrl()`. */
196
+ readonly allowUrl?: AllowUrl;
197
+ /** Defaults to `standardWebhooks()`. */
198
+ readonly signer?: WebhookSigner;
199
+ /** Defaults to `sqlSecretStore(transport)`. */
200
+ readonly secrets?: WebhookSecretStore;
201
+ readonly retry?: RetryPolicy;
202
+ /** Return `false` (or throw) to cancel a delivery instead of sending it. */
203
+ readonly shouldDeliver?: (delivery: WebhookDelivery) => boolean | Promise<boolean>;
204
+ /**
205
+ * The JSON body. Defaults to the Standard Webhooks envelope,
206
+ * `{ type, timestamp, data }`.
207
+ */
208
+ readonly transform?: (delivery: WebhookDelivery) => unknown;
209
+ /** Extra headers, e.g. an `idempotency-key`. */
210
+ readonly headers?: (delivery: WebhookDelivery) => Readonly<Record<string, string>>;
211
+ /** Characters of the response body kept in the log. Defaults to 2000. */
212
+ readonly responseBodyLimit?: number;
213
+ /** `betterSupabase.events`, for `webhook.*` kit events. */
214
+ readonly events?: EventHub;
215
+ readonly context?: RequestContext;
216
+ readonly errorMappers?: readonly ErrorMapper[];
217
+ }
218
+ interface PublishInput {
219
+ readonly type: string;
220
+ readonly data: unknown;
221
+ readonly tenant?: string;
222
+ /** With an id, publishing it again never queues a second delivery. */
223
+ readonly id?: string;
224
+ }
225
+ interface DispatchInput {
226
+ readonly endpointId: string;
227
+ readonly type: string;
228
+ readonly data: unknown;
229
+ /** An external run id stored with the delivery, e.g. a workflow run. */
230
+ readonly runId?: string;
231
+ readonly eventId?: string;
232
+ }
233
+ interface DeliverWebhooksOptions {
234
+ /** Deliveries per claim. Defaults to 25. */
235
+ readonly batch?: number;
236
+ /**
237
+ * Requests in flight at once. Defaults to 10, so a batch of 25 at the
238
+ * 10-second timeout finishes well inside the lease.
239
+ */
240
+ readonly concurrency?: number;
241
+ /** How long a claim holds a delivery. Defaults to `'2 minutes'`. */
242
+ readonly lease?: string;
243
+ readonly budgetMs?: number;
244
+ }
245
+ interface DeliverWebhooksResult {
246
+ readonly succeeded: number;
247
+ /** Failed attempts that will retry. */
248
+ readonly retrying: number;
249
+ /** Deliveries that ran out of attempts or can't succeed. */
250
+ readonly dead: number;
251
+ readonly canceled: number;
252
+ /** Endpoints disabled after failing for `disableAfter`. */
253
+ readonly disabled: number;
254
+ }
255
+ interface WebhooksRouteOptions extends DeliverWebhooksOptions {
256
+ readonly secret: string | undefined;
257
+ readonly onError?: (error: unknown) => void;
258
+ }
259
+ interface Webhooks {
260
+ /** Queues the event for each subscribed endpoint; returns how many. */
261
+ publish(event: PublishInput): AsyncResult<number>;
262
+ /** Sends to one endpoint outside its subscriptions; returns the delivery id. */
263
+ dispatch(input: DispatchInput): AsyncResult<string>;
264
+ /** Queues a finished delivery again. */
265
+ redeliver(deliveryId: string): AsyncResult<string>;
266
+ /** A new signing secret, returned once. */
267
+ rotateSecret(endpointId: string, options?: RotateSecretOptions): AsyncResult<string>;
268
+ /** Sends due deliveries. Run it from a cron route or a job. */
269
+ deliver(options?: DeliverWebhooksOptions): Promise<DeliverWebhooksResult>;
270
+ /** A `GET`/`POST` handler for Vercel Cron that runs `deliver` behind a bearer secret. */
271
+ deliverRoute(options: WebhooksRouteOptions): (request: Request) => Promise<Response>;
272
+ /**
273
+ * An `EventSink` that publishes CloudEvents, e.g. from the outbox relay.
274
+ * Endpoints subscribe to unprefixed types, so it removes `typePrefix`
275
+ * (`dev.better-supabase` by default, the relay's default) and the dot.
276
+ */
277
+ sink(options?: WebhookSinkOptions): EventSink;
278
+ }
279
+ interface WebhookSinkOptions {
280
+ /** The relay's `typePrefix`. */
281
+ readonly typePrefix?: string;
282
+ }
283
+ export declare function createWebhooks(options: WebhooksOptions): Webhooks;
284
+ //#endregion
285
+ export { type AllowUrl, type AuthHookError, type AuthHookKind, type AuthHooks, type DatabaseChange, type DatabaseWebhookPayload, type DeliverWebhooksOptions, type DeliverWebhooksResult, type DispatchInput, type FetchTransportOptions, type HmacSignerOptions, type KitTransport, type PublicUrlOptions, type PublishInput, type ResolveHost, type RetryPolicy, type RotateSecretOptions, type RpcClient, type StandardWebhooksOptions, type VerifiedWebhook, type VerifyOptions, type WebhookDelivery, type WebhookInput, WebhookPolicyError, type WebhookRequest, type WebhookResponse, type WebhookSecretStore, type WebhookSignInput, type WebhookSigner, type WebhookSinkOptions, type WebhookTransport, type Webhooks, type WebhooksOptions, type WebhooksRouteOptions, fetchTransport, hmacSigner, isPublicAddress, publicUrl, rpcTransport, sqlSecretStore, sqlTransport, standardWebhooks };