@soulcraft/sdk 2.8.0 → 3.0.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 (52) hide show
  1. package/dist/modules/auth/products.d.ts +1 -1
  2. package/dist/modules/auth/products.js +1 -1
  3. package/dist/modules/auth/request-backchannel.d.ts +39 -6
  4. package/dist/modules/auth/request-backchannel.d.ts.map +1 -1
  5. package/dist/modules/auth/request-backchannel.js +15 -5
  6. package/dist/modules/auth/request-backchannel.js.map +1 -1
  7. package/dist/modules/auth/request-middleware.d.ts +267 -24
  8. package/dist/modules/auth/request-middleware.d.ts.map +1 -1
  9. package/dist/modules/auth/request-middleware.js +264 -23
  10. package/dist/modules/auth/request-middleware.js.map +1 -1
  11. package/dist/modules/auth/service-token.d.ts +8 -7
  12. package/dist/modules/auth/service-token.d.ts.map +1 -1
  13. package/dist/modules/auth/service-token.js +8 -7
  14. package/dist/modules/auth/service-token.js.map +1 -1
  15. package/dist/modules/auth/sveltekit.d.ts +1 -1
  16. package/dist/modules/auth/sveltekit.d.ts.map +1 -1
  17. package/dist/modules/auth/sveltekit.js +1 -1
  18. package/dist/modules/auth/sveltekit.js.map +1 -1
  19. package/dist/namespaces.d.ts +1 -1
  20. package/dist/server/handlers/export.js +1 -1
  21. package/dist/server/handlers/export.js.map +1 -1
  22. package/dist/server/handlers/workspace.d.ts +1 -1
  23. package/dist/server/handlers/workspace.d.ts.map +1 -1
  24. package/dist/server/handlers/workspace.js +3 -4
  25. package/dist/server/handlers/workspace.js.map +1 -1
  26. package/dist/server/index.d.ts +5 -14
  27. package/dist/server/index.d.ts.map +1 -1
  28. package/dist/server/index.js +3 -11
  29. package/dist/server/index.js.map +1 -1
  30. package/dist/server/namespace-router.d.ts +1 -1
  31. package/dist/server/namespace-router.js +1 -1
  32. package/dist/server/rpc-handler.d.ts +27 -20
  33. package/dist/server/rpc-handler.d.ts.map +1 -1
  34. package/dist/server/rpc-handler.js +20 -20
  35. package/dist/server/rpc-handler.js.map +1 -1
  36. package/docs/ADR-001-sdk-design.md +3 -3
  37. package/docs/ADR-004-product-registry.md +1 -1
  38. package/docs/ADR-005-hall-integration.md +1 -1
  39. package/docs/ADR-006-rpc-cache.md +2 -2
  40. package/docs/IMPLEMENTATION-PLAN.md +7 -7
  41. package/docs/KIT-APP-GUIDE.md +100 -99
  42. package/docs/USAGE.md +30 -40
  43. package/docs/kit-sdk-guide.md +59 -60
  44. package/package.json +1 -1
  45. package/dist/modules/auth/backchannel.d.ts +0 -98
  46. package/dist/modules/auth/backchannel.d.ts.map +0 -1
  47. package/dist/modules/auth/backchannel.js +0 -171
  48. package/dist/modules/auth/backchannel.js.map +0 -1
  49. package/dist/modules/auth/middleware.d.ts +0 -412
  50. package/dist/modules/auth/middleware.d.ts.map +0 -1
  51. package/dist/modules/auth/middleware.js +0 -586
  52. package/dist/modules/auth/middleware.js.map +0 -1
@@ -1,586 +0,0 @@
1
- /**
2
- * @module modules/auth/middleware
3
- * @description Hono auth middleware factories, remote session verification, and
4
- * dev/guest session utilities for Soulcraft product backends.
5
- *
6
- * ## Session verification strategies
7
- *
8
- * All products share the same `createAuthMiddleware` factory, but each product
9
- * selects the right session verifier for its deployment context:
10
- *
11
- * ```
12
- * Production (all products):
13
- * createRemoteSessionVerifier({ idpUrl: 'https://auth.soulcraft.com' })
14
- *
15
- * Development (all products):
16
- * createDevSessionVerifier({ role: 'owner' }) // auto-login, no OAuth needed
17
- *
18
- * Workshop standalone (legacy / local OAuth):
19
- * createAuthMiddleware(betterAuthInstance) // BetterAuthLike overload
20
- * ```
21
- *
22
- * ## Dev and guest endpoint factories
23
- *
24
- * - `createDevLoginHandler` — mounts a `/api/dev/login` endpoint for role-switching
25
- * during development. Issues a signed dev session cookie. No-ops in production.
26
- * - `createGuestSessionHandler` — mounts a `/api/guest/session` endpoint so Venue
27
- * visitors can obtain a guest session (platformRole `'guest'`) for anonymous
28
- * browse and booking flows, before they create an account.
29
- *
30
- * @example Production setup (Venue / Academy)
31
- * ```typescript
32
- * import { createAuthMiddleware, createRemoteSessionVerifier } from '@soulcraft/sdk/server'
33
- *
34
- * const verifySession = createRemoteSessionVerifier({ idpUrl: process.env.SOULCRAFT_IDP_URL! })
35
- * const { requireAuth, optionalAuth } = createAuthMiddleware(verifySession)
36
- *
37
- * app.get('/api/bookings', requireAuth, async (c) => {
38
- * const user = c.get('user')! // SoulcraftSessionUser
39
- * })
40
- * ```
41
- */
42
- import { LRUCache } from 'lru-cache';
43
- import { computeEmailHash } from './config.js';
44
- // ─────────────────────────────────────────────────────────────────────────────
45
- // Types
46
- // ─────────────────────────────────────────────────────────────────────────────
47
- /** The Hono context variable key where the resolved user is stored. */
48
- export const AUTH_USER_KEY = 'user';
49
- // ─────────────────────────────────────────────────────────────────────────────
50
- // Shared internal helpers
51
- // ─────────────────────────────────────────────────────────────────────────────
52
- /** Resolve a raw user record from a better-auth session into a `SoulcraftSessionUser`. */
53
- function _resolveUser(raw) {
54
- const email = String(raw['email'] ?? '');
55
- const emailHash = raw['emailHash']
56
- ? String(raw['emailHash'])
57
- : computeEmailHash(email);
58
- return {
59
- id: String(raw['id'] ?? ''),
60
- email,
61
- name: String(raw['name'] ?? ''),
62
- image: raw['image'] ?? null,
63
- platformRole: raw['platformRole'] ?? 'creator',
64
- emailHash,
65
- ...(raw['handle'] ? { handle: String(raw['handle']) } : {}),
66
- };
67
- }
68
- /** Parse a simple `name=value` cookie from a raw cookie header string. */
69
- function _parseCookie(cookieHeader, name) {
70
- for (const part of cookieHeader.split(';')) {
71
- const [k, ...rest] = part.trim().split('=');
72
- if (k?.trim() === name)
73
- return rest.join('=').trim();
74
- }
75
- return undefined;
76
- }
77
- /** Encode a dev/guest session payload as a compact JSON+base64url string (unsigned). */
78
- function _encodeSessionCookie(session) {
79
- return Buffer.from(JSON.stringify(session)).toString('base64url');
80
- }
81
- /** Decode a session payload encoded by `_encodeSessionCookie`. Returns null on any error. */
82
- function _decodeSessionCookie(value) {
83
- try {
84
- const raw = JSON.parse(Buffer.from(value, 'base64url').toString('utf-8'));
85
- if (!raw.user || !raw.sessionId || !raw.expiresAt)
86
- return null;
87
- if (raw.expiresAt < Date.now())
88
- return null;
89
- return raw;
90
- }
91
- catch {
92
- return null;
93
- }
94
- }
95
- // ─────────────────────────────────────────────────────────────────────────────
96
- // createAuthMiddleware
97
- // ─────────────────────────────────────────────────────────────────────────────
98
- /**
99
- * Creates Hono auth middleware from a `SessionVerifier` function or a `BetterAuthLike`
100
- * instance.
101
- *
102
- * **Preferred form (all products in OIDC-client mode):**
103
- * Pass a `SessionVerifier` returned by `createRemoteSessionVerifier` or
104
- * `createDevSessionVerifier`. The middleware reads the request cookie header and
105
- * passes it to the verifier.
106
- *
107
- * **Legacy form (Workshop standalone mode):**
108
- * Pass a `better-auth` instance directly. The middleware calls `auth.api.getSession`.
109
- * In non-production environments and when `devAutoLogin` is enabled, a synthetic dev
110
- * user is injected on failed lookups so local dev works without OAuth.
111
- *
112
- * Both forms return identical `{ requireAuth, optionalAuth }` middleware.
113
- *
114
- * @param authOrVerifier - A `better-auth` instance or a `SessionVerifier` function.
115
- * @param options - Optional middleware configuration (only applies to `BetterAuthLike` form).
116
- * @returns Middleware pair: `{ requireAuth, optionalAuth }`.
117
- *
118
- * @example Verifier form (Venue / Academy / Workshop in OIDC mode)
119
- * ```typescript
120
- * const verifySession = createRemoteSessionVerifier({ idpUrl: process.env.SOULCRAFT_IDP_URL! })
121
- * const { requireAuth } = createAuthMiddleware(verifySession)
122
- * ```
123
- *
124
- * @deprecated Use `createRequestAuthMiddleware` from `request-middleware.ts` instead.
125
- * The Hono-specific middleware will be removed in a future major version.
126
- *
127
- * @example BetterAuth form (Workshop dev standalone)
128
- * ```typescript
129
- * import { auth } from './better-auth.js'
130
- * const { requireAuth } = createAuthMiddleware(auth)
131
- * ```
132
- */
133
- export function createAuthMiddleware(authOrVerifier, options = {}) {
134
- const isVerifier = typeof authOrVerifier === 'function';
135
- if (isVerifier) {
136
- const verify = authOrVerifier;
137
- const requireAuth = async (c, next) => {
138
- const cookieHeader = c.req.header('cookie') ?? '';
139
- const session = await verify(cookieHeader);
140
- if (!session)
141
- return c.json({ error: 'Authentication required' }, 401);
142
- c.set(AUTH_USER_KEY, session.user);
143
- await next();
144
- return;
145
- };
146
- const optionalAuth = async (c, next) => {
147
- const cookieHeader = c.req.header('cookie') ?? '';
148
- const session = await verify(cookieHeader);
149
- c.set(AUTH_USER_KEY, session?.user ?? null);
150
- await next();
151
- };
152
- return { requireAuth, optionalAuth };
153
- }
154
- // BetterAuthLike form (Workshop standalone)
155
- const auth = authOrVerifier;
156
- const devAutoLogin = options.devAutoLogin ?? true;
157
- const isDev = process.env['NODE_ENV'] !== 'production';
158
- const DEV_USER = {
159
- id: 'dev-user-001',
160
- email: 'dev@localhost',
161
- name: 'Dev User',
162
- image: null,
163
- emailHash: computeEmailHash('dev@localhost'),
164
- platformRole: 'creator',
165
- handle: 'dev',
166
- };
167
- const requireAuth = async (c, next) => {
168
- if (isDev && devAutoLogin) {
169
- if (!c.get(AUTH_USER_KEY))
170
- c.set(AUTH_USER_KEY, DEV_USER);
171
- await next();
172
- return;
173
- }
174
- const session = await auth.api.getSession({ headers: c.req.raw.headers });
175
- if (!session?.user) {
176
- return c.json({ error: 'Authentication required' }, 401);
177
- }
178
- c.set(AUTH_USER_KEY, _resolveUser(session.user));
179
- await next();
180
- return;
181
- };
182
- const optionalAuth = async (c, next) => {
183
- if (isDev && devAutoLogin) {
184
- if (!c.get(AUTH_USER_KEY))
185
- c.set(AUTH_USER_KEY, DEV_USER);
186
- await next();
187
- return;
188
- }
189
- const session = await auth.api.getSession({ headers: c.req.raw.headers });
190
- if (session?.user) {
191
- c.set(AUTH_USER_KEY, _resolveUser(session.user));
192
- }
193
- else {
194
- c.set(AUTH_USER_KEY, null);
195
- }
196
- await next();
197
- };
198
- return { requireAuth, optionalAuth };
199
- }
200
- // ─────────────────────────────────────────────────────────────────────────────
201
- // createRemoteSessionVerifier
202
- // ─────────────────────────────────────────────────────────────────────────────
203
- /**
204
- * Creates a cached remote session verifier that proxies session lookups to
205
- * the central IdP at `auth.soulcraft.com`.
206
- *
207
- * Used by products that operate as OIDC clients (Venue, Academy, and Workshop
208
- * in production). Caches successful lookups in an LRU cache to avoid per-request
209
- * HTTP round-trips to the IdP.
210
- *
211
- * The verifier sends the cookie header to the IdP's `/api/auth/get-session` endpoint
212
- * and returns the resolved `SoulcraftSession` or `null` if the session is invalid.
213
- *
214
- * Pass the returned function directly to `createAuthMiddleware`:
215
- * ```typescript
216
- * const verifySession = createRemoteSessionVerifier({ idpUrl: process.env.SOULCRAFT_IDP_URL! })
217
- * const { requireAuth } = createAuthMiddleware(verifySession)
218
- * ```
219
- *
220
- * @param options - IdP URL, cache TTL, and max cache size.
221
- * @returns A `SessionVerifier` — async function that accepts a cookie header string.
222
- *
223
- * @example
224
- * ```typescript
225
- * const verifySession = createRemoteSessionVerifier({
226
- * idpUrl: 'https://auth.soulcraft.com',
227
- * cacheTtlMs: 30_000,
228
- * })
229
- *
230
- * const session = await verifySession(c.req.header('cookie') ?? '')
231
- * if (!session) return c.json({ error: 'Unauthorized' }, 401)
232
- * ```
233
- */
234
- export function createRemoteSessionVerifier(options) {
235
- const cacheTtl = options.cacheTtlMs ?? 30_000;
236
- const cacheMax = options.cacheMax ?? 500;
237
- const sessionUrl = `${options.idpUrl.replace(/\/$/, '')}/api/auth/get-session`;
238
- const cache = new LRUCache({
239
- max: cacheMax,
240
- ttl: cacheTtl,
241
- });
242
- return async function verifyRemoteSession(cookieHeader) {
243
- if (!cookieHeader)
244
- return null;
245
- // Use cookie header as cache key — it contains the session token
246
- const cached = cache.get(cookieHeader);
247
- if (cached !== undefined)
248
- return cached;
249
- let response;
250
- try {
251
- response = await fetch(sessionUrl, {
252
- headers: { cookie: cookieHeader },
253
- credentials: 'include',
254
- });
255
- }
256
- catch {
257
- return null;
258
- }
259
- if (!response.ok)
260
- return null;
261
- let data;
262
- try {
263
- data = await response.json();
264
- }
265
- catch {
266
- return null;
267
- }
268
- // `get-session` returns the JSON literal `null` when no session is active.
269
- // The fetch succeeds (200 OK) and `response.json()` parses it without error,
270
- // but `data` is null — not an object. Guard before any property access.
271
- if (!data || typeof data !== 'object')
272
- return null;
273
- const rawUser = data['user'];
274
- const rawSession = data['session'];
275
- if (!rawUser || !rawSession)
276
- return null;
277
- const email = String(rawUser['email'] ?? '');
278
- const session = {
279
- user: {
280
- id: String(rawUser['id'] ?? ''),
281
- email,
282
- name: String(rawUser['name'] ?? ''),
283
- image: rawUser['image'] ?? null,
284
- platformRole: rawUser['platformRole'] ?? 'creator',
285
- emailHash: rawUser['emailHash'] ? String(rawUser['emailHash']) : computeEmailHash(email),
286
- ...(rawUser['handle'] ? { handle: String(rawUser['handle']) } : {}),
287
- },
288
- sessionId: String(rawSession['id'] ?? ''),
289
- expiresAt: Number(rawSession['expiresAt'] ?? 0),
290
- };
291
- cache.set(cookieHeader, session);
292
- return session;
293
- };
294
- }
295
- // ─────────────────────────────────────────────────────────────────────────────
296
- // createDevSessionVerifier
297
- // ─────────────────────────────────────────────────────────────────────────────
298
- /**
299
- * Creates a session verifier that always resolves to a synthetic dev session.
300
- *
301
- * Intended for products that run as OIDC clients but need local development auth
302
- * without OAuth, network calls, SQLite, or real cookies. The returned verifier always
303
- * succeeds — any request resolves to the configured synthetic user.
304
- *
305
- * Designed as a drop-in replacement for `createRemoteSessionVerifier` in local dev:
306
- *
307
- * ```typescript
308
- * const verifySession = process.env.SOULCRAFT_IDP_URL
309
- * ? createRemoteSessionVerifier({ idpUrl: process.env.SOULCRAFT_IDP_URL })
310
- * : createDevSessionVerifier({ role: 'owner' })
311
- *
312
- * const { requireAuth } = createAuthMiddleware(verifySession)
313
- * ```
314
- *
315
- * **Never use in production.** The verifier performs no validation whatsoever.
316
- *
317
- * @param options - Optional synthetic user configuration.
318
- * @returns A `SessionVerifier` with the same signature as `createRemoteSessionVerifier`.
319
- *
320
- * @example
321
- * ```typescript
322
- * const verifySession = process.env.SOULCRAFT_IDP_URL
323
- * ? createRemoteSessionVerifier({ idpUrl: process.env.SOULCRAFT_IDP_URL })
324
- * : createDevSessionVerifier({ role: 'owner' })
325
- *
326
- * export const handle = async ({ event, resolve }) => {
327
- * const session = await verifySession(event.request.headers.get('cookie') ?? '')
328
- * event.locals.session = session
329
- * return resolve(event)
330
- * }
331
- * ```
332
- */
333
- export function createDevSessionVerifier(options = {}) {
334
- const role = options.role ?? 'owner';
335
- const email = options.email ?? 'dev@soulcraft.com';
336
- const name = options.name ?? 'Dev User';
337
- const session = {
338
- user: {
339
- id: 'dev-user-001',
340
- email,
341
- name,
342
- image: null,
343
- platformRole: role,
344
- emailHash: computeEmailHash(email),
345
- handle: 'dev',
346
- },
347
- sessionId: 'dev-session-001',
348
- expiresAt: Date.now() + 30 * 24 * 60 * 60 * 1000,
349
- };
350
- return async function verifyDevSession() {
351
- return session;
352
- };
353
- }
354
- // ─────────────────────────────────────────────────────────────────────────────
355
- // createDevLoginHandler
356
- // ─────────────────────────────────────────────────────────────────────────────
357
- /**
358
- * Creates a Hono request handler for a dev login endpoint.
359
- *
360
- * Mount at `/api/dev/login` to get a role-switching endpoint for local
361
- * development. Accepts `?role=<platformRole>` and optional `?email=` / `?name=`
362
- * query params. Issues a signed base64url session cookie that `createAuthMiddleware`
363
- * (when used with a `SessionVerifier` that reads dev cookies) can resolve.
364
- *
365
- * **Guards against production use:** the handler returns HTTP 404 when
366
- * `NODE_ENV === 'production'` — it is safe to leave mounted in all environments.
367
- *
368
- * @param options - Allowed roles, cookie name, and max-age.
369
- * @returns A Hono-compatible request handler `(c: HonoContext) => Response`.
370
- *
371
- * @deprecated Use `createRequestDevLoginHandler` from `request-middleware.ts` instead.
372
- * The Hono-specific handler will be removed in a future major version.
373
- *
374
- * @example
375
- * ```typescript
376
- * import { createDevLoginHandler } from '@soulcraft/sdk/server'
377
- *
378
- * // In your Hono server setup:
379
- * app.get('/api/dev/login', createDevLoginHandler({ allowedRoles: ['owner', 'staff', 'customer'] }))
380
- *
381
- * // Usage: GET /api/dev/login?role=staff → sets cookie + redirects to /
382
- * ```
383
- */
384
- export function createDevLoginHandler(options = {}) {
385
- const DEFAULT_ROLES = [
386
- 'creator', 'viewer', 'customer', 'staff', 'manager', 'owner', 'learner', 'instructor',
387
- ];
388
- const allowedRoles = options.allowedRoles ?? DEFAULT_ROLES;
389
- const cookieName = options.cookieName ?? 'soulcraft_dev_session';
390
- const maxAgeSeconds = options.maxAgeSeconds ?? 86_400;
391
- return function devLoginHandler(c) {
392
- if (process.env['NODE_ENV'] === 'production') {
393
- return c.json({ error: 'Not found' }, 404);
394
- }
395
- const role = c.req.query('role');
396
- if (!role || !allowedRoles.includes(role)) {
397
- return c.json({
398
- error: `Invalid role. Allowed: ${allowedRoles.join(', ')}`,
399
- allowedRoles,
400
- }, 400);
401
- }
402
- const email = c.req.query('email') ?? `dev-${role}@soulcraft.com`;
403
- const name = c.req.query('name') ?? `Dev ${role.charAt(0).toUpperCase() + role.slice(1)}`;
404
- const redirect = c.req.query('redirect') ?? '/';
405
- const session = {
406
- user: {
407
- id: `dev-user-${role}`,
408
- email,
409
- name,
410
- image: null,
411
- platformRole: role,
412
- emailHash: computeEmailHash(email),
413
- },
414
- sessionId: `dev-session-${Date.now()}`,
415
- expiresAt: Date.now() + maxAgeSeconds * 1000,
416
- };
417
- const cookieValue = _encodeSessionCookie(session);
418
- const cookieHeader = [
419
- `${cookieName}=${cookieValue}`,
420
- `Path=/`,
421
- `HttpOnly`,
422
- `SameSite=Lax`,
423
- `Max-Age=${maxAgeSeconds}`,
424
- ].join('; ');
425
- const response = new Response(null, {
426
- status: 302,
427
- headers: {
428
- Location: redirect,
429
- 'Set-Cookie': cookieHeader,
430
- },
431
- });
432
- return response;
433
- };
434
- }
435
- // ─────────────────────────────────────────────────────────────────────────────
436
- // createDevCookieVerifier
437
- // ─────────────────────────────────────────────────────────────────────────────
438
- /**
439
- * Creates a session verifier that reads the cookie issued by `createDevLoginHandler`.
440
- *
441
- * Use this together with `createDevLoginHandler` when you want dev role-switching
442
- * (e.g. clicking "Login as Staff" in a dev UI) rather than a fixed synthetic user.
443
- *
444
- * The verifier decodes the base64url cookie value and returns the embedded session.
445
- * Falls back to `null` (unauthenticated) if the cookie is absent or expired.
446
- *
447
- * ```typescript
448
- * // Only one of these in dev — pick what fits your workflow:
449
- *
450
- * // Option A: Fixed dev user, no login UI needed
451
- * const verifySession = createDevSessionVerifier({ role: 'owner' })
452
- *
453
- * // Option B: Role-switching dev login UI
454
- * app.get('/api/dev/login', createDevLoginHandler({ allowedRoles: ['owner', 'staff', 'customer'] }))
455
- * const verifySession = createDevCookieVerifier()
456
- * ```
457
- *
458
- * @param cookieName - Must match the `cookieName` passed to `createDevLoginHandler`. Default: `'soulcraft_dev_session'`.
459
- * @returns A `SessionVerifier` compatible with `createAuthMiddleware`.
460
- */
461
- export function createDevCookieVerifier(cookieName = 'soulcraft_dev_session') {
462
- return async function verifyDevCookie(cookieHeader) {
463
- const value = _parseCookie(cookieHeader, cookieName);
464
- if (!value)
465
- return null;
466
- return _decodeSessionCookie(value);
467
- };
468
- }
469
- // ─────────────────────────────────────────────────────────────────────────────
470
- // createGuestSessionHandler
471
- // ─────────────────────────────────────────────────────────────────────────────
472
- /**
473
- * Creates a Hono request handler that issues a guest session cookie.
474
- *
475
- * Venue visitors can browse and initiate bookings without creating an account.
476
- * This handler mounts at e.g. `/api/guest/session` and issues a session cookie
477
- * with `platformRole: 'guest'` and a unique guest ID on each call (if no valid
478
- * guest session already exists).
479
- *
480
- * The guest session cookie can be verified using `createGuestCookieVerifier`,
481
- * which returns a `SessionVerifier` compatible with `createAuthMiddleware`.
482
- *
483
- * @param options - Cookie name, max-age, and optional `onGuestCreated` callback.
484
- * @returns A Hono-compatible request handler.
485
- *
486
- * @deprecated Use `createRequestGuestSessionHandler` from `request-middleware.ts` instead.
487
- * The Hono-specific handler will be removed in a future major version.
488
- *
489
- * @example
490
- * ```typescript
491
- * import { createGuestSessionHandler, createGuestCookieVerifier, createAuthMiddleware } from '@soulcraft/sdk/server'
492
- *
493
- * // Issue guest sessions
494
- * app.post('/api/guest/session', createGuestSessionHandler({
495
- * onGuestCreated: async (guestId) => {
496
- * await db.guests.insert({ id: guestId, createdAt: new Date() })
497
- * },
498
- * }))
499
- *
500
- * // Verify guest sessions in optional auth (guests can browse)
501
- * const verifyGuest = createGuestCookieVerifier()
502
- * const verifySession = createRemoteSessionVerifier({ idpUrl: process.env.SOULCRAFT_IDP_URL! })
503
- *
504
- * // Compose: check real session first, fall back to guest
505
- * const { optionalAuth } = createAuthMiddleware(async (cookie) =>
506
- * await verifySession(cookie) ?? await verifyGuest(cookie)
507
- * )
508
- * ```
509
- */
510
- export function createGuestSessionHandler(options = {}) {
511
- const cookieName = options.cookieName ?? 'soulcraft_guest_session';
512
- const maxAgeSeconds = options.maxAgeSeconds ?? 3_600;
513
- const onGuestCreated = options.onGuestCreated;
514
- return async function guestSessionHandler(c) {
515
- // Return existing guest session if still valid
516
- const cookieHeader = c.req.header('cookie') ?? '';
517
- const existingValue = _parseCookie(cookieHeader, cookieName);
518
- if (existingValue) {
519
- const existing = _decodeSessionCookie(existingValue);
520
- if (existing)
521
- return c.json({ guestId: existing.user.id, existing: true });
522
- }
523
- // Create a new guest session
524
- const guestId = `guest-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
525
- const email = `${guestId}@guest.soulcraft.com`;
526
- const session = {
527
- user: {
528
- id: guestId,
529
- email,
530
- name: 'Guest',
531
- image: null,
532
- platformRole: 'guest',
533
- emailHash: computeEmailHash(email),
534
- },
535
- sessionId: `guest-session-${Date.now()}`,
536
- expiresAt: Date.now() + maxAgeSeconds * 1000,
537
- };
538
- if (onGuestCreated)
539
- await onGuestCreated(guestId);
540
- const cookieValue = _encodeSessionCookie(session);
541
- const cookieHeader2 = [
542
- `${cookieName}=${cookieValue}`,
543
- `Path=/`,
544
- `HttpOnly`,
545
- `SameSite=Lax`,
546
- `Max-Age=${maxAgeSeconds}`,
547
- ].join('; ');
548
- return new Response(JSON.stringify({ guestId, existing: false }), {
549
- status: 200,
550
- headers: {
551
- 'Content-Type': 'application/json',
552
- 'Set-Cookie': cookieHeader2,
553
- },
554
- });
555
- };
556
- }
557
- // ─────────────────────────────────────────────────────────────────────────────
558
- // createGuestCookieVerifier
559
- // ─────────────────────────────────────────────────────────────────────────────
560
- /**
561
- * Creates a session verifier that reads the cookie issued by `createGuestSessionHandler`.
562
- *
563
- * Returns the guest `SoulcraftSession` or `null` if no valid guest cookie is present.
564
- * Compose with `createRemoteSessionVerifier` to allow both authenticated and guest access:
565
- *
566
- * ```typescript
567
- * const verifyReal = createRemoteSessionVerifier({ idpUrl: process.env.SOULCRAFT_IDP_URL! })
568
- * const verifyGuest = createGuestCookieVerifier()
569
- *
570
- * const { optionalAuth } = createAuthMiddleware(async (cookie) =>
571
- * await verifyReal(cookie) ?? await verifyGuest(cookie)
572
- * )
573
- * ```
574
- *
575
- * @param cookieName - Must match the `cookieName` passed to `createGuestSessionHandler`. Default: `'soulcraft_guest_session'`.
576
- * @returns A `SessionVerifier` compatible with `createAuthMiddleware`.
577
- */
578
- export function createGuestCookieVerifier(cookieName = 'soulcraft_guest_session') {
579
- return async function verifyGuestCookie(cookieHeader) {
580
- const value = _parseCookie(cookieHeader, cookieName);
581
- if (!value)
582
- return null;
583
- return _decodeSessionCookie(value);
584
- };
585
- }
586
- //# sourceMappingURL=middleware.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../src/modules/auth/middleware.ts"],"names":[],"mappings":"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"}