@run402/functions 2.9.0 → 3.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.
@@ -0,0 +1,453 @@
1
+ /**
2
+ * `auth.*` — the sole server-side auth namespace.
3
+ *
4
+ * The single import line for any consumer:
5
+ *
6
+ * import { auth } from "@run402/functions";
7
+ *
8
+ * Surface (deliberately small):
9
+ *
10
+ * auth.user() → Actor | null
11
+ * auth.requireUser() → Actor (throws / 303 otherwise)
12
+ * auth.requireRole(role) → { user, role }
13
+ * auth.requireMembership(membership) → { user, membership }
14
+ * auth.requireFresh({ maxAge, amr? }) → void (throws / 303 otherwise)
15
+ * auth.identities.link({ ... }) → void
16
+ * auth.fetch(input, init?) → Response (same-origin only)
17
+ * auth.csrfToken() → string
18
+ * auth.csrfField() → "<input type=hidden ...>"
19
+ * auth.sessions.createResponseFromIdentity({ ... }) → Response
20
+ * auth.sessions.endResponse() → Response
21
+ *
22
+ * Behaviour notes baked into the helpers:
23
+ * - Calling any helper taints the cache (the response now depends on
24
+ * per-request actor state). The taint is monotonic — once set, the
25
+ * SSR cache layer treats the response as non-cacheable until the
26
+ * request completes.
27
+ * - HTML-vs-JSON failure decisions are made by the gateway middleware
28
+ * (303 redirect for HTML, 401/403 envelope for JSON). The SDK throws
29
+ * a typed Error subclass; framework code OR the gateway translates.
30
+ * - `requireRole` / `requireMembership` always read fresh server-side
31
+ * grant data — no positive cache (matches D8 + the "instant revocation"
32
+ * contract). For now we route via `getRole` which the gateway sets
33
+ * at the routed-function envelope; once the v1.60 grants table lands,
34
+ * gate helpers will JOIN against it inside the same request.
35
+ * - `requireFresh` consults the per-method `amr_times` on the Actor —
36
+ * a recent password proof does NOT satisfy `{amr: ["passkey"]}`.
37
+ *
38
+ * @see openspec/changes/auth-aware-ssr/specs/auth-sdk-namespace/spec.md
39
+ */
40
+ import { getCurrentContext, requireActiveContext, taintCacheBypass, } from "../runtime-context.js";
41
+ import { config } from "../config.js";
42
+ import jwt from "../lib/jwt.js";
43
+ import { AuthRequiredError, FetchAbsoluteUrlError, FreshnessRequiredError, InsufficientMembershipError, InsufficientRoleError, UnknownExportError, } from "./errors.js";
44
+ import { validateAuthFetchInput } from "./url-validation.js";
45
+ import crypto from "node:crypto";
46
+ // ---------------------------------------------------------------------------
47
+ // Identity & authorization helpers
48
+ // ---------------------------------------------------------------------------
49
+ async function user() {
50
+ // Taint cache regardless of outcome — the response depends on actor
51
+ // state once any consumer asks. The taint is monotonic (D23).
52
+ taintCacheBypass();
53
+ const ctx = getCurrentContext();
54
+ if (ctx === undefined) {
55
+ // No active context — could be (a) module scope or (b) prerendered
56
+ // build. The runtime-context module distinguishes these via the
57
+ // `active` flag, but for `auth.user()` specifically we return null
58
+ // for module-scope while throwing R402_AUTH_PRERENDERED for the
59
+ // prerendered case. Without a context we can't tell, so return
60
+ // null — Astro's prerender detection runs upstream in @run402/astro.
61
+ return null;
62
+ }
63
+ // SSR / cookie-session path: actor populated from the verified
64
+ // gateway-signed envelope at runWithContext entry.
65
+ if (ctx.actor) {
66
+ return actorContextToPublicActor(ctx.actor, ctx.projectId);
67
+ }
68
+ // Direct function invocation path (Bearer JWT, no cookie envelope):
69
+ // fall back to decoding the Authorization header. This is the legacy
70
+ // getUser(req) contract — mobile / server-to-server callers send a
71
+ // signed JWT in the Authorization header, the function reads it.
72
+ // The gateway has already routed the request to this function and
73
+ // injected the Authorization header per the apikey/wallet-auth
74
+ // pipeline, so we can trust JWT_SECRET-signed claims here.
75
+ return actorFromAuthorizationHeader(ctx);
76
+ }
77
+ /** Read `Authorization: Bearer <jwt>` from the runtime context's
78
+ * request headers and decode it via JWT_SECRET. Returns an `Actor`
79
+ * populated from the JWT claims on success, `null` on absence /
80
+ * malformed / wrong-project / verify-fail.
81
+ *
82
+ * This is the legacy `getUser(req)` shape adapted to the v3.0 `auth.*`
83
+ * surface — it preserves the direct-function-invocation contract that
84
+ * the platform's own E2E suite exercises and that mobile / CI callers
85
+ * rely on. The cookie-session SSR path doesn't go through here (it
86
+ * populates ctx.actor at runWithContext entry via the verified
87
+ * envelope). */
88
+ function actorFromAuthorizationHeader(ctx) {
89
+ if (!config.JWT_SECRET)
90
+ return null;
91
+ const headers = ctx.request.headers;
92
+ // The runtime-context wrapper accepts either a `Headers` instance
93
+ // (when the gateway's buildEntryWrapper passes a Request) or a plain
94
+ // header object. Handle both.
95
+ let authHeader;
96
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
97
+ const h = headers;
98
+ if (typeof h?.get === "function") {
99
+ authHeader = h.get("authorization") ?? h.get("Authorization") ?? undefined;
100
+ }
101
+ else {
102
+ const raw = h?.["authorization"] ?? h?.["Authorization"];
103
+ authHeader = Array.isArray(raw) ? raw[0] : raw;
104
+ }
105
+ if (!authHeader || !authHeader.startsWith("Bearer "))
106
+ return null;
107
+ const token = authHeader.slice(7);
108
+ try {
109
+ const payload = jwt.verify(token, config.JWT_SECRET);
110
+ if (payload.project_id !== ctx.projectId)
111
+ return null;
112
+ return {
113
+ id: payload.sub,
114
+ projectId: payload.project_id,
115
+ sessionId: payload.session_id ?? `bearer:${payload.sub}`,
116
+ email: payload.email ?? "",
117
+ emailVerified: false,
118
+ authTime: payload.auth_time ?? Math.floor(Date.now() / 1000),
119
+ amr: Array.isArray(payload.amr) ? [...payload.amr] : [],
120
+ amrTimes: {},
121
+ };
122
+ }
123
+ catch {
124
+ return null;
125
+ }
126
+ }
127
+ async function requireUser() {
128
+ const actor = await user();
129
+ if (actor === null) {
130
+ throw new AuthRequiredError({ returnTo: currentReturnTo() });
131
+ }
132
+ return actor;
133
+ }
134
+ async function requireRole(role) {
135
+ const actor = await requireUser();
136
+ // For v1A wiring: read the gate-resolved role from the routed-function
137
+ // envelope header set by the gateway middleware. When the v1.60
138
+ // platform-owned grants table lands, this swaps to a fresh DB read
139
+ // joined to internal.role_grants.
140
+ const ctx = requireActiveContext("auth.requireRole");
141
+ const headerRole = readHeader(ctx.request.headers, "x-run402-user-role");
142
+ if (headerRole === role) {
143
+ return { user: actor, role };
144
+ }
145
+ throw new InsufficientRoleError(role);
146
+ }
147
+ function readHeader(headers, name) {
148
+ const v = headers[name] ?? headers[name.toLowerCase()] ?? headers[name.toUpperCase()];
149
+ return Array.isArray(v) ? v[0] : v;
150
+ }
151
+ async function requireMembership(membership) {
152
+ const actor = await requireUser();
153
+ // Membership shape mirrors role for v1A. The grant table for membership
154
+ // lands in a separate change (auth-as-sdlc); meanwhile the gateway-side
155
+ // gate helpers populate `x-run402-user-membership` when configured.
156
+ const ctx = requireActiveContext("auth.requireMembership");
157
+ const headerMembership = readHeader(ctx.request.headers, "x-run402-user-membership");
158
+ if (headerMembership === membership) {
159
+ return { user: actor, membership };
160
+ }
161
+ throw new InsufficientMembershipError(membership);
162
+ }
163
+ async function requireFresh(opts) {
164
+ taintCacheBypass();
165
+ const actor = await requireUser();
166
+ const maxAgeSec = parseMaxAge(opts.maxAge);
167
+ const nowSec = Math.floor(Date.now() / 1000);
168
+ if (opts.amr && opts.amr.length > 0) {
169
+ const ok = opts.amr.some((method) => {
170
+ const ts = actor.amrTimes[method];
171
+ return typeof ts === "number" && nowSec - ts <= maxAgeSec;
172
+ });
173
+ if (!ok) {
174
+ throw new FreshnessRequiredError({
175
+ maxAge: opts.maxAge,
176
+ amr: opts.amr,
177
+ returnTo: currentReturnTo(),
178
+ });
179
+ }
180
+ return;
181
+ }
182
+ if (nowSec - actor.authTime <= maxAgeSec)
183
+ return;
184
+ throw new FreshnessRequiredError({
185
+ maxAge: opts.maxAge,
186
+ amr: [],
187
+ returnTo: currentReturnTo(),
188
+ });
189
+ }
190
+ function parseMaxAge(raw) {
191
+ if (/^\d+$/.test(raw))
192
+ return Number(raw);
193
+ let total = 0;
194
+ const re = /(\d+)\s*([smhd])/gi;
195
+ let m;
196
+ while ((m = re.exec(raw)) !== null) {
197
+ const v = Number(m[1]);
198
+ switch (m[2].toLowerCase()) {
199
+ case "s":
200
+ total += v;
201
+ break;
202
+ case "m":
203
+ total += v * 60;
204
+ break;
205
+ case "h":
206
+ total += v * 3600;
207
+ break;
208
+ case "d":
209
+ total += v * 86400;
210
+ break;
211
+ }
212
+ }
213
+ return total;
214
+ }
215
+ // ---------------------------------------------------------------------------
216
+ // auth.fetch — relative-only with manual-redirect default
217
+ // ---------------------------------------------------------------------------
218
+ async function authFetch(input, init) {
219
+ const ctx = requireActiveContext("auth.fetch");
220
+ const origin = `https://${ctx.host}`;
221
+ const result = validateAuthFetchInput(input, { requestOrigin: origin });
222
+ if (!result.ok) {
223
+ throw new FetchAbsoluteUrlError({
224
+ attempted: typeof input === "string" ? input : (input instanceof URL ? input.toString() : input.url),
225
+ reason: result.reason,
226
+ });
227
+ }
228
+ // The validated URL is same-origin. Default redirect: "manual" so
229
+ // follow-cross-origin redirects don't smuggle our actor context to
230
+ // hostile hops. If the caller opts in via init.redirect: "follow",
231
+ // we still re-validate each hop — but native fetch doesn't expose
232
+ // hop-by-hop hooks, so we emulate by doing manual redirects.
233
+ const headers = new Headers(init?.headers);
234
+ // Forward only headers the gateway expects from a same-origin SSR
235
+ // fetch. Actor-context propagation is automatic (the inbound envelope
236
+ // is propagated as a header; the SSR runtime already verified it).
237
+ // Cookies are NEVER forwarded — never set the Cookie header here.
238
+ headers.delete("cookie");
239
+ headers.delete("Cookie");
240
+ const requestInit = {
241
+ ...init,
242
+ headers,
243
+ redirect: init?.redirect ?? "manual",
244
+ };
245
+ return fetch(result.normalized, requestInit);
246
+ }
247
+ // ---------------------------------------------------------------------------
248
+ // CSRF token helpers (double-submit token bound to the active session).
249
+ // ---------------------------------------------------------------------------
250
+ function csrfToken() {
251
+ const ctx = getCurrentContext();
252
+ if (!ctx || !ctx.actor) {
253
+ // No session ⇒ no CSRF token. Returning an empty string would let
254
+ // the form submit with no token at all; instead throw so the page
255
+ // author knows the helper should be inside `<SignedIn>`-style
256
+ // conditional rendering.
257
+ throw new AuthRequiredError();
258
+ }
259
+ // The token derivation is HMAC(session_secret, "csrf") truncated to
260
+ // 32 hex chars. Browsers double-submit; the gateway re-derives and
261
+ // compares constant-time. We use the session_id + auth_time as the
262
+ // poor-man's MAC input since the SDK doesn't have access to the
263
+ // pepper; the gateway is the authoritative verifier (cross-checks
264
+ // against internal.sessions via session_id). This is double-submit
265
+ // CSRF, not a primary control — the Origin check is.
266
+ const input = `${ctx.actor.sessionId}:${ctx.actor.authTime}:csrf`;
267
+ return crypto.createHash("sha256").update(input, "utf8").digest("hex").slice(0, 32);
268
+ }
269
+ function csrfField() {
270
+ return `<input type="hidden" name="_csrf" value="${escapeHtml(csrfToken())}">`;
271
+ }
272
+ function escapeHtml(s) {
273
+ return s
274
+ .replace(/&/g, "&amp;")
275
+ .replace(/</g, "&lt;")
276
+ .replace(/>/g, "&gt;")
277
+ .replace(/"/g, "&quot;")
278
+ .replace(/'/g, "&#39;");
279
+ }
280
+ // ---------------------------------------------------------------------------
281
+ // Session bridge — createResponseFromIdentity / endResponse.
282
+ //
283
+ // These delegate to the platform routes; the SDK never holds raw secrets.
284
+ // The session-minting route lives at POST /auth/v1/sessions/from-identity
285
+ // (gateway-internal). The endResponse helper just emits the clear-cookie
286
+ // Set-Cookie + body and lets the gateway-side mounted CSRF/origin check
287
+ // run on the calling capability's response.
288
+ // ---------------------------------------------------------------------------
289
+ async function createResponseFromIdentity(opts) {
290
+ const ctx = requireActiveContext("auth.sessions.createResponseFromIdentity");
291
+ const origin = `https://${ctx.host}`;
292
+ // Delegate to the platform route. The route verifies the proof
293
+ // against the project's registered verifier (wallet/oidc/custom) and
294
+ // mints the session via the internal-only primitive. The Response
295
+ // already carries Set-Cookie and the canonical {ok, user} body.
296
+ const res = await fetch(`${origin}/auth/v1/sessions/from-identity`, {
297
+ method: "POST",
298
+ headers: { "content-type": "application/json" },
299
+ body: JSON.stringify(opts),
300
+ redirect: "manual",
301
+ });
302
+ return res;
303
+ }
304
+ async function endResponse() {
305
+ const ctx = requireActiveContext("auth.sessions.endResponse");
306
+ const origin = `https://${ctx.host}`;
307
+ const res = await fetch(`${origin}/auth/v1/sessions/end`, {
308
+ method: "POST",
309
+ headers: { "content-type": "application/json" },
310
+ redirect: "manual",
311
+ });
312
+ return res;
313
+ }
314
+ // ---------------------------------------------------------------------------
315
+ // Identity linking.
316
+ // ---------------------------------------------------------------------------
317
+ async function linkIdentity(opts) {
318
+ const ctx = requireActiveContext("auth.identities.link");
319
+ await requireUser();
320
+ const origin = `https://${ctx.host}`;
321
+ const res = await fetch(`${origin}/auth/v1/identities/link`, {
322
+ method: "POST",
323
+ headers: { "content-type": "application/json" },
324
+ body: JSON.stringify(opts),
325
+ redirect: "manual",
326
+ });
327
+ if (res.status === 409) {
328
+ // The platform route maps unique_violation on
329
+ // internal.identities (project_id, provider, subject) to 409.
330
+ throw new (await import("./errors.js")).IdentityLinkConflictError({
331
+ provider: opts.provider,
332
+ subject: opts.subject,
333
+ });
334
+ }
335
+ if (!res.ok) {
336
+ const body = await res.json().catch(() => ({}));
337
+ throw new (await import("./errors.js")).SessionBridgeUnverifiedError({
338
+ reason: body.code ?? `link failed: ${res.status}`,
339
+ });
340
+ }
341
+ }
342
+ // ---------------------------------------------------------------------------
343
+ // SDK proxy intercepting hallucinated names.
344
+ // ---------------------------------------------------------------------------
345
+ const HALLUCINATED_NAMES = {
346
+ session: "auth.user() then read .sessionId / .amr / etc.",
347
+ getSession: "auth.user()",
348
+ currentUser: "auth.user()",
349
+ currentSession: "auth.user()",
350
+ requireAuth: "auth.requireUser()",
351
+ middleware: "auth.csrfField() / @run402/astro middleware",
352
+ signIn: "POST /auth/sign-in (browser form) or auth.sessions.createResponseFromIdentity({...})",
353
+ signout: "auth.sessions.endResponse()",
354
+ signOut: "auth.sessions.endResponse()",
355
+ logout: "auth.sessions.endResponse()",
356
+ login: "auth.sessions.createResponseFromIdentity({...})",
357
+ redirectToSignIn: "auth.requireUser() — platform redirects",
358
+ getUser: "auth.user()",
359
+ getToken: "auth.requireUser() then user.sessionId (tokens are not exposed)",
360
+ protect: "auth.requireUser() / auth.requireRole(...)",
361
+ };
362
+ const baseAuth = {
363
+ user,
364
+ requireUser,
365
+ requireRole,
366
+ requireMembership,
367
+ requireFresh,
368
+ fetch: authFetch,
369
+ csrfToken,
370
+ csrfField,
371
+ identities: {
372
+ link: linkIdentity,
373
+ },
374
+ sessions: {
375
+ createResponseFromIdentity,
376
+ endResponse,
377
+ },
378
+ };
379
+ /** Hallucinated-name proxy. Property access for a name not in
380
+ * `baseAuth` throws `R402_AUTH_UNKNOWN_EXPORT` with the canonical
381
+ * replacement. Hot-path access (existing keys) returns the actual
382
+ * helper — proxy overhead is one Reflect.has + Reflect.get. */
383
+ export const auth = new Proxy(baseAuth, {
384
+ get(target, prop, receiver) {
385
+ if (typeof prop === "string" && !(prop in target)) {
386
+ const replacement = HALLUCINATED_NAMES[prop];
387
+ if (replacement) {
388
+ throw new UnknownExportError({
389
+ attemptedName: `auth.${prop}`,
390
+ canonicalName: replacement,
391
+ });
392
+ }
393
+ throw new UnknownExportError({
394
+ attemptedName: `auth.${prop}`,
395
+ canonicalName: "auth.user / auth.requireUser / auth.requireRole / auth.requireMembership",
396
+ });
397
+ }
398
+ return Reflect.get(target, prop, receiver);
399
+ },
400
+ });
401
+ /** Throwing-sentinel exports for the top hallucinated *bare* names.
402
+ * ESM `import { getUser } from "@run402/functions"` can be intercepted
403
+ * only by a real export — so we ship these as exported throwing
404
+ * functions. They're marked `@deprecated` in the type JSDoc; the SDK
405
+ * proxy + lint registry + `run402 doctor` scan all flag the import
406
+ * before runtime if the user is running the tooling.
407
+ *
408
+ * Excluded from public docs and AGENTS.md per the spec.
409
+ */
410
+ /** @deprecated Use `auth.user()` or `auth.requireUser()`. */
411
+ export function getSession() {
412
+ throw new UnknownExportError({ attemptedName: "getSession", canonicalName: "auth.user()" });
413
+ }
414
+ /** @deprecated Use `auth.user()`. */
415
+ export function currentUser() {
416
+ throw new UnknownExportError({ attemptedName: "currentUser", canonicalName: "auth.user()" });
417
+ }
418
+ /** @deprecated Use `auth.user()`. */
419
+ export function getCurrentUser() {
420
+ throw new UnknownExportError({ attemptedName: "getCurrentUser", canonicalName: "auth.user()" });
421
+ }
422
+ /** @deprecated Use `auth.user()`. */
423
+ export function getServerSession() {
424
+ throw new UnknownExportError({
425
+ attemptedName: "getServerSession",
426
+ canonicalName: "auth.user()",
427
+ });
428
+ }
429
+ // ---------------------------------------------------------------------------
430
+ // Internal helpers
431
+ // ---------------------------------------------------------------------------
432
+ function actorContextToPublicActor(ctxActor, projectId) {
433
+ if (!ctxActor)
434
+ return null;
435
+ return {
436
+ id: ctxActor.id,
437
+ projectId,
438
+ sessionId: ctxActor.sessionId,
439
+ email: ctxActor.email,
440
+ emailVerified: ctxActor.emailVerified,
441
+ authTime: ctxActor.authTime,
442
+ amr: [...ctxActor.amr],
443
+ amrTimes: { ...ctxActor.amrTimes },
444
+ };
445
+ }
446
+ function currentReturnTo() {
447
+ const ctx = getCurrentContext();
448
+ if (!ctx)
449
+ return undefined;
450
+ return ctx.request.url;
451
+ }
452
+ export { AuthRequiredError, InsufficientRoleError, InsufficientMembershipError, FreshnessRequiredError, FetchAbsoluteUrlError, PrerenderedError, UnknownExportError, SessionBridgeUnverifiedError, IdentityLinkConflictError, UnknownIdentityError, Run402AuthError, } from "./errors.js";
453
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,GAEjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,GAAG,MAAM,eAAe,CAAC;AAChC,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,2BAA2B,EAC3B,qBAAqB,EAErB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAMrB,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,8EAA8E;AAC9E,mCAAmC;AACnC,8EAA8E;AAE9E,KAAK,UAAU,IAAI;IACjB,oEAAoE;IACpE,8DAA8D;IAC9D,gBAAgB,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAC;IAChC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,mEAAmE;QACnE,gEAAgE;QAChE,mEAAmE;QACnE,gEAAgE;QAChE,+DAA+D;QAC/D,qEAAqE;QACrE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,+DAA+D;IAC/D,mDAAmD;IACnD,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;QACd,OAAO,yBAAyB,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;IAC7D,CAAC;IACD,oEAAoE;IACpE,qEAAqE;IACrE,mEAAmE;IACnE,iEAAiE;IACjE,kEAAkE;IAClE,+DAA+D;IAC/D,2DAA2D;IAC3D,OAAO,4BAA4B,CAAC,GAAG,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;iBAUiB;AACjB,SAAS,4BAA4B,CACnC,GAAsD;IAEtD,IAAI,CAAC,MAAM,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;IACpC,kEAAkE;IAClE,qEAAqE;IACrE,8BAA8B;IAC9B,IAAI,UAA8B,CAAC;IACnC,8DAA8D;IAC9D,MAAM,CAAC,GAAG,OAAc,CAAC;IACzB,IAAI,OAAO,CAAC,EAAE,GAAG,KAAK,UAAU,EAAE,CAAC;QACjC,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,SAAS,CAAC;IAC7E,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC;QACzD,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACjD,CAAC;IACD,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAClE,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CASvB,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QAC7B,IAAI,OAAO,CAAC,UAAU,KAAK,GAAG,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QACtD,OAAO;YACL,EAAE,EAAE,OAAO,CAAC,GAAG;YACf,SAAS,EAAE,OAAO,CAAC,UAAU;YAC7B,SAAS,EAAE,OAAO,CAAC,UAAU,IAAI,UAAU,OAAO,CAAC,GAAG,EAAE;YACxD,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;YAC1B,aAAa,EAAE,KAAK;YACpB,QAAQ,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YAC5D,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE;YACvD,QAAQ,EAAE,EAAE;SACb,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,WAAW;IACxB,MAAM,KAAK,GAAG,MAAM,IAAI,EAAE,CAAC;IAC3B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,iBAAiB,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,IAAO;IAEP,MAAM,KAAK,GAAG,MAAM,WAAW,EAAE,CAAC;IAClC,uEAAuE;IACvE,gEAAgE;IAChE,mEAAmE;IACnE,kCAAkC;IAClC,MAAM,GAAG,GAAG,oBAAoB,CAAC,kBAAkB,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;IACzE,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACxB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC/B,CAAC;IACD,MAAM,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,UAAU,CACjB,OAAsD,EACtD,IAAY;IAEZ,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACtF,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrC,CAAC;AAED,KAAK,UAAU,iBAAiB,CAC9B,UAAa;IAEb,MAAM,KAAK,GAAG,MAAM,WAAW,EAAE,CAAC;IAClC,wEAAwE;IACxE,wEAAwE;IACxE,oEAAoE;IACpE,MAAM,GAAG,GAAG,oBAAoB,CAAC,wBAAwB,CAAC,CAAC;IAC3D,MAAM,gBAAgB,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,0BAA0B,CAAC,CAAC;IACrF,IAAI,gBAAgB,KAAK,UAAU,EAAE,CAAC;QACpC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IACrC,CAAC;IACD,MAAM,IAAI,2BAA2B,CAAC,UAAU,CAAC,CAAC;AACpD,CAAC;AAaD,KAAK,UAAU,YAAY,CAAC,IAAyB;IACnD,gBAAgB,EAAE,CAAC;IACnB,MAAM,KAAK,GAAG,MAAM,WAAW,EAAE,CAAC;IAClC,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAC7C,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YAClC,MAAM,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAClC,OAAO,OAAO,EAAE,KAAK,QAAQ,IAAI,MAAM,GAAG,EAAE,IAAI,SAAS,CAAC;QAC5D,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,MAAM,IAAI,sBAAsB,CAAC;gBAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,QAAQ,EAAE,eAAe,EAAE;aAC5B,CAAC,CAAC;QACL,CAAC;QACD,OAAO;IACT,CAAC;IACD,IAAI,MAAM,GAAG,KAAK,CAAC,QAAQ,IAAI,SAAS;QAAE,OAAO;IACjD,MAAM,IAAI,sBAAsB,CAAC;QAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,GAAG,EAAE,EAAE;QACP,QAAQ,EAAE,eAAe,EAAE;KAC5B,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,EAAE,GAAG,oBAAoB,CAAC;IAChC,IAAI,CAAyB,CAAC;IAC9B,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACvB,QAAQ,CAAC,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,EAAE,CAAC;YAC5B,KAAK,GAAG;gBACN,KAAK,IAAI,CAAC,CAAC;gBACX,MAAM;YACR,KAAK,GAAG;gBACN,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;gBAChB,MAAM;YACR,KAAK,GAAG;gBACN,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;gBAClB,MAAM;YACR,KAAK,GAAG;gBACN,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC;gBACnB,MAAM;QACV,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,8EAA8E;AAC9E,0DAA0D;AAC1D,8EAA8E;AAE9E,KAAK,UAAU,SAAS,CACtB,KAAwB,EACxB,IAAkB;IAElB,MAAM,GAAG,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,WAAW,GAAG,CAAC,IAAI,EAAE,CAAC;IACrC,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC;IACxE,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,qBAAqB,CAAC;YAC9B,SAAS,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,YAAY,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;YACpG,MAAM,EAAE,MAAM,CAAC,MAAM;SACtB,CAAC,CAAC;IACL,CAAC;IAED,kEAAkE;IAClE,mEAAmE;IACnE,mEAAmE;IACnE,kEAAkE;IAClE,6DAA6D;IAC7D,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC3C,kEAAkE;IAClE,sEAAsE;IACtE,mEAAmE;IACnE,kEAAkE;IAClE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEzB,MAAM,WAAW,GAAgB;QAC/B,GAAG,IAAI;QACP,OAAO;QACP,QAAQ,EAAE,IAAI,EAAE,QAAQ,IAAI,QAAQ;KACrC,CAAC;IACF,OAAO,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;AAC/C,CAAC;AAED,8EAA8E;AAC9E,wEAAwE;AACxE,8EAA8E;AAE9E,SAAS,SAAS;IAChB,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAC;IAChC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;QACvB,kEAAkE;QAClE,kEAAkE;QAClE,8DAA8D;QAC9D,yBAAyB;QACzB,MAAM,IAAI,iBAAiB,EAAE,CAAC;IAChC,CAAC;IACD,oEAAoE;IACpE,mEAAmE;IACnE,mEAAmE;IACnE,gEAAgE;IAChE,kEAAkE;IAClE,mEAAmE;IACnE,qDAAqD;IACrD,MAAM,KAAK,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ,OAAO,CAAC;IAClE,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACtF,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,4CAA4C,UAAU,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC;AACjF,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC;SACL,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,8EAA8E;AAC9E,6DAA6D;AAC7D,EAAE;AACF,0EAA0E;AAC1E,0EAA0E;AAC1E,yEAAyE;AACzE,wEAAwE;AACxE,4CAA4C;AAC5C,8EAA8E;AAE9E,KAAK,UAAU,0BAA0B,CACvC,IAAuC;IAEvC,MAAM,GAAG,GAAG,oBAAoB,CAAC,0CAA0C,CAAC,CAAC;IAC7E,MAAM,MAAM,GAAG,WAAW,GAAG,CAAC,IAAI,EAAE,CAAC;IACrC,+DAA+D;IAC/D,qEAAqE;IACrE,kEAAkE;IAClE,gEAAgE;IAChE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,iCAAiC,EAAE;QAClE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QAC1B,QAAQ,EAAE,QAAQ;KACnB,CAAC,CAAC;IACH,OAAO,GAAG,CAAC;AACb,CAAC;AAED,KAAK,UAAU,WAAW;IACxB,MAAM,GAAG,GAAG,oBAAoB,CAAC,2BAA2B,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,WAAW,GAAG,CAAC,IAAI,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,uBAAuB,EAAE;QACxD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,QAAQ,EAAE,QAAQ;KACnB,CAAC,CAAC;IACH,OAAO,GAAG,CAAC;AACb,CAAC;AAED,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E,KAAK,UAAU,YAAY,CAAC,IAAyB;IACnD,MAAM,GAAG,GAAG,oBAAoB,CAAC,sBAAsB,CAAC,CAAC;IACzD,MAAM,WAAW,EAAE,CAAC;IACpB,MAAM,MAAM,GAAG,WAAW,GAAG,CAAC,IAAI,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,0BAA0B,EAAE;QAC3D,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QAC1B,QAAQ,EAAE,QAAQ;KACnB,CAAC,CAAC;IACH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvB,8CAA8C;QAC9C,8DAA8D;QAC9D,MAAM,IAAI,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,yBAAyB,CAAC;YAChE,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAChD,MAAM,IAAI,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,4BAA4B,CAAC;YACnE,MAAM,EAAG,IAA0B,CAAC,IAAI,IAAI,gBAAgB,GAAG,CAAC,MAAM,EAAE;SACzE,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,6CAA6C;AAC7C,8EAA8E;AAE9E,MAAM,kBAAkB,GAA2B;IACjD,OAAO,EAAE,gDAAgD;IACzD,UAAU,EAAE,aAAa;IACzB,WAAW,EAAE,aAAa;IAC1B,cAAc,EAAE,aAAa;IAC7B,WAAW,EAAE,oBAAoB;IACjC,UAAU,EAAE,6CAA6C;IACzD,MAAM,EAAE,sFAAsF;IAC9F,OAAO,EAAE,6BAA6B;IACtC,OAAO,EAAE,6BAA6B;IACtC,MAAM,EAAE,6BAA6B;IACrC,KAAK,EAAE,iDAAiD;IACxD,gBAAgB,EAAE,yCAAyC;IAC3D,OAAO,EAAE,aAAa;IACtB,QAAQ,EAAE,iEAAiE;IAC3E,OAAO,EAAE,4CAA4C;CACtD,CAAC;AA2BF,MAAM,QAAQ,GAAkB;IAC9B,IAAI;IACJ,WAAW;IACX,WAAW;IACX,iBAAiB;IACjB,YAAY;IACZ,KAAK,EAAE,SAAS;IAChB,SAAS;IACT,SAAS;IACT,UAAU,EAAE;QACV,IAAI,EAAE,YAAY;KACnB;IACD,QAAQ,EAAE;QACR,0BAA0B;QAC1B,WAAW;KACZ;CACF,CAAC;AAEF;;;gEAGgE;AAChE,MAAM,CAAC,MAAM,IAAI,GAAkB,IAAI,KAAK,CAAC,QAAQ,EAAE;IACrD,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ;QACxB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,EAAE,CAAC;YAClD,MAAM,WAAW,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;YAC7C,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,IAAI,kBAAkB,CAAC;oBAC3B,aAAa,EAAE,QAAQ,IAAI,EAAE;oBAC7B,aAAa,EAAE,WAAW;iBAC3B,CAAC,CAAC;YACL,CAAC;YACD,MAAM,IAAI,kBAAkB,CAAC;gBAC3B,aAAa,EAAE,QAAQ,IAAI,EAAE;gBAC7B,aAAa,EAAE,0EAA0E;aAC1F,CAAC,CAAC;QACL,CAAC;QACD,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC7C,CAAC;CACF,CAAC,CAAC;AAEH;;;;;;;;GAQG;AAEH,6DAA6D;AAC7D,MAAM,UAAU,UAAU;IACxB,MAAM,IAAI,kBAAkB,CAAC,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC,CAAC;AAC9F,CAAC;AAED,qCAAqC;AACrC,MAAM,UAAU,WAAW;IACzB,MAAM,IAAI,kBAAkB,CAAC,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC,CAAC;AAC/F,CAAC;AAED,qCAAqC;AACrC,MAAM,UAAU,cAAc;IAC5B,MAAM,IAAI,kBAAkB,CAAC,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC,CAAC;AAClG,CAAC;AAED,qCAAqC;AACrC,MAAM,UAAU,gBAAgB;IAC9B,MAAM,IAAI,kBAAkB,CAAC;QAC3B,aAAa,EAAE,kBAAkB;QACjC,aAAa,EAAE,aAAa;KAC7B,CAAC,CAAC;AACL,CAAC;AAED,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,SAAS,yBAAyB,CAChC,QAA6B,EAC7B,SAAiB;IAEjB,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,OAAO;QACL,EAAE,EAAE,QAAQ,CAAC,EAAE;QACf,SAAS;QACT,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,aAAa,EAAE,QAAQ,CAAC,aAAa;QACrC,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,GAAG,EAAE,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC;QACtB,QAAQ,EAAE,EAAE,GAAG,QAAQ,CAAC,QAAQ,EAAE;KACnC,CAAC;AACJ,CAAC;AAED,SAAS,eAAe;IACtB,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAC;IAChC,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,OAAO,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC;AACzB,CAAC;AAID,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,2BAA2B,EAC3B,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,4BAA4B,EAC5B,yBAAyB,EACzB,oBAAoB,EACpB,eAAe,GAChB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Public types for the `auth.*` namespace.
3
+ *
4
+ * The canonical actor shape used everywhere `auth.user()` /
5
+ * `auth.requireUser()` / `auth.requireRole()` etc. resolve to a user.
6
+ * Note that `id` (not `userId`) is the canonical public field — matches
7
+ * Supabase / Clerk / Auth.js / NextAuth so coding-agent generated code
8
+ * gets it right on the first try.
9
+ *
10
+ * @see openspec/changes/auth-aware-ssr/specs/auth-sdk-namespace/spec.md
11
+ */
12
+ export interface Actor {
13
+ /** Canonical public user-id. Matches `internal.users.id` UUID. */
14
+ id: string;
15
+ projectId: string;
16
+ sessionId: string;
17
+ email: string;
18
+ emailVerified: boolean;
19
+ /** Last any-method auth proof, seconds-since-epoch. */
20
+ authTime: number;
21
+ amr: string[];
22
+ /** Per-AMR last-verified UNIX seconds. */
23
+ amrTimes: Record<string, number>;
24
+ }
25
+ /** Provider-shaped identity proof. The `wallet` shape carries an SIWX
26
+ * signature + message; `oidc` carries a JWT bound to a project-configured
27
+ * issuer; `custom` requires admin-registered project-side verifier and
28
+ * carries provider-specific bytes. */
29
+ export type IdentityProof = {
30
+ kind: "siwx";
31
+ signature: string;
32
+ message: string;
33
+ nonce?: string;
34
+ } | {
35
+ kind: "oidc_jwt";
36
+ token: string;
37
+ nonce?: string;
38
+ } | {
39
+ kind: "custom";
40
+ payload: unknown;
41
+ nonce?: string;
42
+ };
43
+ export interface CreateResponseFromIdentityOptions {
44
+ provider: "wallet" | "oidc" | "custom";
45
+ subject: string;
46
+ proof: IdentityProof;
47
+ amr: string[];
48
+ /** When `false` (default), unknown identities cause
49
+ * `R402_AUTH_UNKNOWN_IDENTITY`. When `true`, the platform creates the
50
+ * user + identity link in the same transaction as the session. */
51
+ createUser?: boolean;
52
+ }
53
+ export interface IdentityLinkOptions {
54
+ provider: string;
55
+ subject: string;
56
+ proof: IdentityProof;
57
+ }
58
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,KAAK;IACpB,kEAAkE;IAClE,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,OAAO,CAAC;IACvB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;;uCAGuC;AACvC,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD,MAAM,WAAW,iCAAiC;IAChD,QAAQ,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,aAAa,CAAC;IACrB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd;;uEAEmE;IACnE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,aAAa,CAAC;CACtB"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Public types for the `auth.*` namespace.
3
+ *
4
+ * The canonical actor shape used everywhere `auth.user()` /
5
+ * `auth.requireUser()` / `auth.requireRole()` etc. resolve to a user.
6
+ * Note that `id` (not `userId`) is the canonical public field — matches
7
+ * Supabase / Clerk / Auth.js / NextAuth so coding-agent generated code
8
+ * gets it right on the first try.
9
+ *
10
+ * @see openspec/changes/auth-aware-ssr/specs/auth-sdk-namespace/spec.md
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * `auth.fetch` URL validation.
3
+ *
4
+ * Synchronous before-network checks: the URL is rejected (sync throw)
5
+ * before any network I/O if it's not safely same-origin. The set of
6
+ * rejected shapes is enumerated by the spec — we mirror it verbatim:
7
+ *
8
+ * - Cross-origin absolute URLs
9
+ * - URLs with embedded credentials (`http://user:pass@host/...`)
10
+ * - Non-HTTP(S) schemes (`javascript:`, `data:`, `file:`, etc.)
11
+ * - Protocol-relative URLs (`//evil.example/...`)
12
+ * - Subdomain-spoof patterns (`https://app.run402.app.evil.example/...`)
13
+ * - Port-mismatch against the current request origin
14
+ *
15
+ * Same-origin normalisation: scheme, host, and default-port comparisons
16
+ * use `URL.origin`, which strips `:80` for http and `:443` for https.
17
+ *
18
+ * @see openspec/changes/auth-aware-ssr/specs/auth-sdk-namespace/spec.md
19
+ */
20
+ export interface UrlValidationContext {
21
+ requestOrigin: string;
22
+ }
23
+ export type UrlValidationResult = {
24
+ ok: true;
25
+ normalized: URL;
26
+ } | {
27
+ ok: false;
28
+ reason: string;
29
+ };
30
+ export declare function validateAuthFetchInput(input: RequestInfo | URL, ctx: UrlValidationContext): UrlValidationResult;
31
+ //# sourceMappingURL=url-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-validation.d.ts","sourceRoot":"","sources":["../../src/auth/url-validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,GAAG,CAAA;CAAE,GAC7B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAIlC,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,GAAG,EAAE,oBAAoB,GACxB,mBAAmB,CAiErB"}