kavachos 0.1.5 → 0.2.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.
@@ -954,7 +954,7 @@ function createAdminModule(config, db, sessionManager) {
954
954
  const url = new URL(request.url);
955
955
  const { pathname } = url;
956
956
  const { method } = request;
957
- const json3 = (data, status = 200) => new Response(JSON.stringify(data), {
957
+ const json2 = (data, status = 200) => new Response(JSON.stringify(data), {
958
958
  status,
959
959
  headers: { "Content-Type": "application/json" }
960
960
  });
@@ -963,14 +963,14 @@ function createAdminModule(config, db, sessionManager) {
963
963
  const offset = url.searchParams.get("offset") ? Number(url.searchParams.get("offset")) : void 0;
964
964
  const search = url.searchParams.get("search") ?? void 0;
965
965
  const result = await listUsers({ limit, offset, search });
966
- return json3(result);
966
+ return json2(result);
967
967
  }
968
968
  const userMatch = /^\/auth\/admin\/users\/([^/]+)$/.exec(pathname);
969
969
  if (method === "GET" && userMatch) {
970
970
  const userId = decodeURIComponent(userMatch[1] ?? "");
971
971
  const user = await getUser(userId);
972
- if (!user) return json3({ error: "User not found" }, 404);
973
- return json3(user);
972
+ if (!user) return json2({ error: "User not found" }, 404);
973
+ return json2(user);
974
974
  }
975
975
  const banMatch = /^\/auth\/admin\/users\/([^/]+)\/ban$/.exec(pathname);
976
976
  if (method === "POST" && banMatch) {
@@ -983,19 +983,19 @@ function createAdminModule(config, db, sessionManager) {
983
983
  const reason = typeof body.reason === "string" ? body.reason : void 0;
984
984
  const expiresAt = body.expiresAt ? new Date(body.expiresAt) : void 0;
985
985
  await banUser(userId, reason, expiresAt);
986
- return json3({ success: true });
986
+ return json2({ success: true });
987
987
  }
988
988
  const unbanMatch = /^\/auth\/admin\/users\/([^/]+)\/unban$/.exec(pathname);
989
989
  if (method === "POST" && unbanMatch) {
990
990
  const userId = decodeURIComponent(unbanMatch[1] ?? "");
991
991
  await unbanUser(userId);
992
- return json3({ success: true });
992
+ return json2({ success: true });
993
993
  }
994
994
  const deleteMatch = /^\/auth\/admin\/users\/([^/]+)$/.exec(pathname);
995
995
  if (method === "DELETE" && deleteMatch) {
996
996
  const userId = decodeURIComponent(deleteMatch[1] ?? "");
997
997
  await deleteUser(userId);
998
- return json3({ success: true });
998
+ return json2({ success: true });
999
999
  }
1000
1000
  const impersonateMatch = /^\/auth\/admin\/impersonate\/([^/]+)$/.exec(pathname);
1001
1001
  if (method === "POST" && impersonateMatch) {
@@ -1004,28 +1004,28 @@ function createAdminModule(config, db, sessionManager) {
1004
1004
  try {
1005
1005
  body = await request.json();
1006
1006
  } catch {
1007
- return json3({ error: "Invalid JSON body" }, 400);
1007
+ return json2({ error: "Invalid JSON body" }, 400);
1008
1008
  }
1009
1009
  const adminUserId = body.adminUserId;
1010
1010
  if (typeof adminUserId !== "string") {
1011
- return json3({ error: "Missing required field: adminUserId" }, 400);
1011
+ return json2({ error: "Missing required field: adminUserId" }, 400);
1012
1012
  }
1013
1013
  try {
1014
1014
  const result = await impersonate(adminUserId, targetUserId);
1015
- return json3(result);
1015
+ return json2(result);
1016
1016
  } catch (err2) {
1017
- return json3({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 403);
1017
+ return json2({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 403);
1018
1018
  }
1019
1019
  }
1020
1020
  if (method === "POST" && pathname === "/auth/admin/stop-impersonation") {
1021
1021
  const auth = request.headers.get("Authorization");
1022
1022
  const token = auth?.startsWith("Bearer ") ? auth.slice(7) : null;
1023
- if (!token) return json3({ error: "Missing Authorization header" }, 401);
1023
+ if (!token) return json2({ error: "Missing Authorization header" }, 401);
1024
1024
  try {
1025
1025
  await stopImpersonation(token);
1026
- return json3({ success: true });
1026
+ return json2({ success: true });
1027
1027
  } catch (err2) {
1028
- return json3({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 400);
1028
+ return json2({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 400);
1029
1029
  }
1030
1030
  }
1031
1031
  return null;
@@ -1044,6 +1044,210 @@ function createAdminModule(config, db, sessionManager) {
1044
1044
  };
1045
1045
  }
1046
1046
 
1047
+ // src/plugin/helpers.ts
1048
+ function json(body, status = 200) {
1049
+ return new Response(JSON.stringify(body), {
1050
+ status,
1051
+ headers: { "Content-Type": "application/json" }
1052
+ });
1053
+ }
1054
+ async function parseBody(request) {
1055
+ try {
1056
+ const data = await request.json();
1057
+ return { ok: true, data };
1058
+ } catch {
1059
+ return {
1060
+ ok: false,
1061
+ response: json({ error: "Invalid JSON body" }, 400)
1062
+ };
1063
+ }
1064
+ }
1065
+ function buildSetCookie(name, value, maxAge, path = "/") {
1066
+ return `${name}=${encodeURIComponent(value)}; HttpOnly; Secure; SameSite=Lax; Path=${path}; Max-Age=${maxAge}`;
1067
+ }
1068
+
1069
+ // src/auth/admin-plugin.ts
1070
+ function admin(config) {
1071
+ return {
1072
+ id: "kavach-admin",
1073
+ async init(ctx) {
1074
+ const module = createAdminModule(config ?? {}, ctx.db, ctx.sessionManager ?? null);
1075
+ ctx.addEndpoint({
1076
+ method: "GET",
1077
+ path: "/auth/admin/users",
1078
+ metadata: {
1079
+ requireAuth: true,
1080
+ description: "List all users (admin only)"
1081
+ },
1082
+ async handler(request, endpointCtx) {
1083
+ const user = await endpointCtx.getUser(request);
1084
+ if (!user) {
1085
+ return json({ error: "Authentication required" }, 401);
1086
+ }
1087
+ const isAdminUser = await module.isAdmin(user.id);
1088
+ if (!isAdminUser) {
1089
+ return json({ error: "Admin access required" }, 403);
1090
+ }
1091
+ const url = new URL(request.url);
1092
+ const limitParam = url.searchParams.get("limit");
1093
+ const offsetParam = url.searchParams.get("offset");
1094
+ const search = url.searchParams.get("search") ?? void 0;
1095
+ const result = await module.listUsers({
1096
+ limit: limitParam ? Number(limitParam) : void 0,
1097
+ offset: offsetParam ? Number(offsetParam) : void 0,
1098
+ search
1099
+ });
1100
+ return json(result);
1101
+ }
1102
+ });
1103
+ ctx.addEndpoint({
1104
+ method: "GET",
1105
+ path: "/auth/admin/users/:id",
1106
+ metadata: {
1107
+ requireAuth: true,
1108
+ description: "Get a user by ID (admin only)"
1109
+ },
1110
+ async handler(request, endpointCtx) {
1111
+ const user = await endpointCtx.getUser(request);
1112
+ if (!user) {
1113
+ return json({ error: "Authentication required" }, 401);
1114
+ }
1115
+ const isAdminUser = await module.isAdmin(user.id);
1116
+ if (!isAdminUser) {
1117
+ return json({ error: "Admin access required" }, 403);
1118
+ }
1119
+ const url = new URL(request.url);
1120
+ const segments = url.pathname.split("/").filter(Boolean);
1121
+ const targetId = segments[3];
1122
+ if (!targetId) {
1123
+ return json({ error: "Missing user ID in path" }, 400);
1124
+ }
1125
+ const found = await module.getUser(decodeURIComponent(targetId));
1126
+ if (!found) {
1127
+ return json({ error: "User not found" }, 404);
1128
+ }
1129
+ return json(found);
1130
+ }
1131
+ });
1132
+ ctx.addEndpoint({
1133
+ method: "POST",
1134
+ path: "/auth/admin/users/:id/ban",
1135
+ metadata: {
1136
+ requireAuth: true,
1137
+ description: "Ban a user (admin only)"
1138
+ },
1139
+ async handler(request, endpointCtx) {
1140
+ const user = await endpointCtx.getUser(request);
1141
+ if (!user) {
1142
+ return json({ error: "Authentication required" }, 401);
1143
+ }
1144
+ const isAdminUser = await module.isAdmin(user.id);
1145
+ if (!isAdminUser) {
1146
+ return json({ error: "Admin access required" }, 403);
1147
+ }
1148
+ const url = new URL(request.url);
1149
+ const segments = url.pathname.split("/").filter(Boolean);
1150
+ const targetId = segments[3];
1151
+ if (!targetId) {
1152
+ return json({ error: "Missing user ID in path" }, 400);
1153
+ }
1154
+ const bodyResult = await parseBody(request);
1155
+ if (!bodyResult.ok) return bodyResult.response;
1156
+ const reason = typeof bodyResult.data.reason === "string" ? bodyResult.data.reason : void 0;
1157
+ const expiresAt = bodyResult.data.expiresAt ? new Date(bodyResult.data.expiresAt) : void 0;
1158
+ await module.banUser(decodeURIComponent(targetId), reason, expiresAt);
1159
+ return json({ success: true });
1160
+ }
1161
+ });
1162
+ ctx.addEndpoint({
1163
+ method: "POST",
1164
+ path: "/auth/admin/users/:id/unban",
1165
+ metadata: {
1166
+ requireAuth: true,
1167
+ description: "Unban a user (admin only)"
1168
+ },
1169
+ async handler(request, endpointCtx) {
1170
+ const user = await endpointCtx.getUser(request);
1171
+ if (!user) {
1172
+ return json({ error: "Authentication required" }, 401);
1173
+ }
1174
+ const isAdminUser = await module.isAdmin(user.id);
1175
+ if (!isAdminUser) {
1176
+ return json({ error: "Admin access required" }, 403);
1177
+ }
1178
+ const url = new URL(request.url);
1179
+ const segments = url.pathname.split("/").filter(Boolean);
1180
+ const targetId = segments[3];
1181
+ if (!targetId) {
1182
+ return json({ error: "Missing user ID in path" }, 400);
1183
+ }
1184
+ await module.unbanUser(decodeURIComponent(targetId));
1185
+ return json({ success: true });
1186
+ }
1187
+ });
1188
+ ctx.addEndpoint({
1189
+ method: "DELETE",
1190
+ path: "/auth/admin/users/:id",
1191
+ metadata: {
1192
+ requireAuth: true,
1193
+ description: "Delete a user (admin only)"
1194
+ },
1195
+ async handler(request, endpointCtx) {
1196
+ const user = await endpointCtx.getUser(request);
1197
+ if (!user) {
1198
+ return json({ error: "Authentication required" }, 401);
1199
+ }
1200
+ const isAdminUser = await module.isAdmin(user.id);
1201
+ if (!isAdminUser) {
1202
+ return json({ error: "Admin access required" }, 403);
1203
+ }
1204
+ const url = new URL(request.url);
1205
+ const segments = url.pathname.split("/").filter(Boolean);
1206
+ const targetId = segments[3];
1207
+ if (!targetId) {
1208
+ return json({ error: "Missing user ID in path" }, 400);
1209
+ }
1210
+ await module.deleteUser(decodeURIComponent(targetId));
1211
+ return json({ success: true });
1212
+ }
1213
+ });
1214
+ ctx.addEndpoint({
1215
+ method: "POST",
1216
+ path: "/auth/admin/users/:id/impersonate",
1217
+ metadata: {
1218
+ requireAuth: true,
1219
+ description: "Start an impersonation session as a target user (admin only)"
1220
+ },
1221
+ async handler(request, endpointCtx) {
1222
+ const user = await endpointCtx.getUser(request);
1223
+ if (!user) {
1224
+ return json({ error: "Authentication required" }, 401);
1225
+ }
1226
+ const isAdminUser = await module.isAdmin(user.id);
1227
+ if (!isAdminUser) {
1228
+ return json({ error: "Admin access required" }, 403);
1229
+ }
1230
+ const url = new URL(request.url);
1231
+ const segments = url.pathname.split("/").filter(Boolean);
1232
+ const targetId = segments[3];
1233
+ if (!targetId) {
1234
+ return json({ error: "Missing user ID in path" }, 400);
1235
+ }
1236
+ try {
1237
+ const result = await module.impersonate(user.id, decodeURIComponent(targetId));
1238
+ return json(result);
1239
+ } catch (err2) {
1240
+ return json(
1241
+ { error: err2 instanceof Error ? err2.message : "Impersonation failed" },
1242
+ 403
1243
+ );
1244
+ }
1245
+ }
1246
+ });
1247
+ }
1248
+ };
1249
+ }
1250
+
1047
1251
  // src/crypto/web-crypto.ts
1048
1252
  var HEX_CHARS = "0123456789abcdef";
1049
1253
  function toHex(bytes) {
@@ -1222,272 +1426,7 @@ function constantTimeEqual(a, b) {
1222
1426
  return diff === 0;
1223
1427
  }
1224
1428
 
1225
- // src/session/session.ts
1226
- var DEFAULT_MAX_AGE_SECONDS = 60 * 60 * 24 * 7;
1227
- function createSessionManager(config, db) {
1228
- if (!config.secret || config.secret.length < 32) {
1229
- throw new Error("SessionManager: secret must be at least 32 characters.");
1230
- }
1231
- const maxAge = config.maxAge ?? DEFAULT_MAX_AGE_SECONDS;
1232
- const keyObject = new TextEncoder().encode(config.secret);
1233
- function rowToSession2(row) {
1234
- return {
1235
- id: row.id,
1236
- userId: row.userId,
1237
- expiresAt: row.expiresAt,
1238
- createdAt: row.createdAt,
1239
- ...row.metadata !== null && { metadata: row.metadata }
1240
- };
1241
- }
1242
- async function create(userId, metadata) {
1243
- const id = generateId();
1244
- const now = /* @__PURE__ */ new Date();
1245
- const expiresAt = new Date(now.getTime() + maxAge * 1e3);
1246
- await db.insert(sessions).values({
1247
- id,
1248
- userId,
1249
- expiresAt,
1250
- metadata: metadata ?? null,
1251
- createdAt: now
1252
- });
1253
- const token = await new SignJWT({ sub: id }).setProtectedHeader({ alg: "HS256" }).setIssuedAt().setExpirationTime(Math.floor(expiresAt.getTime() / 1e3)).sign(keyObject);
1254
- const session = {
1255
- id,
1256
- userId,
1257
- expiresAt,
1258
- createdAt: now,
1259
- ...metadata !== void 0 && { metadata }
1260
- };
1261
- return { session, token };
1262
- }
1263
- async function validate(token) {
1264
- let sessionId;
1265
- try {
1266
- const { payload } = await jwtVerify(token, keyObject);
1267
- if (typeof payload.sub !== "string" || !payload.sub) return null;
1268
- sessionId = payload.sub;
1269
- } catch {
1270
- return null;
1271
- }
1272
- const now = /* @__PURE__ */ new Date();
1273
- const rows = await db.select().from(sessions).where(and(eq(sessions.id, sessionId)));
1274
- const row = rows[0];
1275
- if (!row) return null;
1276
- if (row.expiresAt <= now) {
1277
- await db.delete(sessions).where(eq(sessions.id, sessionId));
1278
- return null;
1279
- }
1280
- return rowToSession2(row);
1281
- }
1282
- async function revoke(sessionId) {
1283
- await db.delete(sessions).where(eq(sessions.id, sessionId));
1284
- }
1285
- async function revokeAll(userId) {
1286
- await db.delete(sessions).where(eq(sessions.userId, userId));
1287
- }
1288
- async function list(userId) {
1289
- const now = /* @__PURE__ */ new Date();
1290
- const rows = await db.select().from(sessions).where(and(eq(sessions.userId, userId)));
1291
- return rows.filter((row) => row.expiresAt > now).sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()).map(rowToSession2);
1292
- }
1293
- return { create, validate, revoke, revokeAll, list };
1294
- }
1295
-
1296
- // src/auth/admin-plugin.ts
1297
- function jsonResponse2(body, status = 200) {
1298
- return new Response(JSON.stringify(body), {
1299
- status,
1300
- headers: { "Content-Type": "application/json" }
1301
- });
1302
- }
1303
- async function parseBody(request) {
1304
- try {
1305
- return await request.json();
1306
- } catch {
1307
- return {};
1308
- }
1309
- }
1310
- function admin(config) {
1311
- return {
1312
- id: "kavach-admin",
1313
- async init(ctx) {
1314
- const sessionConfig = ctx.config.auth?.session;
1315
- const sessionManager = sessionConfig ? createSessionManager(sessionConfig, ctx.db) : null;
1316
- const module = createAdminModule(config ?? {}, ctx.db, sessionManager);
1317
- ctx.addEndpoint({
1318
- method: "GET",
1319
- path: "/auth/admin/users",
1320
- metadata: {
1321
- requireAuth: true,
1322
- description: "List all users (admin only)"
1323
- },
1324
- async handler(request, endpointCtx) {
1325
- const user = await endpointCtx.getUser(request);
1326
- if (!user) {
1327
- return jsonResponse2({ error: "Authentication required" }, 401);
1328
- }
1329
- const isAdminUser = await module.isAdmin(user.id);
1330
- if (!isAdminUser) {
1331
- return jsonResponse2({ error: "Admin access required" }, 403);
1332
- }
1333
- const url = new URL(request.url);
1334
- const limitParam = url.searchParams.get("limit");
1335
- const offsetParam = url.searchParams.get("offset");
1336
- const search = url.searchParams.get("search") ?? void 0;
1337
- const result = await module.listUsers({
1338
- limit: limitParam ? Number(limitParam) : void 0,
1339
- offset: offsetParam ? Number(offsetParam) : void 0,
1340
- search
1341
- });
1342
- return jsonResponse2(result);
1343
- }
1344
- });
1345
- ctx.addEndpoint({
1346
- method: "GET",
1347
- path: "/auth/admin/users/:id",
1348
- metadata: {
1349
- requireAuth: true,
1350
- description: "Get a user by ID (admin only)"
1351
- },
1352
- async handler(request, endpointCtx) {
1353
- const user = await endpointCtx.getUser(request);
1354
- if (!user) {
1355
- return jsonResponse2({ error: "Authentication required" }, 401);
1356
- }
1357
- const isAdminUser = await module.isAdmin(user.id);
1358
- if (!isAdminUser) {
1359
- return jsonResponse2({ error: "Admin access required" }, 403);
1360
- }
1361
- const url = new URL(request.url);
1362
- const segments = url.pathname.split("/").filter(Boolean);
1363
- const targetId = segments[3];
1364
- if (!targetId) {
1365
- return jsonResponse2({ error: "Missing user ID in path" }, 400);
1366
- }
1367
- const found = await module.getUser(decodeURIComponent(targetId));
1368
- if (!found) {
1369
- return jsonResponse2({ error: "User not found" }, 404);
1370
- }
1371
- return jsonResponse2(found);
1372
- }
1373
- });
1374
- ctx.addEndpoint({
1375
- method: "POST",
1376
- path: "/auth/admin/users/:id/ban",
1377
- metadata: {
1378
- requireAuth: true,
1379
- description: "Ban a user (admin only)"
1380
- },
1381
- async handler(request, endpointCtx) {
1382
- const user = await endpointCtx.getUser(request);
1383
- if (!user) {
1384
- return jsonResponse2({ error: "Authentication required" }, 401);
1385
- }
1386
- const isAdminUser = await module.isAdmin(user.id);
1387
- if (!isAdminUser) {
1388
- return jsonResponse2({ error: "Admin access required" }, 403);
1389
- }
1390
- const url = new URL(request.url);
1391
- const segments = url.pathname.split("/").filter(Boolean);
1392
- const targetId = segments[3];
1393
- if (!targetId) {
1394
- return jsonResponse2({ error: "Missing user ID in path" }, 400);
1395
- }
1396
- const body = await parseBody(request);
1397
- const reason = typeof body.reason === "string" ? body.reason : void 0;
1398
- const expiresAt = body.expiresAt ? new Date(body.expiresAt) : void 0;
1399
- await module.banUser(decodeURIComponent(targetId), reason, expiresAt);
1400
- return jsonResponse2({ success: true });
1401
- }
1402
- });
1403
- ctx.addEndpoint({
1404
- method: "POST",
1405
- path: "/auth/admin/users/:id/unban",
1406
- metadata: {
1407
- requireAuth: true,
1408
- description: "Unban a user (admin only)"
1409
- },
1410
- async handler(request, endpointCtx) {
1411
- const user = await endpointCtx.getUser(request);
1412
- if (!user) {
1413
- return jsonResponse2({ error: "Authentication required" }, 401);
1414
- }
1415
- const isAdminUser = await module.isAdmin(user.id);
1416
- if (!isAdminUser) {
1417
- return jsonResponse2({ error: "Admin access required" }, 403);
1418
- }
1419
- const url = new URL(request.url);
1420
- const segments = url.pathname.split("/").filter(Boolean);
1421
- const targetId = segments[3];
1422
- if (!targetId) {
1423
- return jsonResponse2({ error: "Missing user ID in path" }, 400);
1424
- }
1425
- await module.unbanUser(decodeURIComponent(targetId));
1426
- return jsonResponse2({ success: true });
1427
- }
1428
- });
1429
- ctx.addEndpoint({
1430
- method: "DELETE",
1431
- path: "/auth/admin/users/:id",
1432
- metadata: {
1433
- requireAuth: true,
1434
- description: "Delete a user (admin only)"
1435
- },
1436
- async handler(request, endpointCtx) {
1437
- const user = await endpointCtx.getUser(request);
1438
- if (!user) {
1439
- return jsonResponse2({ error: "Authentication required" }, 401);
1440
- }
1441
- const isAdminUser = await module.isAdmin(user.id);
1442
- if (!isAdminUser) {
1443
- return jsonResponse2({ error: "Admin access required" }, 403);
1444
- }
1445
- const url = new URL(request.url);
1446
- const segments = url.pathname.split("/").filter(Boolean);
1447
- const targetId = segments[3];
1448
- if (!targetId) {
1449
- return jsonResponse2({ error: "Missing user ID in path" }, 400);
1450
- }
1451
- await module.deleteUser(decodeURIComponent(targetId));
1452
- return jsonResponse2({ success: true });
1453
- }
1454
- });
1455
- ctx.addEndpoint({
1456
- method: "POST",
1457
- path: "/auth/admin/users/:id/impersonate",
1458
- metadata: {
1459
- requireAuth: true,
1460
- description: "Start an impersonation session as a target user (admin only)"
1461
- },
1462
- async handler(request, endpointCtx) {
1463
- const user = await endpointCtx.getUser(request);
1464
- if (!user) {
1465
- return jsonResponse2({ error: "Authentication required" }, 401);
1466
- }
1467
- const isAdminUser = await module.isAdmin(user.id);
1468
- if (!isAdminUser) {
1469
- return jsonResponse2({ error: "Admin access required" }, 403);
1470
- }
1471
- const url = new URL(request.url);
1472
- const segments = url.pathname.split("/").filter(Boolean);
1473
- const targetId = segments[3];
1474
- if (!targetId) {
1475
- return jsonResponse2({ error: "Missing user ID in path" }, 400);
1476
- }
1477
- try {
1478
- const result = await module.impersonate(user.id, decodeURIComponent(targetId));
1479
- return jsonResponse2(result);
1480
- } catch (err2) {
1481
- return jsonResponse2(
1482
- { error: err2 instanceof Error ? err2.message : "Impersonation failed" },
1483
- 403
1484
- );
1485
- }
1486
- }
1487
- });
1488
- }
1489
- };
1490
- }
1429
+ // src/auth/anonymous.ts
1491
1430
  var DEFAULT_SESSION_TTL_SECONDS = 60 * 60 * 24;
1492
1431
  var DEFAULT_MAX_AGE_MS = 1e3 * 60 * 60 * 24;
1493
1432
  var ANONYMOUS_EMAIL_DOMAIN = "kavachos.anonymous";
@@ -1557,29 +1496,14 @@ function createAnonymousAuthModule(config, db, sessionManager) {
1557
1496
  }
1558
1497
 
1559
1498
  // src/auth/anonymous-plugin.ts
1560
- function jsonResponse3(body, status = 200) {
1561
- return new Response(JSON.stringify(body), {
1562
- status,
1563
- headers: { "Content-Type": "application/json" }
1564
- });
1565
- }
1566
- async function parseBody2(request) {
1567
- try {
1568
- return await request.json();
1569
- } catch {
1570
- return {};
1571
- }
1572
- }
1573
1499
  function anonymousAuth(config) {
1574
1500
  return {
1575
1501
  id: "kavach-anonymous",
1576
1502
  async init(ctx) {
1577
- const sessionSecret = ctx.config.auth?.session?.secret;
1578
- if (!sessionSecret) {
1503
+ if (!ctx.sessionManager) {
1579
1504
  throw new Error("anonymousAuth plugin requires auth.session.secret to be configured");
1580
1505
  }
1581
- const sessionManager = createSessionManager({ secret: sessionSecret }, ctx.db);
1582
- const mod = createAnonymousAuthModule(config ?? {}, ctx.db, sessionManager);
1506
+ const mod = createAnonymousAuthModule(config ?? {}, ctx.db, ctx.sessionManager);
1583
1507
  ctx.addEndpoint({
1584
1508
  method: "POST",
1585
1509
  path: "/auth/anonymous",
@@ -1590,9 +1514,9 @@ function anonymousAuth(config) {
1590
1514
  async handler(_request, _endpointCtx) {
1591
1515
  try {
1592
1516
  const result = await mod.createAnonymousUser();
1593
- return jsonResponse3({ userId: result.userId, sessionToken: result.sessionToken });
1517
+ return json({ userId: result.userId, sessionToken: result.sessionToken });
1594
1518
  } catch (err2) {
1595
- return jsonResponse3(
1519
+ return json(
1596
1520
  { error: err2 instanceof Error ? err2.message : "Failed to create anonymous user" },
1597
1521
  500
1598
1522
  );
@@ -1609,21 +1533,22 @@ function anonymousAuth(config) {
1609
1533
  async handler(request, endpointCtx) {
1610
1534
  const user = await endpointCtx.getUser(request);
1611
1535
  if (!user) {
1612
- return jsonResponse3({ error: "Authentication required" }, 401);
1536
+ return json({ error: "Authentication required" }, 401);
1613
1537
  }
1614
- const body = await parseBody2(request);
1615
- const email = typeof body.email === "string" ? body.email.trim() : null;
1616
- const name = typeof body.name === "string" ? body.name.trim() : void 0;
1538
+ const bodyResult = await parseBody(request);
1539
+ if (!bodyResult.ok) return bodyResult.response;
1540
+ const email = typeof bodyResult.data.email === "string" ? bodyResult.data.email.trim() : null;
1541
+ const name = typeof bodyResult.data.name === "string" ? bodyResult.data.name.trim() : void 0;
1617
1542
  if (!email) {
1618
- return jsonResponse3({ error: "Missing required field: email" }, 400);
1543
+ return json({ error: "Missing required field: email" }, 400);
1619
1544
  }
1620
1545
  try {
1621
1546
  await mod.upgradeUser(user.id, { email, name });
1622
- return jsonResponse3({ upgraded: true });
1547
+ return json({ upgraded: true });
1623
1548
  } catch (err2) {
1624
1549
  const message = err2 instanceof Error ? err2.message : "Upgrade failed";
1625
1550
  const status = message.includes("not an anonymous user") ? 400 : 500;
1626
- return jsonResponse3({ error: message }, status);
1551
+ return json({ error: message }, status);
1627
1552
  }
1628
1553
  }
1629
1554
  });
@@ -1637,10 +1562,10 @@ function anonymousAuth(config) {
1637
1562
  async handler(request, endpointCtx) {
1638
1563
  const user = await endpointCtx.getUser(request);
1639
1564
  if (!user) {
1640
- return jsonResponse3({ error: "Authentication required" }, 401);
1565
+ return json({ error: "Authentication required" }, 401);
1641
1566
  }
1642
1567
  const anonymous = await mod.isAnonymous(user.id);
1643
- return jsonResponse3({ anonymous });
1568
+ return json({ anonymous });
1644
1569
  }
1645
1570
  });
1646
1571
  }
@@ -1746,7 +1671,7 @@ function createApiKeyManagerModule(config, db) {
1746
1671
  const url = new URL(request.url);
1747
1672
  const { pathname } = url;
1748
1673
  const { method } = request;
1749
- const json3 = (data, status = 200) => new Response(JSON.stringify(data), {
1674
+ const json2 = (data, status = 200) => new Response(JSON.stringify(data), {
1750
1675
  status,
1751
1676
  headers: { "Content-Type": "application/json" }
1752
1677
  });
@@ -1755,11 +1680,11 @@ function createApiKeyManagerModule(config, db) {
1755
1680
  try {
1756
1681
  body = await request.json();
1757
1682
  } catch {
1758
- return json3({ error: "Invalid JSON body" }, 400);
1683
+ return json2({ error: "Invalid JSON body" }, 400);
1759
1684
  }
1760
1685
  const b = body;
1761
1686
  if (typeof b.userId !== "string" || typeof b.name !== "string" || !Array.isArray(b.permissions)) {
1762
- return json3({ error: "Missing required fields: userId, name, permissions" }, 400);
1687
+ return json2({ error: "Missing required fields: userId, name, permissions" }, 400);
1763
1688
  }
1764
1689
  const expiresAt = b.expiresAt ? new Date(b.expiresAt) : void 0;
1765
1690
  const result = await create({
@@ -1768,28 +1693,28 @@ function createApiKeyManagerModule(config, db) {
1768
1693
  permissions: b.permissions,
1769
1694
  expiresAt
1770
1695
  });
1771
- return json3(result, 201);
1696
+ return json2(result, 201);
1772
1697
  }
1773
1698
  const listMatch = /^\/auth\/api-keys\/([^/]+)$/.exec(pathname);
1774
1699
  if (method === "GET" && listMatch) {
1775
1700
  const userId = decodeURIComponent(listMatch[1] ?? "");
1776
1701
  const keys = await list(userId);
1777
- return json3(keys);
1702
+ return json2(keys);
1778
1703
  }
1779
1704
  const deleteMatch = /^\/auth\/api-keys\/([^/]+)$/.exec(pathname);
1780
1705
  if (method === "DELETE" && deleteMatch) {
1781
1706
  const keyId = decodeURIComponent(deleteMatch[1] ?? "");
1782
1707
  await revoke(keyId);
1783
- return json3({ success: true });
1708
+ return json2({ success: true });
1784
1709
  }
1785
1710
  const rotateMatch = /^\/auth\/api-keys\/([^/]+)\/rotate$/.exec(pathname);
1786
1711
  if (method === "POST" && rotateMatch) {
1787
1712
  const keyId = decodeURIComponent(rotateMatch[1] ?? "");
1788
1713
  try {
1789
1714
  const result = await rotate(keyId);
1790
- return json3(result);
1715
+ return json2(result);
1791
1716
  } catch (err2) {
1792
- return json3({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 404);
1717
+ return json2({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 404);
1793
1718
  }
1794
1719
  }
1795
1720
  return null;
@@ -1806,19 +1731,6 @@ function createApiKeyManagerModule(config, db) {
1806
1731
  }
1807
1732
 
1808
1733
  // src/auth/api-key-plugin.ts
1809
- function jsonResponse4(body, status = 200) {
1810
- return new Response(JSON.stringify(body), {
1811
- status,
1812
- headers: { "Content-Type": "application/json" }
1813
- });
1814
- }
1815
- async function parseBody3(request) {
1816
- try {
1817
- return await request.json();
1818
- } catch {
1819
- return {};
1820
- }
1821
- }
1822
1734
  function apiKeys2(config) {
1823
1735
  return {
1824
1736
  id: "kavach-api-key",
@@ -1834,15 +1746,16 @@ function apiKeys2(config) {
1834
1746
  async handler(request, endpointCtx) {
1835
1747
  const user = await endpointCtx.getUser(request);
1836
1748
  if (!user) {
1837
- return jsonResponse4({ error: "Authentication required" }, 401);
1749
+ return json({ error: "Authentication required" }, 401);
1838
1750
  }
1839
- const body = await parseBody3(request);
1840
- const name = typeof body.name === "string" ? body.name.trim() : null;
1841
- const permissions2 = Array.isArray(body.permissions) ? body.permissions : null;
1751
+ const bodyResult = await parseBody(request);
1752
+ if (!bodyResult.ok) return bodyResult.response;
1753
+ const name = typeof bodyResult.data.name === "string" ? bodyResult.data.name.trim() : null;
1754
+ const permissions2 = Array.isArray(bodyResult.data.permissions) ? bodyResult.data.permissions : null;
1842
1755
  if (!name || !permissions2) {
1843
- return jsonResponse4({ error: "Missing required fields: name, permissions" }, 400);
1756
+ return json({ error: "Missing required fields: name, permissions" }, 400);
1844
1757
  }
1845
- const expiresAt = body.expiresAt ? new Date(body.expiresAt) : void 0;
1758
+ const expiresAt = bodyResult.data.expiresAt ? new Date(bodyResult.data.expiresAt) : void 0;
1846
1759
  try {
1847
1760
  const result = await module.create({
1848
1761
  userId: user.id,
@@ -1850,9 +1763,9 @@ function apiKeys2(config) {
1850
1763
  permissions: permissions2,
1851
1764
  expiresAt
1852
1765
  });
1853
- return jsonResponse4(result, 201);
1766
+ return json(result, 201);
1854
1767
  } catch (err2) {
1855
- return jsonResponse4(
1768
+ return json(
1856
1769
  { error: err2 instanceof Error ? err2.message : "Failed to create API key" },
1857
1770
  500
1858
1771
  );
@@ -1869,10 +1782,10 @@ function apiKeys2(config) {
1869
1782
  async handler(request, endpointCtx) {
1870
1783
  const user = await endpointCtx.getUser(request);
1871
1784
  if (!user) {
1872
- return jsonResponse4({ error: "Authentication required" }, 401);
1785
+ return json({ error: "Authentication required" }, 401);
1873
1786
  }
1874
1787
  const keys = await module.list(user.id);
1875
- return jsonResponse4({ apiKeys: keys });
1788
+ return json({ apiKeys: keys });
1876
1789
  }
1877
1790
  });
1878
1791
  ctx.addEndpoint({
@@ -1885,21 +1798,21 @@ function apiKeys2(config) {
1885
1798
  async handler(request, endpointCtx) {
1886
1799
  const user = await endpointCtx.getUser(request);
1887
1800
  if (!user) {
1888
- return jsonResponse4({ error: "Authentication required" }, 401);
1801
+ return json({ error: "Authentication required" }, 401);
1889
1802
  }
1890
1803
  const url = new URL(request.url);
1891
1804
  const segments = url.pathname.split("/").filter(Boolean);
1892
1805
  const keyId = segments[2];
1893
1806
  if (!keyId) {
1894
- return jsonResponse4({ error: "Missing API key ID in path" }, 400);
1807
+ return json({ error: "Missing API key ID in path" }, 400);
1895
1808
  }
1896
1809
  const keys = await module.list(user.id);
1897
1810
  const owned = keys.some((k) => k.id === decodeURIComponent(keyId));
1898
1811
  if (!owned) {
1899
- return jsonResponse4({ error: "API key not found" }, 404);
1812
+ return json({ error: "API key not found" }, 404);
1900
1813
  }
1901
1814
  await module.revoke(decodeURIComponent(keyId));
1902
- return jsonResponse4({ revoked: true });
1815
+ return json({ revoked: true });
1903
1816
  }
1904
1817
  });
1905
1818
  ctx.addEndpoint({
@@ -1912,24 +1825,24 @@ function apiKeys2(config) {
1912
1825
  async handler(request, endpointCtx) {
1913
1826
  const user = await endpointCtx.getUser(request);
1914
1827
  if (!user) {
1915
- return jsonResponse4({ error: "Authentication required" }, 401);
1828
+ return json({ error: "Authentication required" }, 401);
1916
1829
  }
1917
1830
  const url = new URL(request.url);
1918
1831
  const segments = url.pathname.split("/").filter(Boolean);
1919
1832
  const keyId = segments[2];
1920
1833
  if (!keyId) {
1921
- return jsonResponse4({ error: "Missing API key ID in path" }, 400);
1834
+ return json({ error: "Missing API key ID in path" }, 400);
1922
1835
  }
1923
1836
  const keys = await module.list(user.id);
1924
1837
  const owned = keys.some((k) => k.id === decodeURIComponent(keyId));
1925
1838
  if (!owned) {
1926
- return jsonResponse4({ error: "API key not found" }, 404);
1839
+ return json({ error: "API key not found" }, 404);
1927
1840
  }
1928
1841
  try {
1929
1842
  const result = await module.rotate(decodeURIComponent(keyId));
1930
- return jsonResponse4(result);
1843
+ return json(result);
1931
1844
  } catch (err2) {
1932
- return jsonResponse4(
1845
+ return json(
1933
1846
  { error: err2 instanceof Error ? err2.message : "Failed to rotate API key" },
1934
1847
  400
1935
1848
  );
@@ -2319,13 +2232,13 @@ function customSession(config = {}) {
2319
2232
  const url = new URL(request.url);
2320
2233
  const sessionId = url.searchParams.get("sessionId");
2321
2234
  if (!sessionId) {
2322
- return jsonResponse5({ error: "Missing required query parameter: sessionId" }, 400);
2235
+ return jsonResponse2({ error: "Missing required query parameter: sessionId" }, 400);
2323
2236
  }
2324
2237
  try {
2325
2238
  const fields = await mod.getSessionFields(sessionId);
2326
- return jsonResponse5({ fields: fields ?? {} });
2239
+ return jsonResponse2({ fields: fields ?? {} });
2327
2240
  } catch (err2) {
2328
- return jsonResponse5(
2241
+ return jsonResponse2(
2329
2242
  { error: err2 instanceof Error ? err2.message : "Failed to get session fields" },
2330
2243
  500
2331
2244
  );
@@ -2344,23 +2257,23 @@ function customSession(config = {}) {
2344
2257
  try {
2345
2258
  body = await request.json();
2346
2259
  } catch {
2347
- return jsonResponse5({ error: "Invalid JSON body" }, 400);
2260
+ return jsonResponse2({ error: "Invalid JSON body" }, 400);
2348
2261
  }
2349
2262
  const sessionId = typeof body.sessionId === "string" ? body.sessionId : null;
2350
2263
  if (!sessionId) {
2351
- return jsonResponse5({ error: "Missing required field: sessionId" }, 400);
2264
+ return jsonResponse2({ error: "Missing required field: sessionId" }, 400);
2352
2265
  }
2353
2266
  const fields = body.fields !== null && body.fields !== void 0 && typeof body.fields === "object" && !Array.isArray(body.fields) ? body.fields : null;
2354
2267
  if (!fields) {
2355
- return jsonResponse5({ error: "Missing or invalid field: fields" }, 400);
2268
+ return jsonResponse2({ error: "Missing or invalid field: fields" }, 400);
2356
2269
  }
2357
2270
  try {
2358
2271
  await mod.updateSessionFields(sessionId, fields);
2359
- return jsonResponse5({ updated: true });
2272
+ return jsonResponse2({ updated: true });
2360
2273
  } catch (err2) {
2361
2274
  const message = err2 instanceof Error ? err2.message : "Update failed";
2362
2275
  const status = message.includes("not found") ? 404 : 500;
2363
- return jsonResponse5({ error: message }, status);
2276
+ return jsonResponse2({ error: message }, status);
2364
2277
  }
2365
2278
  }
2366
2279
  });
@@ -2370,7 +2283,7 @@ function customSession(config = {}) {
2370
2283
  }
2371
2284
  };
2372
2285
  }
2373
- function jsonResponse5(body, status = 200) {
2286
+ function jsonResponse2(body, status = 200) {
2374
2287
  return new Response(JSON.stringify(body), {
2375
2288
  status,
2376
2289
  headers: { "Content-Type": "application/json" }
@@ -2383,13 +2296,13 @@ var DEFAULT_CODE_EXPIRY_SECONDS = 900;
2383
2296
  var DEFAULT_POLL_INTERVAL_SECONDS = 5;
2384
2297
  var USER_CODE_ALPHABET = "BCDFGHJKLMNPQRSTVWXZ";
2385
2298
  var SLOW_DOWN_THRESHOLD_MS = 4e3;
2386
- function jsonResponse6(body, status = 200) {
2299
+ function jsonResponse3(body, status = 200) {
2387
2300
  return new Response(JSON.stringify(body), {
2388
2301
  status,
2389
2302
  headers: { "Content-Type": "application/json" }
2390
2303
  });
2391
2304
  }
2392
- async function parseBody4(request) {
2305
+ async function parseBody2(request) {
2393
2306
  try {
2394
2307
  return await request.json();
2395
2308
  } catch {
@@ -2513,7 +2426,7 @@ function createDeviceAuthModule(config) {
2513
2426
  const { method, pathname } = { method: request.method, pathname: url.pathname };
2514
2427
  if (method === "POST" && pathname.endsWith("/auth/device/code")) {
2515
2428
  const response = await requestCode();
2516
- return jsonResponse6({
2429
+ return jsonResponse3({
2517
2430
  device_code: response.deviceCode,
2518
2431
  user_code: response.userCode,
2519
2432
  verification_uri: response.verificationUri,
@@ -2523,17 +2436,17 @@ function createDeviceAuthModule(config) {
2523
2436
  });
2524
2437
  }
2525
2438
  if (method === "POST" && pathname.endsWith("/auth/device/token")) {
2526
- const body = await parseBody4(request);
2439
+ const body = await parseBody2(request);
2527
2440
  const deviceCode = typeof body.device_code === "string" ? body.device_code : null;
2528
2441
  if (!deviceCode) {
2529
- return jsonResponse6(
2442
+ return jsonResponse3(
2530
2443
  { error: "invalid_request", error_description: "Missing device_code" },
2531
2444
  400
2532
2445
  );
2533
2446
  }
2534
2447
  const grant = grantsByDevice.get(deviceCode);
2535
2448
  if (grant?.lastPolledAt && Date.now() - grant.lastPolledAt < SLOW_DOWN_THRESHOLD_MS) {
2536
- return jsonResponse6(
2449
+ return jsonResponse3(
2537
2450
  {
2538
2451
  error: "slow_down",
2539
2452
  error_description: "Polling too frequently",
@@ -2544,10 +2457,10 @@ function createDeviceAuthModule(config) {
2544
2457
  }
2545
2458
  const status = await checkAuthorization(deviceCode);
2546
2459
  if (status.status === "authorized") {
2547
- return jsonResponse6({ authorized: true, user_id: status.userId });
2460
+ return jsonResponse3({ authorized: true, user_id: status.userId });
2548
2461
  }
2549
2462
  if (status.status === "pending") {
2550
- return jsonResponse6(
2463
+ return jsonResponse3(
2551
2464
  {
2552
2465
  error: "authorization_pending",
2553
2466
  error_description: "The user has not yet authorized the device"
@@ -2556,7 +2469,7 @@ function createDeviceAuthModule(config) {
2556
2469
  );
2557
2470
  }
2558
2471
  if (status.status === "denied") {
2559
- return jsonResponse6(
2472
+ return jsonResponse3(
2560
2473
  {
2561
2474
  error: "access_denied",
2562
2475
  error_description: "The user denied the authorization request"
@@ -2564,7 +2477,7 @@ function createDeviceAuthModule(config) {
2564
2477
  400
2565
2478
  );
2566
2479
  }
2567
- return jsonResponse6(
2480
+ return jsonResponse3(
2568
2481
  {
2569
2482
  error: "expired_token",
2570
2483
  error_description: "The device code has expired"
@@ -2573,12 +2486,12 @@ function createDeviceAuthModule(config) {
2573
2486
  );
2574
2487
  }
2575
2488
  if (method === "POST" && pathname.endsWith("/auth/device/authorize")) {
2576
- const body = await parseBody4(request);
2489
+ const body = await parseBody2(request);
2577
2490
  const userCode = typeof body.user_code === "string" ? body.user_code : null;
2578
2491
  const userId = typeof body.user_id === "string" ? body.user_id : null;
2579
2492
  const action = typeof body.action === "string" ? body.action : "approve";
2580
2493
  if (!userCode || !userId) {
2581
- return jsonResponse6(
2494
+ return jsonResponse3(
2582
2495
  { error: "invalid_request", error_description: "Missing user_code or user_id" },
2583
2496
  400
2584
2497
  );
@@ -2586,12 +2499,12 @@ function createDeviceAuthModule(config) {
2586
2499
  try {
2587
2500
  if (action === "deny") {
2588
2501
  await deny(userCode);
2589
- return jsonResponse6({ denied: true });
2502
+ return jsonResponse3({ denied: true });
2590
2503
  }
2591
2504
  await authorize(userCode, userId);
2592
- return jsonResponse6({ authorized: true });
2505
+ return jsonResponse3({ authorized: true });
2593
2506
  } catch (err2) {
2594
- return jsonResponse6(
2507
+ return jsonResponse3(
2595
2508
  {
2596
2509
  error: "invalid_request",
2597
2510
  error_description: err2 instanceof Error ? err2.message : "Authorization failed"
@@ -2872,31 +2785,16 @@ function createEmailOtpModule(config, db, sessionManager) {
2872
2785
  }
2873
2786
 
2874
2787
  // src/auth/email-otp-plugin.ts
2875
- function jsonResponse7(body, status = 200) {
2876
- return new Response(JSON.stringify(body), {
2877
- status,
2878
- headers: { "Content-Type": "application/json" }
2879
- });
2880
- }
2881
- async function parseBody5(request) {
2882
- try {
2883
- return await request.json();
2884
- } catch {
2885
- return {};
2886
- }
2887
- }
2888
2788
  function emailOtp(config) {
2889
2789
  return {
2890
2790
  id: "kavach-email-otp",
2891
2791
  async init(ctx) {
2892
- const sessionConfig = ctx.config.auth?.session;
2893
- if (!sessionConfig) {
2792
+ if (!ctx.sessionManager) {
2894
2793
  throw new Error(
2895
2794
  "kavach-email-otp plugin requires auth.session to be configured so that sessions can be issued on successful verification."
2896
2795
  );
2897
2796
  }
2898
- const sessionManager = createSessionManager(sessionConfig, ctx.db);
2899
- const module = createEmailOtpModule(config, ctx.db, sessionManager);
2797
+ const module = createEmailOtpModule(config, ctx.db, ctx.sessionManager);
2900
2798
  ctx.addEndpoint({
2901
2799
  method: "POST",
2902
2800
  path: "/auth/email-otp/send",
@@ -2905,19 +2803,17 @@ function emailOtp(config) {
2905
2803
  description: "Send a one-time passcode to the provided email address"
2906
2804
  },
2907
2805
  async handler(request) {
2908
- const body = await parseBody5(request);
2909
- const rawEmail = typeof body.email === "string" ? body.email.trim().toLowerCase() : null;
2806
+ const bodyResult = await parseBody(request);
2807
+ if (!bodyResult.ok) return bodyResult.response;
2808
+ const rawEmail = typeof bodyResult.data.email === "string" ? bodyResult.data.email.trim().toLowerCase() : null;
2910
2809
  if (!rawEmail) {
2911
- return jsonResponse7({ error: "Missing required field: email" }, 400);
2810
+ return json({ error: "Missing required field: email" }, 400);
2912
2811
  }
2913
2812
  try {
2914
2813
  const result = await module.sendCode(rawEmail);
2915
- return jsonResponse7(result);
2814
+ return json(result);
2916
2815
  } catch (err2) {
2917
- return jsonResponse7(
2918
- { error: err2 instanceof Error ? err2.message : "Failed to send OTP" },
2919
- 500
2920
- );
2816
+ return json({ error: err2 instanceof Error ? err2.message : "Failed to send OTP" }, 500);
2921
2817
  }
2922
2818
  }
2923
2819
  });
@@ -2929,17 +2825,18 @@ function emailOtp(config) {
2929
2825
  description: "Verify an OTP code and return a session on success"
2930
2826
  },
2931
2827
  async handler(request) {
2932
- const body = await parseBody5(request);
2933
- const rawEmail = typeof body.email === "string" ? body.email.trim().toLowerCase() : null;
2934
- const code = typeof body.code === "string" ? body.code.trim() : null;
2828
+ const bodyResult = await parseBody(request);
2829
+ if (!bodyResult.ok) return bodyResult.response;
2830
+ const rawEmail = typeof bodyResult.data.email === "string" ? bodyResult.data.email.trim().toLowerCase() : null;
2831
+ const code = typeof bodyResult.data.code === "string" ? bodyResult.data.code.trim() : null;
2935
2832
  if (!rawEmail || !code) {
2936
- return jsonResponse7({ error: "Missing required fields: email, code" }, 400);
2833
+ return json({ error: "Missing required fields: email, code" }, 400);
2937
2834
  }
2938
2835
  const result = await module.verifyCode(rawEmail, code);
2939
2836
  if (!result) {
2940
- return jsonResponse7({ error: "Invalid or expired OTP code" }, 401);
2837
+ return json({ error: "Invalid or expired OTP code" }, 401);
2941
2838
  }
2942
- return jsonResponse7(result);
2839
+ return json(result);
2943
2840
  }
2944
2841
  });
2945
2842
  }
@@ -2950,7 +2847,7 @@ var TOKEN_PURPOSE = "email-verify";
2950
2847
  function makeError(code, message, details) {
2951
2848
  return { code, message, ...details !== void 0 ? { details } : {} };
2952
2849
  }
2953
- function jsonResponse8(body, status = 200) {
2850
+ function jsonResponse4(body, status = 200) {
2954
2851
  return new Response(JSON.stringify(body), {
2955
2852
  status,
2956
2853
  headers: { "Content-Type": "application/json" }
@@ -3042,29 +2939,29 @@ function createEmailVerificationModule(config, db, tokenModule) {
3042
2939
  try {
3043
2940
  body = await request.json();
3044
2941
  } catch {
3045
- return jsonResponse8({ error: "Invalid JSON body" }, 400);
2942
+ return jsonResponse4({ error: "Invalid JSON body" }, 400);
3046
2943
  }
3047
2944
  const b = body;
3048
2945
  if (pathname === "/auth/verify-email/send") {
3049
2946
  if (typeof b.userId !== "string" || typeof b.email !== "string") {
3050
- return jsonResponse8({ error: "Missing required fields: userId, email" }, 400);
2947
+ return jsonResponse4({ error: "Missing required fields: userId, email" }, 400);
3051
2948
  }
3052
2949
  const result = await sendVerification(b.userId, b.email);
3053
2950
  if (!result.success) {
3054
2951
  const status = result.error.code === "USER_NOT_FOUND" ? 404 : 500;
3055
- return jsonResponse8({ error: result.error.message }, status);
2952
+ return jsonResponse4({ error: result.error.message }, status);
3056
2953
  }
3057
2954
  return new Response(null, { status: 204 });
3058
2955
  }
3059
2956
  if (pathname === "/auth/verify-email/confirm") {
3060
2957
  if (typeof b.token !== "string") {
3061
- return jsonResponse8({ error: "Missing required field: token" }, 400);
2958
+ return jsonResponse4({ error: "Missing required field: token" }, 400);
3062
2959
  }
3063
2960
  const result = await verify(b.token);
3064
2961
  if (!result.success) {
3065
- return jsonResponse8({ error: result.error.message }, 400);
2962
+ return jsonResponse4({ error: result.error.message }, 400);
3066
2963
  }
3067
- return jsonResponse8({ userId: result.data.userId, email: result.data.email });
2964
+ return jsonResponse4({ userId: result.data.userId, email: result.data.email });
3068
2965
  }
3069
2966
  return null;
3070
2967
  }
@@ -4098,19 +3995,6 @@ function createGdprModule(db) {
4098
3995
  }
4099
3996
 
4100
3997
  // src/auth/gdpr-plugin.ts
4101
- function jsonResponse9(body, status = 200) {
4102
- return new Response(JSON.stringify(body), {
4103
- status,
4104
- headers: { "Content-Type": "application/json" }
4105
- });
4106
- }
4107
- async function parseBody6(request) {
4108
- try {
4109
- return await request.json();
4110
- } catch {
4111
- return {};
4112
- }
4113
- }
4114
3998
  function gdpr() {
4115
3999
  return {
4116
4000
  id: "kavach-gdpr",
@@ -4126,16 +4010,13 @@ function gdpr() {
4126
4010
  async handler(request, endpointCtx) {
4127
4011
  const user = await endpointCtx.getUser(request);
4128
4012
  if (!user) {
4129
- return jsonResponse9({ error: "Authentication required" }, 401);
4013
+ return json({ error: "Authentication required" }, 401);
4130
4014
  }
4131
4015
  try {
4132
4016
  const data = await module.exportUserData(user.id);
4133
- return jsonResponse9(data);
4017
+ return json(data);
4134
4018
  } catch (err2) {
4135
- return jsonResponse9(
4136
- { error: err2 instanceof Error ? err2.message : "Export failed" },
4137
- 500
4138
- );
4019
+ return json({ error: err2 instanceof Error ? err2.message : "Export failed" }, 500);
4139
4020
  }
4140
4021
  }
4141
4022
  });
@@ -4149,30 +4030,28 @@ function gdpr() {
4149
4030
  async handler(request, endpointCtx) {
4150
4031
  const user = await endpointCtx.getUser(request);
4151
4032
  if (!user) {
4152
- return jsonResponse9({ error: "Authentication required" }, 401);
4033
+ return json({ error: "Authentication required" }, 401);
4153
4034
  }
4154
- const body = await parseBody6(request);
4155
- if (body.confirm !== "delete my account") {
4156
- return jsonResponse9(
4035
+ const bodyResult = await parseBody(request);
4036
+ if (!bodyResult.ok) return bodyResult.response;
4037
+ if (bodyResult.data.confirm !== "delete my account") {
4038
+ return json(
4157
4039
  {
4158
4040
  error: 'Confirmation required. Send { "confirm": "delete my account" } in the request body.'
4159
4041
  },
4160
4042
  400
4161
4043
  );
4162
4044
  }
4163
- const keepAuditLogs = typeof body.keepAuditLogs === "boolean" ? body.keepAuditLogs : true;
4164
- const deleteOrganizations = typeof body.deleteOrganizations === "boolean" ? body.deleteOrganizations : false;
4045
+ const keepAuditLogs = typeof bodyResult.data.keepAuditLogs === "boolean" ? bodyResult.data.keepAuditLogs : true;
4046
+ const deleteOrganizations = typeof bodyResult.data.deleteOrganizations === "boolean" ? bodyResult.data.deleteOrganizations : false;
4165
4047
  try {
4166
4048
  const result = await module.deleteUser(user.id, {
4167
4049
  keepAuditLogs,
4168
4050
  deleteOrganizations
4169
4051
  });
4170
- return jsonResponse9({ success: true, ...result });
4052
+ return json({ success: true, ...result });
4171
4053
  } catch (err2) {
4172
- return jsonResponse9(
4173
- { error: err2 instanceof Error ? err2.message : "Deletion failed" },
4174
- 500
4175
- );
4054
+ return json({ error: err2 instanceof Error ? err2.message : "Deletion failed" }, 500);
4176
4055
  }
4177
4056
  }
4178
4057
  });
@@ -4186,13 +4065,13 @@ function gdpr() {
4186
4065
  async handler(request, endpointCtx) {
4187
4066
  const user = await endpointCtx.getUser(request);
4188
4067
  if (!user) {
4189
- return jsonResponse9({ error: "Authentication required" }, 401);
4068
+ return json({ error: "Authentication required" }, 401);
4190
4069
  }
4191
4070
  try {
4192
4071
  await module.anonymizeUser(user.id);
4193
- return jsonResponse9({ success: true });
4072
+ return json({ success: true });
4194
4073
  } catch (err2) {
4195
- return jsonResponse9(
4074
+ return json(
4196
4075
  { error: err2 instanceof Error ? err2.message : "Anonymization failed" },
4197
4076
  500
4198
4077
  );
@@ -4828,14 +4707,12 @@ function magicLink(config) {
4828
4707
  return {
4829
4708
  id: "kavach-magic-link",
4830
4709
  async init(ctx) {
4831
- const sessionConfig = ctx.config.auth?.session;
4832
- if (!sessionConfig) {
4710
+ if (!ctx.sessionManager) {
4833
4711
  throw new Error(
4834
4712
  "kavach-magic-link plugin requires auth.session to be configured so that sessions can be issued on successful verification."
4835
4713
  );
4836
4714
  }
4837
- const sessionManager = createSessionManager(sessionConfig, ctx.db);
4838
- const module = createMagicLinkModule(config, ctx.db, sessionManager);
4715
+ const module = createMagicLinkModule(config, ctx.db, ctx.sessionManager);
4839
4716
  const sendLimiter = createRateLimiter({ max: 5, window: 60 });
4840
4717
  ctx.addEndpoint({
4841
4718
  method: "POST",
@@ -4845,35 +4722,19 @@ function magicLink(config) {
4845
4722
  description: "Send a magic link to the provided email address"
4846
4723
  },
4847
4724
  handler: withRateLimit(async (request) => {
4848
- let body;
4849
- try {
4850
- body = await request.json();
4851
- } catch {
4852
- return new Response(JSON.stringify({ error: "Invalid JSON body" }), {
4853
- status: 400,
4854
- headers: { "Content-Type": "application/json" }
4855
- });
4856
- }
4857
- const b = body;
4858
- const rawEmail = typeof b.email === "string" ? b.email.trim().toLowerCase() : null;
4725
+ const bodyResult = await parseBody(request);
4726
+ if (!bodyResult.ok) return bodyResult.response;
4727
+ const rawEmail = typeof bodyResult.data.email === "string" ? bodyResult.data.email.trim().toLowerCase() : null;
4859
4728
  if (!rawEmail) {
4860
- return new Response(JSON.stringify({ error: "Missing required field: email" }), {
4861
- status: 400,
4862
- headers: { "Content-Type": "application/json" }
4863
- });
4729
+ return json({ error: "Missing required field: email" }, 400);
4864
4730
  }
4865
4731
  try {
4866
4732
  const result = await module.sendLink(rawEmail);
4867
- return new Response(JSON.stringify(result), {
4868
- status: 200,
4869
- headers: { "Content-Type": "application/json" }
4870
- });
4733
+ return json(result);
4871
4734
  } catch (err2) {
4872
- return new Response(
4873
- JSON.stringify({
4874
- error: err2 instanceof Error ? err2.message : "Failed to send magic link"
4875
- }),
4876
- { status: 500, headers: { "Content-Type": "application/json" } }
4735
+ return json(
4736
+ { error: err2 instanceof Error ? err2.message : "Failed to send magic link" },
4737
+ 500
4877
4738
  );
4878
4739
  }
4879
4740
  }, sendLimiter)
@@ -4888,22 +4749,13 @@ function magicLink(config) {
4888
4749
  const url = new URL(request.url);
4889
4750
  const token = url.searchParams.get("token");
4890
4751
  if (!token) {
4891
- return new Response(JSON.stringify({ error: "Missing token query parameter" }), {
4892
- status: 400,
4893
- headers: { "Content-Type": "application/json" }
4894
- });
4752
+ return json({ error: "Missing token query parameter" }, 400);
4895
4753
  }
4896
4754
  const result = await module.verify(token);
4897
4755
  if (!result) {
4898
- return new Response(JSON.stringify({ error: "Invalid or expired magic link" }), {
4899
- status: 401,
4900
- headers: { "Content-Type": "application/json" }
4901
- });
4756
+ return json({ error: "Invalid or expired magic link" }, 401);
4902
4757
  }
4903
- return new Response(JSON.stringify(result), {
4904
- status: 200,
4905
- headers: { "Content-Type": "application/json" }
4906
- });
4758
+ return json(result);
4907
4759
  }
4908
4760
  });
4909
4761
  }
@@ -5128,7 +4980,7 @@ function createOAuthModule(db, config) {
5128
4980
  pruneExpiredStates
5129
4981
  };
5130
4982
  }
5131
- function jsonResponse10(body, status = 200) {
4983
+ function jsonResponse5(body, status = 200) {
5132
4984
  return new Response(JSON.stringify(body), {
5133
4985
  status,
5134
4986
  headers: { "Content-Type": "application/json" }
@@ -5146,8 +4998,12 @@ function oauth(config) {
5146
4998
  async init(ctx) {
5147
4999
  const module = createOAuthModule(ctx.db, config);
5148
5000
  const baseUrl = ctx.config.baseUrl ?? "";
5149
- const sessionConfig = ctx.config.auth?.session;
5150
- const sessionManager = sessionConfig ? createSessionManager(sessionConfig, ctx.db) : null;
5001
+ const sessionManager = ctx.sessionManager;
5002
+ if (!sessionManager) {
5003
+ throw new Error(
5004
+ "kavach-oauth plugin requires auth.session to be configured so that sessions can be issued on successful OAuth callback."
5005
+ );
5006
+ }
5151
5007
  const authorizeLimiter = createRateLimiter({ max: 20, window: 60 });
5152
5008
  function getRedirectUri(provider) {
5153
5009
  if (config.buildRedirectUri) {
@@ -5166,14 +5022,14 @@ function oauth(config) {
5166
5022
  const url = new URL(request.url);
5167
5023
  const provider = url.searchParams.get("_param_provider");
5168
5024
  if (!provider) {
5169
- return jsonResponse10({ error: "Missing provider parameter" }, 400);
5025
+ return jsonResponse5({ error: "Missing provider parameter" }, 400);
5170
5026
  }
5171
5027
  const redirectUri = getRedirectUri(provider);
5172
5028
  try {
5173
5029
  const { url: authUrl } = await module.getAuthorizationUrl(provider, redirectUri);
5174
5030
  return redirectResponse(authUrl);
5175
5031
  } catch (err2) {
5176
- return jsonResponse10(
5032
+ return jsonResponse5(
5177
5033
  { error: err2 instanceof Error ? err2.message : "Failed to build authorization URL" },
5178
5034
  400
5179
5035
  );
@@ -5190,10 +5046,10 @@ function oauth(config) {
5190
5046
  const code = url.searchParams.get("code");
5191
5047
  const state = url.searchParams.get("state");
5192
5048
  if (!provider) {
5193
- return jsonResponse10({ error: "Missing provider parameter" }, 400);
5049
+ return jsonResponse5({ error: "Missing provider parameter" }, 400);
5194
5050
  }
5195
5051
  if (!code || !state) {
5196
- return jsonResponse10({ error: "Missing code or state query parameter" }, 400);
5052
+ return jsonResponse5({ error: "Missing code or state query parameter" }, 400);
5197
5053
  }
5198
5054
  const redirectUri = getRedirectUri(provider);
5199
5055
  try {
@@ -5225,18 +5081,27 @@ function oauth(config) {
5225
5081
  raw: {}
5226
5082
  });
5227
5083
  }
5228
- if (sessionManager && userId !== "__pending__") {
5084
+ if (userId !== "__pending__") {
5229
5085
  const { session, token } = await sessionManager.create(userId);
5230
- const callbackUrl = `${baseUrl}/?session=${encodeURIComponent(JSON.stringify({ token, user: { id: userId, email }, expiresAt: session.expiresAt }))}`;
5231
- return redirectResponse(callbackUrl);
5086
+ const maxAge = Math.floor((session.expiresAt.getTime() - Date.now()) / 1e3);
5087
+ const cookie = buildSetCookie("kavach_session", token, maxAge);
5088
+ const userInfo = encodeURIComponent(JSON.stringify({ id: userId, email }));
5089
+ const callbackUrl = `${baseUrl}/?auth_user=${userInfo}`;
5090
+ return new Response(null, {
5091
+ status: 302,
5092
+ headers: {
5093
+ Location: callbackUrl,
5094
+ "Set-Cookie": cookie
5095
+ }
5096
+ });
5232
5097
  }
5233
- return jsonResponse10({
5098
+ return jsonResponse5({
5234
5099
  isNewAccount: result.isNewAccount,
5235
5100
  account: result.account,
5236
5101
  userInfo: result.userInfo
5237
5102
  });
5238
5103
  } catch (err2) {
5239
- return jsonResponse10(
5104
+ return jsonResponse5(
5240
5105
  { error: err2 instanceof Error ? err2.message : "OAuth callback failed" },
5241
5106
  400
5242
5107
  );
@@ -5253,29 +5118,29 @@ function oauth(config) {
5253
5118
  async handler(request, endpointCtx) {
5254
5119
  const user = await endpointCtx.getUser(request);
5255
5120
  if (!user) {
5256
- return jsonResponse10({ error: "Authentication required" }, 401);
5121
+ return jsonResponse5({ error: "Authentication required" }, 401);
5257
5122
  }
5258
5123
  let body;
5259
5124
  try {
5260
5125
  body = await request.json();
5261
5126
  } catch {
5262
- return jsonResponse10({ error: "Invalid JSON body" }, 400);
5127
+ return jsonResponse5({ error: "Invalid JSON body" }, 400);
5263
5128
  }
5264
5129
  const b = body;
5265
5130
  const provider = typeof b.provider === "string" ? b.provider : null;
5266
5131
  const userInfo = typeof b.userInfo === "object" && b.userInfo !== null ? b.userInfo : null;
5267
5132
  const tokens = typeof b.tokens === "object" && b.tokens !== null ? b.tokens : null;
5268
5133
  if (!provider || !userInfo || !tokens) {
5269
- return jsonResponse10(
5134
+ return jsonResponse5(
5270
5135
  { error: "Missing required fields: provider, userInfo, tokens" },
5271
5136
  400
5272
5137
  );
5273
5138
  }
5274
5139
  try {
5275
5140
  const account = await module.linkAccount(user.id, provider, userInfo, tokens);
5276
- return jsonResponse10({ account });
5141
+ return jsonResponse5({ account });
5277
5142
  } catch (err2) {
5278
- return jsonResponse10(
5143
+ return jsonResponse5(
5279
5144
  { error: err2 instanceof Error ? err2.message : "Failed to link account" },
5280
5145
  400
5281
5146
  );
@@ -5291,7 +5156,7 @@ function oauth(config) {
5291
5156
  id: p.id,
5292
5157
  name: p.name
5293
5158
  }));
5294
- return jsonResponse10({ providers });
5159
+ return jsonResponse5({ providers });
5295
5160
  }
5296
5161
  });
5297
5162
  }
@@ -7088,25 +6953,25 @@ function createOneTapModule(config, db, sessionManager) {
7088
6953
  const text3 = await request.text();
7089
6954
  formData = new URLSearchParams(text3);
7090
6955
  } catch {
7091
- return jsonResponse11({ error: "Failed to parse request body" }, 400);
6956
+ return jsonResponse6({ error: "Failed to parse request body" }, 400);
7092
6957
  }
7093
6958
  const credential = formData.get("credential");
7094
6959
  const bodyToken = formData.get(csrfCookieName);
7095
6960
  if (!credential) {
7096
- return jsonResponse11({ error: "Missing credential field" }, 400);
6961
+ return jsonResponse6({ error: "Missing credential field" }, 400);
7097
6962
  }
7098
6963
  const cookieToken = getCsrfCookie(request);
7099
6964
  if (!cookieToken || !bodyToken || cookieToken !== bodyToken) {
7100
- return jsonResponse11({ error: "CSRF token mismatch" }, 403);
6965
+ return jsonResponse6({ error: "CSRF token mismatch" }, 403);
7101
6966
  }
7102
6967
  let googleUser;
7103
6968
  try {
7104
6969
  googleUser = await verify(credential);
7105
6970
  } catch (err2) {
7106
6971
  if (err2 instanceof OneTapVerifyError && err2.code === "USER_NOT_FOUND") {
7107
- return jsonResponse11({ error: err2.message }, 403);
6972
+ return jsonResponse6({ error: err2.message }, 403);
7108
6973
  }
7109
- return jsonResponse11(
6974
+ return jsonResponse6(
7110
6975
  { error: err2 instanceof Error ? err2.message : "Token verification failed" },
7111
6976
  401
7112
6977
  );
@@ -7116,27 +6981,96 @@ function createOneTapModule(config, db, sessionManager) {
7116
6981
  user = await findOrCreateUser(googleUser);
7117
6982
  } catch (err2) {
7118
6983
  if (err2 instanceof OneTapVerifyError && err2.code === "USER_NOT_FOUND") {
7119
- return jsonResponse11({ error: err2.message }, 403);
6984
+ return jsonResponse6({ error: err2.message }, 403);
7120
6985
  }
7121
- return jsonResponse11(
6986
+ return jsonResponse6(
7122
6987
  { error: err2 instanceof Error ? err2.message : "Failed to resolve user" },
7123
6988
  500
7124
6989
  );
7125
6990
  }
7126
6991
  const { token: sessionToken, session } = await sessionManager.create(user.id);
7127
- return jsonResponse11({
6992
+ return jsonResponse6({
7128
6993
  user: { id: user.id, email: user.email },
7129
6994
  session: { token: sessionToken, expiresAt: session.expiresAt }
7130
6995
  });
7131
6996
  }
7132
6997
  return { verify, handleRequest };
7133
6998
  }
7134
- function jsonResponse11(body, status = 200) {
6999
+ function jsonResponse6(body, status = 200) {
7135
7000
  return new Response(JSON.stringify(body), {
7136
7001
  status,
7137
7002
  headers: { "Content-Type": "application/json" }
7138
7003
  });
7139
7004
  }
7005
+ var DEFAULT_MAX_AGE_SECONDS = 60 * 60 * 24 * 7;
7006
+ function createSessionManager(config, db) {
7007
+ if (!config.secret || config.secret.length < 32) {
7008
+ throw new Error("SessionManager: secret must be at least 32 characters.");
7009
+ }
7010
+ const maxAge = config.maxAge ?? DEFAULT_MAX_AGE_SECONDS;
7011
+ const keyObject = new TextEncoder().encode(config.secret);
7012
+ function rowToSession2(row) {
7013
+ return {
7014
+ id: row.id,
7015
+ userId: row.userId,
7016
+ expiresAt: row.expiresAt,
7017
+ createdAt: row.createdAt,
7018
+ ...row.metadata !== null && { metadata: row.metadata }
7019
+ };
7020
+ }
7021
+ async function create(userId, metadata) {
7022
+ const id = generateId();
7023
+ const now = /* @__PURE__ */ new Date();
7024
+ const expiresAt = new Date(now.getTime() + maxAge * 1e3);
7025
+ await db.insert(sessions).values({
7026
+ id,
7027
+ userId,
7028
+ expiresAt,
7029
+ metadata: metadata ?? null,
7030
+ createdAt: now
7031
+ });
7032
+ const token = await new SignJWT({ sub: id }).setProtectedHeader({ alg: "HS256" }).setIssuedAt().setExpirationTime(Math.floor(expiresAt.getTime() / 1e3)).sign(keyObject);
7033
+ const session = {
7034
+ id,
7035
+ userId,
7036
+ expiresAt,
7037
+ createdAt: now,
7038
+ ...metadata !== void 0 && { metadata }
7039
+ };
7040
+ return { session, token };
7041
+ }
7042
+ async function validate(token) {
7043
+ let sessionId;
7044
+ try {
7045
+ const { payload } = await jwtVerify(token, keyObject);
7046
+ if (typeof payload.sub !== "string" || !payload.sub) return null;
7047
+ sessionId = payload.sub;
7048
+ } catch {
7049
+ return null;
7050
+ }
7051
+ const now = /* @__PURE__ */ new Date();
7052
+ const rows = await db.select().from(sessions).where(and(eq(sessions.id, sessionId)));
7053
+ const row = rows[0];
7054
+ if (!row) return null;
7055
+ if (row.expiresAt <= now) {
7056
+ await db.delete(sessions).where(eq(sessions.id, sessionId));
7057
+ return null;
7058
+ }
7059
+ return rowToSession2(row);
7060
+ }
7061
+ async function revoke(sessionId) {
7062
+ await db.delete(sessions).where(eq(sessions.id, sessionId));
7063
+ }
7064
+ async function revokeAll(userId) {
7065
+ await db.delete(sessions).where(eq(sessions.userId, userId));
7066
+ }
7067
+ async function list(userId) {
7068
+ const now = /* @__PURE__ */ new Date();
7069
+ const rows = await db.select().from(sessions).where(and(eq(sessions.userId, userId)));
7070
+ return rows.filter((row) => row.expiresAt > now).sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()).map(rowToSession2);
7071
+ }
7072
+ return { create, validate, revoke, revokeAll, list };
7073
+ }
7140
7074
 
7141
7075
  // src/auth/one-tap-plugin.ts
7142
7076
  function oneTap(config) {
@@ -8428,14 +8362,14 @@ function rowToInvitation(row) {
8428
8362
  createdAt: row.createdAt
8429
8363
  };
8430
8364
  }
8431
- function jsonResponse12(body, status = 200) {
8365
+ function jsonResponse7(body, status = 200) {
8432
8366
  return new Response(JSON.stringify(body), {
8433
8367
  status,
8434
8368
  headers: { "Content-Type": "application/json" }
8435
8369
  });
8436
8370
  }
8437
8371
  function errorResponse(message, status) {
8438
- return jsonResponse12({ error: message }, status);
8372
+ return jsonResponse7({ error: message }, status);
8439
8373
  }
8440
8374
  function createOrgModule(config, db) {
8441
8375
  const maxMembers = config.maxMembers ?? DEFAULT_MAX_MEMBERS;
@@ -8741,7 +8675,7 @@ function createOrgModule(config, db) {
8741
8675
  try {
8742
8676
  const body = await request.json();
8743
8677
  const org = await create(body);
8744
- return jsonResponse12(org, 201);
8678
+ return jsonResponse7(org, 201);
8745
8679
  } catch (err2) {
8746
8680
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
8747
8681
  }
@@ -8751,7 +8685,7 @@ function createOrgModule(config, db) {
8751
8685
  const userId = userOrgMatch[1];
8752
8686
  if (!userId) return errorResponse("Missing userId", 400);
8753
8687
  const orgs = await list(userId);
8754
- return jsonResponse12(orgs);
8688
+ return jsonResponse7(orgs);
8755
8689
  }
8756
8690
  const orgBaseMatch = pathname.match(/^\/auth\/org\/([^/]+)(\/.*)?$/);
8757
8691
  if (!orgBaseMatch) return null;
@@ -8761,13 +8695,13 @@ function createOrgModule(config, db) {
8761
8695
  if (method === "GET" && subPath === "") {
8762
8696
  const org = await get(orgId);
8763
8697
  if (!org) return errorResponse("Organization not found", 404);
8764
- return jsonResponse12(org);
8698
+ return jsonResponse7(org);
8765
8699
  }
8766
8700
  if (method === "PATCH" && subPath === "") {
8767
8701
  try {
8768
8702
  const body = await request.json();
8769
8703
  const org = await update(orgId, body);
8770
- return jsonResponse12(org);
8704
+ return jsonResponse7(org);
8771
8705
  } catch (err2) {
8772
8706
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
8773
8707
  }
@@ -8775,7 +8709,7 @@ function createOrgModule(config, db) {
8775
8709
  if (method === "DELETE" && subPath === "") {
8776
8710
  try {
8777
8711
  await remove(orgId);
8778
- return jsonResponse12({ success: true });
8712
+ return jsonResponse7({ success: true });
8779
8713
  } catch (err2) {
8780
8714
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
8781
8715
  }
@@ -8784,14 +8718,14 @@ function createOrgModule(config, db) {
8784
8718
  try {
8785
8719
  const body = await request.json();
8786
8720
  const member = await addMember(orgId, body.userId, body.role);
8787
- return jsonResponse12(member, 201);
8721
+ return jsonResponse7(member, 201);
8788
8722
  } catch (err2) {
8789
8723
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
8790
8724
  }
8791
8725
  }
8792
8726
  if (method === "GET" && subPath === "/members") {
8793
8727
  const members = await getMembers(orgId);
8794
- return jsonResponse12(members);
8728
+ return jsonResponse7(members);
8795
8729
  }
8796
8730
  const memberMatch = subPath.match(/^\/members\/([^/]+)$/);
8797
8731
  if (method === "PATCH" && memberMatch) {
@@ -8800,7 +8734,7 @@ function createOrgModule(config, db) {
8800
8734
  try {
8801
8735
  const body = await request.json();
8802
8736
  const member = await updateMemberRole(orgId, userId, body.role);
8803
- return jsonResponse12(member);
8737
+ return jsonResponse7(member);
8804
8738
  } catch (err2) {
8805
8739
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
8806
8740
  }
@@ -8809,20 +8743,20 @@ function createOrgModule(config, db) {
8809
8743
  const userId = memberMatch[1];
8810
8744
  if (!userId) return errorResponse("Missing userId", 400);
8811
8745
  await removeMember(orgId, userId);
8812
- return jsonResponse12({ success: true });
8746
+ return jsonResponse7({ success: true });
8813
8747
  }
8814
8748
  if (method === "POST" && subPath === "/invite") {
8815
8749
  try {
8816
8750
  const body = await request.json();
8817
8751
  const invitation = await invite({ orgId, ...body });
8818
- return jsonResponse12(invitation, 201);
8752
+ return jsonResponse7(invitation, 201);
8819
8753
  } catch (err2) {
8820
8754
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
8821
8755
  }
8822
8756
  }
8823
8757
  if (method === "GET" && subPath === "/invitations") {
8824
8758
  const invitations = await listInvitations(orgId);
8825
- return jsonResponse12(invitations);
8759
+ return jsonResponse7(invitations);
8826
8760
  }
8827
8761
  const permMatch = subPath.match(/^\/permissions\/([^/]+)\/([^/]+)$/);
8828
8762
  if (method === "GET" && permMatch) {
@@ -8830,20 +8764,20 @@ function createOrgModule(config, db) {
8830
8764
  const permission = permMatch[2];
8831
8765
  if (!userId || !permission) return errorResponse("Missing userId or permission", 400);
8832
8766
  const allowed = await hasPermission(orgId, userId, permission);
8833
- return jsonResponse12({ allowed });
8767
+ return jsonResponse7({ allowed });
8834
8768
  }
8835
8769
  if (method === "POST" && subPath === "/roles") {
8836
8770
  try {
8837
8771
  const body = await request.json();
8838
8772
  const role = await createRole(orgId, body);
8839
- return jsonResponse12(role, 201);
8773
+ return jsonResponse7(role, 201);
8840
8774
  } catch (err2) {
8841
8775
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
8842
8776
  }
8843
8777
  }
8844
8778
  if (method === "GET" && subPath === "/roles") {
8845
8779
  const roles = await getRoles(orgId);
8846
- return jsonResponse12(roles);
8780
+ return jsonResponse7(roles);
8847
8781
  }
8848
8782
  return null;
8849
8783
  }
@@ -8858,7 +8792,7 @@ function createOrgModule(config, db) {
8858
8792
  try {
8859
8793
  const body = await request.json();
8860
8794
  const member = await acceptInvitation(invitationId, body.userId);
8861
- return jsonResponse12(member, 201);
8795
+ return jsonResponse7(member, 201);
8862
8796
  } catch (err2) {
8863
8797
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
8864
8798
  }
@@ -8868,7 +8802,7 @@ function createOrgModule(config, db) {
8868
8802
  const invitationId = revokeMatch[1];
8869
8803
  if (!invitationId) return errorResponse("Missing invitationId", 400);
8870
8804
  await revokeInvitation(invitationId);
8871
- return jsonResponse12({ success: true });
8805
+ return jsonResponse7({ success: true });
8872
8806
  }
8873
8807
  return handleRequest(request);
8874
8808
  }
@@ -8899,13 +8833,13 @@ function createOrgModule(config, db) {
8899
8833
  }
8900
8834
 
8901
8835
  // src/auth/organization-plugin.ts
8902
- function jsonResponse13(body, status = 200) {
8836
+ function jsonResponse8(body, status = 200) {
8903
8837
  return new Response(JSON.stringify(body), {
8904
8838
  status,
8905
8839
  headers: { "Content-Type": "application/json" }
8906
8840
  });
8907
8841
  }
8908
- async function parseBody7(request) {
8842
+ async function parseBody3(request) {
8909
8843
  try {
8910
8844
  return await request.json();
8911
8845
  } catch {
@@ -8928,20 +8862,20 @@ function organization(config) {
8928
8862
  async handler(request, endpointCtx) {
8929
8863
  const user = await endpointCtx.getUser(request);
8930
8864
  if (!user) {
8931
- return jsonResponse13({ error: "Authentication required" }, 401);
8865
+ return jsonResponse8({ error: "Authentication required" }, 401);
8932
8866
  }
8933
- const body = await parseBody7(request);
8867
+ const body = await parseBody3(request);
8934
8868
  const name = typeof body.name === "string" ? body.name.trim() : null;
8935
8869
  const slug = typeof body.slug === "string" ? body.slug.trim() : null;
8936
8870
  if (!name || !slug) {
8937
- return jsonResponse13({ error: "Missing required fields: name, slug" }, 400);
8871
+ return jsonResponse8({ error: "Missing required fields: name, slug" }, 400);
8938
8872
  }
8939
8873
  const metadata = body.metadata !== void 0 && typeof body.metadata === "object" && body.metadata !== null ? body.metadata : void 0;
8940
8874
  try {
8941
8875
  const org = await module.create({ name, slug, ownerId: user.id, metadata });
8942
- return jsonResponse13(org, 201);
8876
+ return jsonResponse8(org, 201);
8943
8877
  } catch (err2) {
8944
- return jsonResponse13(
8878
+ return jsonResponse8(
8945
8879
  { error: err2 instanceof Error ? err2.message : "Failed to create organization" },
8946
8880
  400
8947
8881
  );
@@ -8958,10 +8892,10 @@ function organization(config) {
8958
8892
  async handler(request, endpointCtx) {
8959
8893
  const user = await endpointCtx.getUser(request);
8960
8894
  if (!user) {
8961
- return jsonResponse13({ error: "Authentication required" }, 401);
8895
+ return jsonResponse8({ error: "Authentication required" }, 401);
8962
8896
  }
8963
8897
  const orgs = await module.list(user.id);
8964
- return jsonResponse13({ organizations: orgs });
8898
+ return jsonResponse8({ organizations: orgs });
8965
8899
  }
8966
8900
  });
8967
8901
  ctx.addEndpoint({
@@ -8974,23 +8908,23 @@ function organization(config) {
8974
8908
  async handler(request, endpointCtx) {
8975
8909
  const user = await endpointCtx.getUser(request);
8976
8910
  if (!user) {
8977
- return jsonResponse13({ error: "Authentication required" }, 401);
8911
+ return jsonResponse8({ error: "Authentication required" }, 401);
8978
8912
  }
8979
8913
  const url = new URL(request.url);
8980
8914
  const segments = url.pathname.split("/").filter(Boolean);
8981
8915
  const orgId = segments[2];
8982
8916
  if (!orgId) {
8983
- return jsonResponse13({ error: "Missing organization ID in path" }, 400);
8917
+ return jsonResponse8({ error: "Missing organization ID in path" }, 400);
8984
8918
  }
8985
8919
  const member = await module.getMember(orgId, user.id);
8986
8920
  if (!member || !ADMIN_ROLES.has(member.role)) {
8987
- return jsonResponse13({ error: "Admin or owner role required" }, 403);
8921
+ return jsonResponse8({ error: "Admin or owner role required" }, 403);
8988
8922
  }
8989
- const body = await parseBody7(request);
8923
+ const body = await parseBody3(request);
8990
8924
  const email = typeof body.email === "string" ? body.email.trim().toLowerCase() : null;
8991
8925
  const role = typeof body.role === "string" ? body.role : "member";
8992
8926
  if (!email) {
8993
- return jsonResponse13({ error: "Missing required field: email" }, 400);
8927
+ return jsonResponse8({ error: "Missing required field: email" }, 400);
8994
8928
  }
8995
8929
  try {
8996
8930
  const invitation = await module.invite({
@@ -8999,9 +8933,9 @@ function organization(config) {
8999
8933
  role,
9000
8934
  invitedBy: user.id
9001
8935
  });
9002
- return jsonResponse13(invitation, 201);
8936
+ return jsonResponse8(invitation, 201);
9003
8937
  } catch (err2) {
9004
- return jsonResponse13(
8938
+ return jsonResponse8(
9005
8939
  { error: err2 instanceof Error ? err2.message : "Failed to send invitation" },
9006
8940
  400
9007
8941
  );
@@ -9018,20 +8952,20 @@ function organization(config) {
9018
8952
  async handler(request, endpointCtx) {
9019
8953
  const user = await endpointCtx.getUser(request);
9020
8954
  if (!user) {
9021
- return jsonResponse13({ error: "Authentication required" }, 401);
8955
+ return jsonResponse8({ error: "Authentication required" }, 401);
9022
8956
  }
9023
8957
  const url = new URL(request.url);
9024
8958
  const segments = url.pathname.split("/").filter(Boolean);
9025
8959
  const orgId = segments[2];
9026
8960
  if (!orgId) {
9027
- return jsonResponse13({ error: "Missing organization ID in path" }, 400);
8961
+ return jsonResponse8({ error: "Missing organization ID in path" }, 400);
9028
8962
  }
9029
8963
  const callerMember = await module.getMember(orgId, user.id);
9030
8964
  if (!callerMember) {
9031
- return jsonResponse13({ error: "You are not a member of this organization" }, 403);
8965
+ return jsonResponse8({ error: "You are not a member of this organization" }, 403);
9032
8966
  }
9033
8967
  const members = await module.getMembers(orgId);
9034
- return jsonResponse13({ members });
8968
+ return jsonResponse8({ members });
9035
8969
  }
9036
8970
  });
9037
8971
  ctx.addEndpoint({
@@ -9044,29 +8978,29 @@ function organization(config) {
9044
8978
  async handler(request, endpointCtx) {
9045
8979
  const user = await endpointCtx.getUser(request);
9046
8980
  if (!user) {
9047
- return jsonResponse13({ error: "Authentication required" }, 401);
8981
+ return jsonResponse8({ error: "Authentication required" }, 401);
9048
8982
  }
9049
8983
  const url = new URL(request.url);
9050
8984
  const segments = url.pathname.split("/").filter(Boolean);
9051
8985
  const orgId = segments[2];
9052
8986
  const targetUserId = segments[4];
9053
8987
  if (!orgId || !targetUserId) {
9054
- return jsonResponse13({ error: "Missing organization ID or user ID in path" }, 400);
8988
+ return jsonResponse8({ error: "Missing organization ID or user ID in path" }, 400);
9055
8989
  }
9056
8990
  const callerMember = await module.getMember(orgId, user.id);
9057
8991
  if (!callerMember || !ADMIN_ROLES.has(callerMember.role)) {
9058
- return jsonResponse13({ error: "Admin or owner role required" }, 403);
8992
+ return jsonResponse8({ error: "Admin or owner role required" }, 403);
9059
8993
  }
9060
- const body = await parseBody7(request);
8994
+ const body = await parseBody3(request);
9061
8995
  const role = typeof body.role === "string" ? body.role : null;
9062
8996
  if (!role) {
9063
- return jsonResponse13({ error: "Missing required field: role" }, 400);
8997
+ return jsonResponse8({ error: "Missing required field: role" }, 400);
9064
8998
  }
9065
8999
  try {
9066
9000
  const member = await module.updateMemberRole(orgId, targetUserId, role);
9067
- return jsonResponse13(member);
9001
+ return jsonResponse8(member);
9068
9002
  } catch (err2) {
9069
- return jsonResponse13(
9003
+ return jsonResponse8(
9070
9004
  { error: err2 instanceof Error ? err2.message : "Failed to update member role" },
9071
9005
  400
9072
9006
  );
@@ -9083,24 +9017,24 @@ function organization(config) {
9083
9017
  async handler(request, endpointCtx) {
9084
9018
  const user = await endpointCtx.getUser(request);
9085
9019
  if (!user) {
9086
- return jsonResponse13({ error: "Authentication required" }, 401);
9020
+ return jsonResponse8({ error: "Authentication required" }, 401);
9087
9021
  }
9088
9022
  const url = new URL(request.url);
9089
9023
  const segments = url.pathname.split("/").filter(Boolean);
9090
9024
  const orgId = segments[2];
9091
9025
  const targetUserId = segments[4];
9092
9026
  if (!orgId || !targetUserId) {
9093
- return jsonResponse13({ error: "Missing organization ID or user ID in path" }, 400);
9027
+ return jsonResponse8({ error: "Missing organization ID or user ID in path" }, 400);
9094
9028
  }
9095
9029
  const callerMember = await module.getMember(orgId, user.id);
9096
9030
  if (!callerMember || !ADMIN_ROLES.has(callerMember.role)) {
9097
- return jsonResponse13({ error: "Admin or owner role required" }, 403);
9031
+ return jsonResponse8({ error: "Admin or owner role required" }, 403);
9098
9032
  }
9099
9033
  try {
9100
9034
  await module.removeMember(orgId, targetUserId);
9101
- return jsonResponse13({ removed: true });
9035
+ return jsonResponse8({ removed: true });
9102
9036
  } catch (err2) {
9103
- return jsonResponse13(
9037
+ return jsonResponse8(
9104
9038
  { error: err2 instanceof Error ? err2.message : "Failed to remove member" },
9105
9039
  400
9106
9040
  );
@@ -9505,13 +9439,13 @@ function parseAuthData(authData) {
9505
9439
  }
9506
9440
  return { rpIdHash, flags, signCount, attestedCredentialData };
9507
9441
  }
9508
- function jsonResponse14(body, status = 200) {
9442
+ function jsonResponse9(body, status = 200) {
9509
9443
  return new Response(JSON.stringify(body), {
9510
9444
  status,
9511
9445
  headers: { "Content-Type": "application/json" }
9512
9446
  });
9513
9447
  }
9514
- async function parseBody8(request) {
9448
+ async function parseBody4(request) {
9515
9449
  try {
9516
9450
  return await request.json();
9517
9451
  } catch {
@@ -9849,84 +9783,84 @@ function createPasskeyModule(config, db) {
9849
9783
  const method = request.method.toUpperCase();
9850
9784
  const segments = getPathSegments(url);
9851
9785
  if (method === "POST" && segments.length === 4 && segments[1] === "passkey" && segments[2] === "register" && segments[3] === "options") {
9852
- const body = await parseBody8(request);
9786
+ const body = await parseBody4(request);
9853
9787
  const userId = typeof body.userId === "string" ? body.userId : null;
9854
9788
  const userName = typeof body.userName === "string" ? body.userName : null;
9855
9789
  if (!userId || !userName) {
9856
- return jsonResponse14({ error: "userId and userName required" }, 400);
9790
+ return jsonResponse9({ error: "userId and userName required" }, 400);
9857
9791
  }
9858
9792
  try {
9859
9793
  const options = await getRegistrationOptions(userId, userName);
9860
- return jsonResponse14(options);
9794
+ return jsonResponse9(options);
9861
9795
  } catch (err2) {
9862
9796
  const message = err2 instanceof Error ? err2.message : "Failed to generate options";
9863
9797
  const code = err2 instanceof PasskeyError ? err2.code : "INTERNAL_ERROR";
9864
- return jsonResponse14({ error: message, code }, 500);
9798
+ return jsonResponse9({ error: message, code }, 500);
9865
9799
  }
9866
9800
  }
9867
9801
  if (method === "POST" && segments.length === 4 && segments[1] === "passkey" && segments[2] === "register" && segments[3] === "verify") {
9868
- const body = await parseBody8(request);
9802
+ const body = await parseBody4(request);
9869
9803
  const userId = typeof body.userId === "string" ? body.userId : null;
9870
- if (!userId) return jsonResponse14({ error: "userId required" }, 400);
9804
+ if (!userId) return jsonResponse9({ error: "userId required" }, 400);
9871
9805
  const resp = body.response;
9872
- if (!resp) return jsonResponse14({ error: "response required" }, 400);
9806
+ if (!resp) return jsonResponse9({ error: "response required" }, 400);
9873
9807
  try {
9874
9808
  const result = await verifyRegistration(userId, resp);
9875
- return jsonResponse14(result);
9809
+ return jsonResponse9(result);
9876
9810
  } catch (err2) {
9877
9811
  const message = err2 instanceof Error ? err2.message : "Registration failed";
9878
9812
  const code = err2 instanceof PasskeyError ? err2.code : "INTERNAL_ERROR";
9879
- return jsonResponse14({ error: message, code }, 400);
9813
+ return jsonResponse9({ error: message, code }, 400);
9880
9814
  }
9881
9815
  }
9882
9816
  if (method === "POST" && segments.length === 4 && segments[1] === "passkey" && segments[2] === "login" && segments[3] === "options") {
9883
- const body = await parseBody8(request);
9817
+ const body = await parseBody4(request);
9884
9818
  const userId = typeof body.userId === "string" ? body.userId : void 0;
9885
9819
  try {
9886
9820
  const options = await getAuthenticationOptions(userId);
9887
- return jsonResponse14(options);
9821
+ return jsonResponse9(options);
9888
9822
  } catch (err2) {
9889
9823
  const message = err2 instanceof Error ? err2.message : "Failed to generate options";
9890
9824
  const code = err2 instanceof PasskeyError ? err2.code : "INTERNAL_ERROR";
9891
- return jsonResponse14({ error: message, code }, 500);
9825
+ return jsonResponse9({ error: message, code }, 500);
9892
9826
  }
9893
9827
  }
9894
9828
  if (method === "POST" && segments.length === 4 && segments[1] === "passkey" && segments[2] === "login" && segments[3] === "verify") {
9895
- const body = await parseBody8(request);
9829
+ const body = await parseBody4(request);
9896
9830
  const resp = body.response;
9897
- if (!resp) return jsonResponse14({ error: "response required" }, 400);
9831
+ if (!resp) return jsonResponse9({ error: "response required" }, 400);
9898
9832
  try {
9899
9833
  const result = await verifyAuthentication(resp);
9900
- return jsonResponse14(result);
9834
+ return jsonResponse9(result);
9901
9835
  } catch (err2) {
9902
9836
  const message = err2 instanceof Error ? err2.message : "Authentication failed";
9903
9837
  const code = err2 instanceof PasskeyError ? err2.code : "INTERNAL_ERROR";
9904
- return jsonResponse14({ error: message, code }, 401);
9838
+ return jsonResponse9({ error: message, code }, 401);
9905
9839
  }
9906
9840
  }
9907
9841
  if (method === "GET" && segments.length === 3 && segments[1] === "passkey" && segments[2] === "credentials") {
9908
9842
  const userId = url.searchParams.get("userId");
9909
- if (!userId) return jsonResponse14({ error: "userId query param required" }, 400);
9843
+ if (!userId) return jsonResponse9({ error: "userId query param required" }, 400);
9910
9844
  try {
9911
9845
  const creds = await listCredentials(userId);
9912
- return jsonResponse14({ credentials: creds });
9846
+ return jsonResponse9({ credentials: creds });
9913
9847
  } catch (err2) {
9914
9848
  const message = err2 instanceof Error ? err2.message : "Failed to list credentials";
9915
- return jsonResponse14({ error: message }, 500);
9849
+ return jsonResponse9({ error: message }, 500);
9916
9850
  }
9917
9851
  }
9918
9852
  if (method === "DELETE" && segments.length === 4 && segments[1] === "passkey" && segments[2] === "credentials") {
9919
9853
  const credentialId = segments[3];
9920
- if (!credentialId) return jsonResponse14({ error: "Credential ID required" }, 400);
9921
- const body = await parseBody8(request);
9854
+ if (!credentialId) return jsonResponse9({ error: "Credential ID required" }, 400);
9855
+ const body = await parseBody4(request);
9922
9856
  const userId = typeof body.userId === "string" ? body.userId : null;
9923
- if (!userId) return jsonResponse14({ error: "userId required" }, 400);
9857
+ if (!userId) return jsonResponse9({ error: "userId required" }, 400);
9924
9858
  try {
9925
9859
  await removeCredential(credentialId, userId);
9926
- return jsonResponse14({ removed: true });
9860
+ return jsonResponse9({ removed: true });
9927
9861
  } catch (err2) {
9928
9862
  const message = err2 instanceof Error ? err2.message : "Failed to remove credential";
9929
- return jsonResponse14({ error: message }, 500);
9863
+ return jsonResponse9({ error: message }, 500);
9930
9864
  }
9931
9865
  }
9932
9866
  return null;
@@ -9943,13 +9877,13 @@ function createPasskeyModule(config, db) {
9943
9877
  }
9944
9878
 
9945
9879
  // src/auth/passkey-plugin.ts
9946
- function jsonResponse15(body, status = 200) {
9880
+ function jsonResponse10(body, status = 200) {
9947
9881
  return new Response(JSON.stringify(body), {
9948
9882
  status,
9949
9883
  headers: { "Content-Type": "application/json" }
9950
9884
  });
9951
9885
  }
9952
- async function parseBody9(request) {
9886
+ async function parseBody5(request) {
9953
9887
  try {
9954
9888
  return await request.json();
9955
9889
  } catch {
@@ -9971,16 +9905,16 @@ function passkey(config) {
9971
9905
  async handler(request, endpointCtx) {
9972
9906
  const user = await endpointCtx.getUser(request);
9973
9907
  if (!user) {
9974
- return jsonResponse15({ error: "Authentication required" }, 401);
9908
+ return jsonResponse10({ error: "Authentication required" }, 401);
9975
9909
  }
9976
- const body = await parseBody9(request);
9910
+ const body = await parseBody5(request);
9977
9911
  const userId = typeof body.userId === "string" ? body.userId : user.id;
9978
9912
  const userName = typeof body.userName === "string" ? body.userName : user.email ?? user.id;
9979
9913
  try {
9980
9914
  const options = await module.getRegistrationOptions(userId, userName);
9981
- return jsonResponse15(options);
9915
+ return jsonResponse10(options);
9982
9916
  } catch (err2) {
9983
- return jsonResponse15(
9917
+ return jsonResponse10(
9984
9918
  { error: err2 instanceof Error ? err2.message : "Failed to generate options" },
9985
9919
  500
9986
9920
  );
@@ -9997,19 +9931,19 @@ function passkey(config) {
9997
9931
  async handler(request, endpointCtx) {
9998
9932
  const user = await endpointCtx.getUser(request);
9999
9933
  if (!user) {
10000
- return jsonResponse15({ error: "Authentication required" }, 401);
9934
+ return jsonResponse10({ error: "Authentication required" }, 401);
10001
9935
  }
10002
- const body = await parseBody9(request);
9936
+ const body = await parseBody5(request);
10003
9937
  const userId = typeof body.userId === "string" ? body.userId : user.id;
10004
9938
  const response = body.response;
10005
9939
  if (!response) {
10006
- return jsonResponse15({ error: "Missing required field: response" }, 400);
9940
+ return jsonResponse10({ error: "Missing required field: response" }, 400);
10007
9941
  }
10008
9942
  try {
10009
9943
  const result = await module.verifyRegistration(userId, response);
10010
- return jsonResponse15(result);
9944
+ return jsonResponse10(result);
10011
9945
  } catch (err2) {
10012
- return jsonResponse15(
9946
+ return jsonResponse10(
10013
9947
  { error: err2 instanceof Error ? err2.message : "Registration failed" },
10014
9948
  400
10015
9949
  );
@@ -10023,13 +9957,13 @@ function passkey(config) {
10023
9957
  description: "Get WebAuthn authentication options"
10024
9958
  },
10025
9959
  async handler(request) {
10026
- const body = await parseBody9(request);
9960
+ const body = await parseBody5(request);
10027
9961
  const userId = typeof body.userId === "string" ? body.userId : void 0;
10028
9962
  try {
10029
9963
  const options = await module.getAuthenticationOptions(userId);
10030
- return jsonResponse15(options);
9964
+ return jsonResponse10(options);
10031
9965
  } catch (err2) {
10032
- return jsonResponse15(
9966
+ return jsonResponse10(
10033
9967
  { error: err2 instanceof Error ? err2.message : "Failed to generate options" },
10034
9968
  500
10035
9969
  );
@@ -10043,19 +9977,37 @@ function passkey(config) {
10043
9977
  description: "Verify a WebAuthn assertion and return the authenticated user"
10044
9978
  },
10045
9979
  async handler(request) {
10046
- const body = await parseBody9(request);
9980
+ const body = await parseBody5(request);
10047
9981
  const response = body.response;
10048
9982
  if (!response) {
10049
- return jsonResponse15({ error: "Missing required field: response" }, 400);
9983
+ return jsonResponse10({ error: "Missing required field: response" }, 400);
10050
9984
  }
10051
9985
  try {
10052
9986
  const result = await module.verifyAuthentication(response);
10053
9987
  if (!result) {
10054
- return jsonResponse15({ error: "Authentication failed" }, 401);
9988
+ return jsonResponse10({ error: "Authentication failed" }, 401);
10055
9989
  }
10056
- return jsonResponse15(result);
9990
+ if (ctx.sessionManager) {
9991
+ const { session, token } = await ctx.sessionManager.create(result.userId);
9992
+ const maxAge = Math.floor((session.expiresAt.getTime() - Date.now()) / 1e3);
9993
+ return new Response(
9994
+ JSON.stringify({
9995
+ user: { id: result.userId },
9996
+ session: { token, expiresAt: session.expiresAt },
9997
+ credential: result.credential
9998
+ }),
9999
+ {
10000
+ status: 200,
10001
+ headers: {
10002
+ "Content-Type": "application/json",
10003
+ "Set-Cookie": buildSetCookie("kavach_session", token, maxAge)
10004
+ }
10005
+ }
10006
+ );
10007
+ }
10008
+ return jsonResponse10(result);
10057
10009
  } catch (err2) {
10058
- return jsonResponse15(
10010
+ return jsonResponse10(
10059
10011
  { error: err2 instanceof Error ? err2.message : "Authentication failed" },
10060
10012
  401
10061
10013
  );
@@ -10072,13 +10024,13 @@ function passkey(config) {
10072
10024
  async handler(request, endpointCtx) {
10073
10025
  const user = await endpointCtx.getUser(request);
10074
10026
  if (!user) {
10075
- return jsonResponse15({ error: "Authentication required" }, 401);
10027
+ return jsonResponse10({ error: "Authentication required" }, 401);
10076
10028
  }
10077
10029
  try {
10078
10030
  const credentials = await module.listCredentials(user.id);
10079
- return jsonResponse15({ credentials });
10031
+ return jsonResponse10({ credentials });
10080
10032
  } catch (err2) {
10081
- return jsonResponse15(
10033
+ return jsonResponse10(
10082
10034
  { error: err2 instanceof Error ? err2.message : "Failed to list credentials" },
10083
10035
  500
10084
10036
  );
@@ -10095,19 +10047,19 @@ function passkey(config) {
10095
10047
  async handler(request, endpointCtx) {
10096
10048
  const user = await endpointCtx.getUser(request);
10097
10049
  if (!user) {
10098
- return jsonResponse15({ error: "Authentication required" }, 401);
10050
+ return jsonResponse10({ error: "Authentication required" }, 401);
10099
10051
  }
10100
10052
  const url = new URL(request.url);
10101
10053
  const segments = url.pathname.split("/").filter(Boolean);
10102
10054
  const credentialId = segments[3];
10103
10055
  if (!credentialId) {
10104
- return jsonResponse15({ error: "Missing credential ID in path" }, 400);
10056
+ return jsonResponse10({ error: "Missing credential ID in path" }, 400);
10105
10057
  }
10106
10058
  try {
10107
10059
  await module.removeCredential(credentialId, user.id);
10108
- return jsonResponse15({ removed: true });
10060
+ return jsonResponse10({ removed: true });
10109
10061
  } catch (err2) {
10110
- return jsonResponse15(
10062
+ return jsonResponse10(
10111
10063
  { error: err2 instanceof Error ? err2.message : "Failed to remove credential" },
10112
10064
  500
10113
10065
  );
@@ -10124,7 +10076,7 @@ var TOKEN_PURPOSE2 = "password-reset";
10124
10076
  function makeError7(code, message, details) {
10125
10077
  return { code, message, ...details !== void 0 ? { details } : {} };
10126
10078
  }
10127
- function jsonResponse16(body, status = 200) {
10079
+ function jsonResponse11(body, status = 200) {
10128
10080
  return new Response(JSON.stringify(body), {
10129
10081
  status,
10130
10082
  headers: { "Content-Type": "application/json" }
@@ -10240,27 +10192,27 @@ function createPasswordResetModule(config, db, sessionManager, tokenModule) {
10240
10192
  try {
10241
10193
  body = await request.json();
10242
10194
  } catch {
10243
- return jsonResponse16({ error: "Invalid JSON body" }, 400);
10195
+ return jsonResponse11({ error: "Invalid JSON body" }, 400);
10244
10196
  }
10245
10197
  const b = body;
10246
10198
  if (pathname === "/auth/forgot-password") {
10247
10199
  if (typeof b.email !== "string") {
10248
- return jsonResponse16({ error: "Missing required field: email" }, 400);
10200
+ return jsonResponse11({ error: "Missing required field: email" }, 400);
10249
10201
  }
10250
10202
  const result = await requestReset(b.email);
10251
10203
  if (!result.success) {
10252
- return jsonResponse16({ error: result.error.message }, 500);
10204
+ return jsonResponse11({ error: result.error.message }, 500);
10253
10205
  }
10254
10206
  return new Response(null, { status: 204 });
10255
10207
  }
10256
10208
  if (pathname === "/auth/reset-password") {
10257
10209
  if (typeof b.token !== "string" || typeof b.password !== "string") {
10258
- return jsonResponse16({ error: "Missing required fields: token, password" }, 400);
10210
+ return jsonResponse11({ error: "Missing required fields: token, password" }, 400);
10259
10211
  }
10260
10212
  const result = await resetPassword(b.token, b.password);
10261
10213
  if (!result.success) {
10262
10214
  const status = result.error.code === "INVALID_PASSWORD" ? 400 : 400;
10263
- return jsonResponse16({ error: result.error.message }, status);
10215
+ return jsonResponse11({ error: result.error.message }, status);
10264
10216
  }
10265
10217
  return new Response(null, { status: 204 });
10266
10218
  }
@@ -10295,7 +10247,7 @@ function generateNumericCode2(length) {
10295
10247
  function normalisePhone(phone) {
10296
10248
  return phone.replace(/\s+/g, "");
10297
10249
  }
10298
- function jsonResponse17(body, status = 200) {
10250
+ function jsonResponse12(body, status = 200) {
10299
10251
  return new Response(JSON.stringify(body), {
10300
10252
  status,
10301
10253
  headers: { "Content-Type": "application/json" }
@@ -10367,25 +10319,25 @@ function createPhoneAuthModule(config, db, sessionManager) {
10367
10319
  try {
10368
10320
  body = await request.json();
10369
10321
  } catch {
10370
- return jsonResponse17({ error: "Invalid JSON body" }, 400);
10322
+ return jsonResponse12({ error: "Invalid JSON body" }, 400);
10371
10323
  }
10372
10324
  const b = body;
10373
10325
  if (pathname === "/auth/phone/send-code") {
10374
10326
  if (typeof b.phoneNumber !== "string") {
10375
- return jsonResponse17({ error: "Missing required field: phoneNumber" }, 400);
10327
+ return jsonResponse12({ error: "Missing required field: phoneNumber" }, 400);
10376
10328
  }
10377
10329
  const result = await sendCode(b.phoneNumber);
10378
- return jsonResponse17(result);
10330
+ return jsonResponse12(result);
10379
10331
  }
10380
10332
  if (pathname === "/auth/phone/verify") {
10381
10333
  if (typeof b.phoneNumber !== "string" || typeof b.code !== "string") {
10382
- return jsonResponse17({ error: "Missing required fields: phoneNumber, code" }, 400);
10334
+ return jsonResponse12({ error: "Missing required fields: phoneNumber, code" }, 400);
10383
10335
  }
10384
10336
  const result = await verifyCode(b.phoneNumber, b.code);
10385
10337
  if (!result) {
10386
- return jsonResponse17({ error: "Invalid or expired code" }, 401);
10338
+ return jsonResponse12({ error: "Invalid or expired code" }, 401);
10387
10339
  }
10388
- return jsonResponse17(result);
10340
+ return jsonResponse12(result);
10389
10341
  }
10390
10342
  return null;
10391
10343
  }
@@ -10405,12 +10357,12 @@ async function polarRequest(accessToken, baseUrl, method, path, body) {
10405
10357
  headers,
10406
10358
  body: body !== void 0 ? JSON.stringify(body) : void 0
10407
10359
  });
10408
- const json3 = await response.json();
10360
+ const json2 = await response.json();
10409
10361
  if (!response.ok) {
10410
- const message = json3.detail ?? json3.message ?? `Polar API error: ${response.status}`;
10362
+ const message = json2.detail ?? json2.message ?? `Polar API error: ${response.status}`;
10411
10363
  throw new Error(message);
10412
10364
  }
10413
- return json3;
10365
+ return json2;
10414
10366
  }
10415
10367
  async function verifyWebhookSignature(payload, signatureHeader, webhookSecret) {
10416
10368
  const prefix = "sha256=";
@@ -10633,19 +10585,6 @@ function createPolarModule(config, db) {
10633
10585
  }
10634
10586
 
10635
10587
  // src/auth/polar-plugin.ts
10636
- function json(body, status = 200) {
10637
- return new Response(JSON.stringify(body), {
10638
- status,
10639
- headers: { "Content-Type": "application/json" }
10640
- });
10641
- }
10642
- async function parseBody10(request) {
10643
- try {
10644
- return await request.json();
10645
- } catch {
10646
- return {};
10647
- }
10648
- }
10649
10588
  function polar(config) {
10650
10589
  return {
10651
10590
  id: "kavach-polar",
@@ -10663,13 +10602,14 @@ function polar(config) {
10663
10602
  if (!user) {
10664
10603
  return json({ error: "Authentication required" }, 401);
10665
10604
  }
10666
- const body = await parseBody10(request);
10667
- const productId = typeof body.productId === "string" ? body.productId.trim() : null;
10605
+ const bodyResult = await parseBody(request);
10606
+ if (!bodyResult.ok) return bodyResult.response;
10607
+ const productId = typeof bodyResult.data.productId === "string" ? bodyResult.data.productId.trim() : null;
10668
10608
  if (!productId) {
10669
10609
  return json({ error: "Missing required field: productId" }, 400);
10670
10610
  }
10671
- const successUrl = typeof body.successUrl === "string" ? body.successUrl : void 0;
10672
- const customerEmail = typeof body.customerEmail === "string" ? body.customerEmail : void 0;
10611
+ const successUrl = typeof bodyResult.data.successUrl === "string" ? bodyResult.data.successUrl : void 0;
10612
+ const customerEmail = typeof bodyResult.data.customerEmail === "string" ? bodyResult.data.customerEmail : void 0;
10673
10613
  try {
10674
10614
  const result = await module.createCheckout(user.id, productId, {
10675
10615
  successUrl,
@@ -12114,13 +12054,13 @@ function scim(config) {
12114
12054
  // src/auth/siwe.ts
12115
12055
  var DEFAULT_NONCE_TTL_SECONDS = 300;
12116
12056
  var SIWE_VERSION = "1";
12117
- function jsonResponse18(body, status = 200) {
12057
+ function jsonResponse13(body, status = 200) {
12118
12058
  return new Response(JSON.stringify(body), {
12119
12059
  status,
12120
12060
  headers: { "Content-Type": "application/json" }
12121
12061
  });
12122
12062
  }
12123
- async function parseBody11(request) {
12063
+ async function parseBody6(request) {
12124
12064
  try {
12125
12065
  return await request.json();
12126
12066
  } catch {
@@ -12255,20 +12195,20 @@ function createSiweModule(config) {
12255
12195
  const { method, pathname } = { method: request.method, pathname: url.pathname };
12256
12196
  if (method === "GET" && pathname.endsWith("/auth/siwe/nonce")) {
12257
12197
  const nonce = await generateNonce();
12258
- return jsonResponse18({ nonce });
12198
+ return jsonResponse13({ nonce });
12259
12199
  }
12260
12200
  if (method === "POST" && pathname.endsWith("/auth/siwe/verify")) {
12261
- const body = await parseBody11(request);
12201
+ const body = await parseBody6(request);
12262
12202
  const message = typeof body.message === "string" ? body.message : null;
12263
12203
  const signature = typeof body.signature === "string" ? body.signature : null;
12264
12204
  if (!message || !signature) {
12265
- return jsonResponse18({ error: "Missing required fields: message, signature" }, 400);
12205
+ return jsonResponse13({ error: "Missing required fields: message, signature" }, 400);
12266
12206
  }
12267
12207
  try {
12268
12208
  const result = await verify(message, signature);
12269
- return jsonResponse18({ address: result.address, chainId: result.chainId });
12209
+ return jsonResponse13({ address: result.address, chainId: result.chainId });
12270
12210
  } catch (err2) {
12271
- return jsonResponse18(
12211
+ return jsonResponse13(
12272
12212
  { error: err2 instanceof Error ? err2.message : "Verification failed" },
12273
12213
  400
12274
12214
  );
@@ -13305,7 +13245,7 @@ function createSsoModule(config, db) {
13305
13245
  const url = new URL(request.url);
13306
13246
  const { pathname } = url;
13307
13247
  const { method } = request;
13308
- const json3 = (data, status = 200) => new Response(JSON.stringify(data), {
13248
+ const json2 = (data, status = 200) => new Response(JSON.stringify(data), {
13309
13249
  status,
13310
13250
  headers: { "Content-Type": "application/json" }
13311
13251
  });
@@ -13314,14 +13254,14 @@ function createSsoModule(config, db) {
13314
13254
  try {
13315
13255
  body = await request.json();
13316
13256
  } catch {
13317
- return json3({ error: "Invalid JSON body" }, 400);
13257
+ return json2({ error: "Invalid JSON body" }, 400);
13318
13258
  }
13319
13259
  const b = body;
13320
13260
  if (typeof b.orgId !== "string" || typeof b.providerId !== "string" || typeof b.type !== "string" || typeof b.domain !== "string") {
13321
- return json3({ error: "Missing required fields: orgId, providerId, type, domain" }, 400);
13261
+ return json2({ error: "Missing required fields: orgId, providerId, type, domain" }, 400);
13322
13262
  }
13323
13263
  if (b.type !== "saml" && b.type !== "oidc") {
13324
- return json3({ error: "type must be 'saml' or 'oidc'" }, 400);
13264
+ return json2({ error: "type must be 'saml' or 'oidc'" }, 400);
13325
13265
  }
13326
13266
  const conn = await createConnection({
13327
13267
  orgId: b.orgId,
@@ -13329,19 +13269,19 @@ function createSsoModule(config, db) {
13329
13269
  type: b.type,
13330
13270
  domain: b.domain
13331
13271
  });
13332
- return json3(conn, 201);
13272
+ return json2(conn, 201);
13333
13273
  }
13334
13274
  const listMatch = /^\/auth\/sso\/connections\/([^/]+)$/.exec(pathname);
13335
13275
  if (method === "GET" && listMatch) {
13336
13276
  const orgId = decodeURIComponent(listMatch[1] ?? "");
13337
13277
  const conns = await listConnections(orgId);
13338
- return json3(conns);
13278
+ return json2(conns);
13339
13279
  }
13340
13280
  const deleteMatch = /^\/auth\/sso\/connections\/([^/]+)$/.exec(pathname);
13341
13281
  if (method === "DELETE" && deleteMatch) {
13342
13282
  const connId = decodeURIComponent(deleteMatch[1] ?? "");
13343
13283
  await removeConnection(connId);
13344
- return json3({ success: true });
13284
+ return json2({ success: true });
13345
13285
  }
13346
13286
  const samlInitMatch = /^\/auth\/sso\/saml\/([^/]+)$/.exec(pathname);
13347
13287
  if (method === "GET" && samlInitMatch) {
@@ -13351,7 +13291,7 @@ function createSsoModule(config, db) {
13351
13291
  const authUrl = await getSamlAuthUrl(connId, relayState);
13352
13292
  return new Response(null, { status: 302, headers: { Location: authUrl } });
13353
13293
  } catch (err2) {
13354
- return json3({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 400);
13294
+ return json2({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 400);
13355
13295
  }
13356
13296
  }
13357
13297
  const samlAcsMatch = /^\/auth\/sso\/saml\/([^/]+)\/acs$/.exec(pathname);
@@ -13364,14 +13304,14 @@ function createSsoModule(config, db) {
13364
13304
  if (typeof val !== "string") throw new Error("Missing SAMLResponse");
13365
13305
  samlResponse = val;
13366
13306
  } catch {
13367
- return json3({ error: "Missing or invalid SAMLResponse" }, 400);
13307
+ return json2({ error: "Missing or invalid SAMLResponse" }, 400);
13368
13308
  }
13369
13309
  try {
13370
13310
  const result = await handleSamlResponse(connId, samlResponse);
13371
- return json3(result);
13311
+ return json2(result);
13372
13312
  } catch (err2) {
13373
13313
  const status = err2 instanceof SsoError && err2.code === SSO_ERROR.RATE_LIMITED ? 429 : 401;
13374
- return json3(
13314
+ return json2(
13375
13315
  {
13376
13316
  error: err2 instanceof Error ? err2.message : "SAML error",
13377
13317
  code: err2 instanceof SsoError ? err2.code : "SAML_ERROR"
@@ -13389,20 +13329,20 @@ function createSsoModule(config, db) {
13389
13329
  const authUrl = await getOidcAuthUrl(connId, state, nonce);
13390
13330
  return new Response(null, { status: 302, headers: { Location: authUrl } });
13391
13331
  } catch (err2) {
13392
- return json3({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 400);
13332
+ return json2({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 400);
13393
13333
  }
13394
13334
  }
13395
13335
  const oidcCbMatch = /^\/auth\/sso\/oidc\/([^/]+)\/callback$/.exec(pathname);
13396
13336
  if (method === "GET" && oidcCbMatch) {
13397
13337
  const connId = decodeURIComponent(oidcCbMatch[1] ?? "");
13398
13338
  const code = url.searchParams.get("code");
13399
- if (!code) return json3({ error: "Missing code parameter" }, 400);
13339
+ if (!code) return json2({ error: "Missing code parameter" }, 400);
13400
13340
  try {
13401
13341
  const result = await handleOidcCallback(connId, code);
13402
- return json3(result);
13342
+ return json2(result);
13403
13343
  } catch (err2) {
13404
13344
  const status = err2 instanceof SsoError && err2.code === SSO_ERROR.RATE_LIMITED ? 429 : 401;
13405
- return json3(
13345
+ return json2(
13406
13346
  {
13407
13347
  error: err2 instanceof Error ? err2.message : "OIDC error",
13408
13348
  code: err2 instanceof SsoError ? err2.code : "OIDC_ERROR"
@@ -13503,12 +13443,12 @@ async function stripeRequest(secretKey, apiVersion, method, path, body) {
13503
13443
  headers,
13504
13444
  body: bodyStr
13505
13445
  });
13506
- const json3 = await response.json();
13446
+ const json2 = await response.json();
13507
13447
  if (!response.ok) {
13508
- const message = json3.error?.message ?? `Stripe API error: ${response.status}`;
13448
+ const message = json2.error?.message ?? `Stripe API error: ${response.status}`;
13509
13449
  throw new Error(message);
13510
13450
  }
13511
- return json3;
13451
+ return json2;
13512
13452
  }
13513
13453
  async function verifyWebhookSignature2(payload, signatureHeader, webhookSecret) {
13514
13454
  const parts = {};
@@ -13818,19 +13758,6 @@ function createStripeModule(config, db) {
13818
13758
  }
13819
13759
 
13820
13760
  // src/auth/stripe-plugin.ts
13821
- function json2(body, status = 200) {
13822
- return new Response(JSON.stringify(body), {
13823
- status,
13824
- headers: { "Content-Type": "application/json" }
13825
- });
13826
- }
13827
- async function parseBody12(request) {
13828
- try {
13829
- return await request.json();
13830
- } catch {
13831
- return {};
13832
- }
13833
- }
13834
13761
  function stripe(config) {
13835
13762
  return {
13836
13763
  id: "kavach-stripe",
@@ -13846,17 +13773,18 @@ function stripe(config) {
13846
13773
  async handler(request, endpointCtx) {
13847
13774
  const user = await endpointCtx.getUser(request);
13848
13775
  if (!user) {
13849
- return json2({ error: "Authentication required" }, 401);
13776
+ return json({ error: "Authentication required" }, 401);
13850
13777
  }
13851
- const body = await parseBody12(request);
13852
- const priceId = typeof body.priceId === "string" ? body.priceId.trim() : null;
13778
+ const bodyResult = await parseBody(request);
13779
+ if (!bodyResult.ok) return bodyResult.response;
13780
+ const priceId = typeof bodyResult.data.priceId === "string" ? bodyResult.data.priceId.trim() : null;
13853
13781
  if (!priceId) {
13854
- return json2({ error: "Missing required field: priceId" }, 400);
13782
+ return json({ error: "Missing required field: priceId" }, 400);
13855
13783
  }
13856
- const successUrl = typeof body.successUrl === "string" ? body.successUrl : void 0;
13857
- const cancelUrl = typeof body.cancelUrl === "string" ? body.cancelUrl : void 0;
13858
- const trialDays = typeof body.trialDays === "number" ? body.trialDays : void 0;
13859
- const metadata = body.metadata != null && typeof body.metadata === "object" && !Array.isArray(body.metadata) ? body.metadata : void 0;
13784
+ const successUrl = typeof bodyResult.data.successUrl === "string" ? bodyResult.data.successUrl : void 0;
13785
+ const cancelUrl = typeof bodyResult.data.cancelUrl === "string" ? bodyResult.data.cancelUrl : void 0;
13786
+ const trialDays = typeof bodyResult.data.trialDays === "number" ? bodyResult.data.trialDays : void 0;
13787
+ const metadata = bodyResult.data.metadata != null && typeof bodyResult.data.metadata === "object" && !Array.isArray(bodyResult.data.metadata) ? bodyResult.data.metadata : void 0;
13860
13788
  try {
13861
13789
  const result = await module.createCheckoutSession(user.id, priceId, {
13862
13790
  successUrl,
@@ -13864,9 +13792,9 @@ function stripe(config) {
13864
13792
  trialDays,
13865
13793
  metadata
13866
13794
  });
13867
- return json2(result);
13795
+ return json(result);
13868
13796
  } catch (err2) {
13869
- return json2(
13797
+ return json(
13870
13798
  {
13871
13799
  error: err2 instanceof Error ? err2.message : "Failed to create checkout session"
13872
13800
  },
@@ -13885,18 +13813,19 @@ function stripe(config) {
13885
13813
  async handler(request, endpointCtx) {
13886
13814
  const user = await endpointCtx.getUser(request);
13887
13815
  if (!user) {
13888
- return json2({ error: "Authentication required" }, 401);
13816
+ return json({ error: "Authentication required" }, 401);
13889
13817
  }
13890
- const body = await parseBody12(request);
13891
- const returnUrl = typeof body.returnUrl === "string" ? body.returnUrl.trim() : null;
13818
+ const bodyResult = await parseBody(request);
13819
+ if (!bodyResult.ok) return bodyResult.response;
13820
+ const returnUrl = typeof bodyResult.data.returnUrl === "string" ? bodyResult.data.returnUrl.trim() : null;
13892
13821
  if (!returnUrl) {
13893
- return json2({ error: "Missing required field: returnUrl" }, 400);
13822
+ return json({ error: "Missing required field: returnUrl" }, 400);
13894
13823
  }
13895
13824
  try {
13896
13825
  const result = await module.createPortalSession(user.id, returnUrl);
13897
- return json2(result);
13826
+ return json(result);
13898
13827
  } catch (err2) {
13899
- return json2(
13828
+ return json(
13900
13829
  {
13901
13830
  error: err2 instanceof Error ? err2.message : "Failed to create portal session"
13902
13831
  },
@@ -13915,10 +13844,10 @@ function stripe(config) {
13915
13844
  async handler(request, endpointCtx) {
13916
13845
  const user = await endpointCtx.getUser(request);
13917
13846
  if (!user) {
13918
- return json2({ error: "Authentication required" }, 401);
13847
+ return json({ error: "Authentication required" }, 401);
13919
13848
  }
13920
13849
  const subscription = await module.getSubscription(user.id);
13921
- return json2({ subscription });
13850
+ return json({ subscription });
13922
13851
  }
13923
13852
  });
13924
13853
  ctx.addEndpoint({
@@ -14020,13 +13949,13 @@ async function generateBackupCodes(count) {
14020
13949
  }
14021
13950
  return { plain, hashed };
14022
13951
  }
14023
- function jsonResponse19(body, status = 200) {
13952
+ function jsonResponse14(body, status = 200) {
14024
13953
  return new Response(JSON.stringify(body), {
14025
13954
  status,
14026
13955
  headers: { "Content-Type": "application/json" }
14027
13956
  });
14028
13957
  }
14029
- async function parseBody13(request) {
13958
+ async function parseBody7(request) {
14030
13959
  try {
14031
13960
  return await request.json();
14032
13961
  } catch {
@@ -14124,50 +14053,50 @@ function createTotpModule(config, db) {
14124
14053
  const method = request.method.toUpperCase();
14125
14054
  if (method !== "POST") return null;
14126
14055
  if (path === "/auth/2fa/setup") {
14127
- const body = await parseBody13(request);
14056
+ const body = await parseBody7(request);
14128
14057
  const userId = typeof body.userId === "string" ? body.userId : null;
14129
- if (!userId) return jsonResponse19({ error: "userId required" }, 400);
14058
+ if (!userId) return jsonResponse14({ error: "userId required" }, 400);
14130
14059
  try {
14131
14060
  const result = await setup(userId);
14132
- return jsonResponse19(result);
14061
+ return jsonResponse14(result);
14133
14062
  } catch (err2) {
14134
- return jsonResponse19({ error: err2 instanceof Error ? err2.message : "Setup failed" }, 500);
14063
+ return jsonResponse14({ error: err2 instanceof Error ? err2.message : "Setup failed" }, 500);
14135
14064
  }
14136
14065
  }
14137
14066
  if (path === "/auth/2fa/enable") {
14138
- const body = await parseBody13(request);
14067
+ const body = await parseBody7(request);
14139
14068
  const userId = typeof body.userId === "string" ? body.userId : null;
14140
14069
  const code = typeof body.code === "string" ? body.code : null;
14141
- if (!userId || !code) return jsonResponse19({ error: "userId and code required" }, 400);
14070
+ if (!userId || !code) return jsonResponse14({ error: "userId and code required" }, 400);
14142
14071
  const result = await enable(userId, code);
14143
- return jsonResponse19(result);
14072
+ return jsonResponse14(result);
14144
14073
  }
14145
14074
  if (path === "/auth/2fa/verify") {
14146
- const body = await parseBody13(request);
14075
+ const body = await parseBody7(request);
14147
14076
  const userId = typeof body.userId === "string" ? body.userId : null;
14148
14077
  const code = typeof body.code === "string" ? body.code : null;
14149
- if (!userId || !code) return jsonResponse19({ error: "userId and code required" }, 400);
14078
+ if (!userId || !code) return jsonResponse14({ error: "userId and code required" }, 400);
14150
14079
  const result = await verify(userId, code);
14151
- return jsonResponse19(result);
14080
+ return jsonResponse14(result);
14152
14081
  }
14153
14082
  if (path === "/auth/2fa/disable") {
14154
- const body = await parseBody13(request);
14083
+ const body = await parseBody7(request);
14155
14084
  const userId = typeof body.userId === "string" ? body.userId : null;
14156
14085
  const code = typeof body.code === "string" ? body.code : null;
14157
- if (!userId || !code) return jsonResponse19({ error: "userId and code required" }, 400);
14086
+ if (!userId || !code) return jsonResponse14({ error: "userId and code required" }, 400);
14158
14087
  const result = await disable(userId, code);
14159
- return jsonResponse19(result);
14088
+ return jsonResponse14(result);
14160
14089
  }
14161
14090
  if (path === "/auth/2fa/backup-codes") {
14162
- const body = await parseBody13(request);
14091
+ const body = await parseBody7(request);
14163
14092
  const userId = typeof body.userId === "string" ? body.userId : null;
14164
14093
  const code = typeof body.code === "string" ? body.code : null;
14165
- if (!userId || !code) return jsonResponse19({ error: "userId and code required" }, 400);
14094
+ if (!userId || !code) return jsonResponse14({ error: "userId and code required" }, 400);
14166
14095
  try {
14167
14096
  const result = await regenerateBackupCodes(userId, code);
14168
- return jsonResponse19(result);
14097
+ return jsonResponse14(result);
14169
14098
  } catch (err2) {
14170
- return jsonResponse19(
14099
+ return jsonResponse14(
14171
14100
  { error: err2 instanceof Error ? err2.message : "Failed to regenerate codes" },
14172
14101
  400
14173
14102
  );
@@ -14187,13 +14116,13 @@ function createTotpModule(config, db) {
14187
14116
  }
14188
14117
 
14189
14118
  // src/auth/totp-plugin.ts
14190
- function jsonResponse20(body, status = 200) {
14119
+ function jsonResponse15(body, status = 200) {
14191
14120
  return new Response(JSON.stringify(body), {
14192
14121
  status,
14193
14122
  headers: { "Content-Type": "application/json" }
14194
14123
  });
14195
14124
  }
14196
- async function parseBody14(request) {
14125
+ async function parseBody8(request) {
14197
14126
  try {
14198
14127
  return await request.json();
14199
14128
  } catch {
@@ -14215,13 +14144,13 @@ function twoFactor(config) {
14215
14144
  async handler(request, endpointCtx) {
14216
14145
  const user = await endpointCtx.getUser(request);
14217
14146
  if (!user) {
14218
- return jsonResponse20({ error: "Authentication required" }, 401);
14147
+ return jsonResponse15({ error: "Authentication required" }, 401);
14219
14148
  }
14220
14149
  try {
14221
14150
  const setup = await module.setup(user.id);
14222
- return jsonResponse20(setup);
14151
+ return jsonResponse15(setup);
14223
14152
  } catch (err2) {
14224
- return jsonResponse20(
14153
+ return jsonResponse15(
14225
14154
  { error: err2 instanceof Error ? err2.message : "Enrollment failed" },
14226
14155
  500
14227
14156
  );
@@ -14238,23 +14167,23 @@ function twoFactor(config) {
14238
14167
  async handler(request, endpointCtx) {
14239
14168
  const user = await endpointCtx.getUser(request);
14240
14169
  if (!user) {
14241
- return jsonResponse20({ error: "Authentication required" }, 401);
14170
+ return jsonResponse15({ error: "Authentication required" }, 401);
14242
14171
  }
14243
- const body = await parseBody14(request);
14172
+ const body = await parseBody8(request);
14244
14173
  const code = typeof body.code === "string" ? body.code : null;
14245
14174
  if (!code) {
14246
- return jsonResponse20({ error: "Missing required field: code" }, 400);
14175
+ return jsonResponse15({ error: "Missing required field: code" }, 400);
14247
14176
  }
14248
14177
  const enabled = await module.isEnabled(user.id);
14249
14178
  if (!enabled) {
14250
14179
  const result2 = await module.enable(user.id, code);
14251
14180
  if (!result2.enabled) {
14252
- return jsonResponse20({ error: "Invalid TOTP code" }, 400);
14181
+ return jsonResponse15({ error: "Invalid TOTP code" }, 400);
14253
14182
  }
14254
- return jsonResponse20({ valid: true, activated: true });
14183
+ return jsonResponse15({ valid: true, activated: true });
14255
14184
  }
14256
14185
  const result = await module.verify(user.id, code);
14257
- return jsonResponse20(result);
14186
+ return jsonResponse15(result);
14258
14187
  }
14259
14188
  });
14260
14189
  ctx.addEndpoint({
@@ -14267,18 +14196,18 @@ function twoFactor(config) {
14267
14196
  async handler(request, endpointCtx) {
14268
14197
  const user = await endpointCtx.getUser(request);
14269
14198
  if (!user) {
14270
- return jsonResponse20({ error: "Authentication required" }, 401);
14199
+ return jsonResponse15({ error: "Authentication required" }, 401);
14271
14200
  }
14272
- const body = await parseBody14(request);
14201
+ const body = await parseBody8(request);
14273
14202
  const code = typeof body.code === "string" ? body.code : null;
14274
14203
  if (!code) {
14275
- return jsonResponse20({ error: "Missing required field: code" }, 400);
14204
+ return jsonResponse15({ error: "Missing required field: code" }, 400);
14276
14205
  }
14277
14206
  const result = await module.disable(user.id, code);
14278
14207
  if (!result.disabled) {
14279
- return jsonResponse20({ error: "Invalid TOTP code" }, 400);
14208
+ return jsonResponse15({ error: "Invalid TOTP code" }, 400);
14280
14209
  }
14281
- return jsonResponse20(result);
14210
+ return jsonResponse15(result);
14282
14211
  }
14283
14212
  });
14284
14213
  ctx.addEndpoint({
@@ -14291,10 +14220,10 @@ function twoFactor(config) {
14291
14220
  async handler(request, endpointCtx) {
14292
14221
  const user = await endpointCtx.getUser(request);
14293
14222
  if (!user) {
14294
- return jsonResponse20({ error: "Authentication required" }, 401);
14223
+ return jsonResponse15({ error: "Authentication required" }, 401);
14295
14224
  }
14296
14225
  const enabled = await module.isEnabled(user.id);
14297
- return jsonResponse20({ enabled });
14226
+ return jsonResponse15({ enabled });
14298
14227
  }
14299
14228
  });
14300
14229
  ctx.addEndpoint({
@@ -14307,18 +14236,18 @@ function twoFactor(config) {
14307
14236
  async handler(request, endpointCtx) {
14308
14237
  const user = await endpointCtx.getUser(request);
14309
14238
  if (!user) {
14310
- return jsonResponse20({ error: "Authentication required" }, 401);
14239
+ return jsonResponse15({ error: "Authentication required" }, 401);
14311
14240
  }
14312
- const body = await parseBody14(request);
14241
+ const body = await parseBody8(request);
14313
14242
  const code = typeof body.code === "string" ? body.code : null;
14314
14243
  if (!code) {
14315
- return jsonResponse20({ error: "Missing required field: code" }, 400);
14244
+ return jsonResponse15({ error: "Missing required field: code" }, 400);
14316
14245
  }
14317
14246
  try {
14318
14247
  const result = await module.regenerateBackupCodes(user.id, code);
14319
- return jsonResponse20(result);
14248
+ return jsonResponse15(result);
14320
14249
  } catch (err2) {
14321
- return jsonResponse20(
14250
+ return jsonResponse15(
14322
14251
  { error: err2 instanceof Error ? err2.message : "Failed to regenerate backup codes" },
14323
14252
  400
14324
14253
  );
@@ -14437,7 +14366,7 @@ async function hashPassword(password) {
14437
14366
  async function verifyPassword(stored, candidate) {
14438
14367
  return pbkdf2Verify(candidate, stored);
14439
14368
  }
14440
- function jsonResponse21(body, status = 200) {
14369
+ function jsonResponse16(body, status = 200) {
14441
14370
  return new Response(JSON.stringify(body), {
14442
14371
  status,
14443
14372
  headers: { "Content-Type": "application/json" }
@@ -14561,12 +14490,12 @@ function createUsernameAuthModule(config, db, sessionManager) {
14561
14490
  try {
14562
14491
  body = await request.json();
14563
14492
  } catch {
14564
- return jsonResponse21({ error: "Invalid JSON body" }, 400);
14493
+ return jsonResponse16({ error: "Invalid JSON body" }, 400);
14565
14494
  }
14566
14495
  const b = body;
14567
14496
  if (pathname === "/auth/username/sign-up") {
14568
14497
  if (typeof b.username !== "string" || typeof b.password !== "string") {
14569
- return jsonResponse21({ error: "Missing required fields: username, password" }, 400);
14498
+ return jsonResponse16({ error: "Missing required fields: username, password" }, 400);
14570
14499
  }
14571
14500
  try {
14572
14501
  const result = await signUp({
@@ -14574,21 +14503,21 @@ function createUsernameAuthModule(config, db, sessionManager) {
14574
14503
  password: b.password,
14575
14504
  name: typeof b.name === "string" ? b.name : void 0
14576
14505
  });
14577
- return jsonResponse21(result, 201);
14506
+ return jsonResponse16(result, 201);
14578
14507
  } catch (err2) {
14579
- return jsonResponse21({ error: err2 instanceof Error ? err2.message : "Sign-up failed" }, 400);
14508
+ return jsonResponse16({ error: err2 instanceof Error ? err2.message : "Sign-up failed" }, 400);
14580
14509
  }
14581
14510
  }
14582
14511
  if (pathname === "/auth/username/sign-in") {
14583
14512
  if (typeof b.username !== "string" || typeof b.password !== "string") {
14584
- return jsonResponse21({ error: "Missing required fields: username, password" }, 400);
14513
+ return jsonResponse16({ error: "Missing required fields: username, password" }, 400);
14585
14514
  }
14586
14515
  try {
14587
14516
  const result = await signIn({ username: b.username, password: b.password });
14588
- return jsonResponse21(result);
14517
+ return jsonResponse16(result);
14589
14518
  } catch (err2) {
14590
14519
  if (err2 instanceof Error && err2.message === "Password reset required") {
14591
- return jsonResponse21(
14520
+ return jsonResponse16(
14592
14521
  {
14593
14522
  error: {
14594
14523
  code: "PASSWORD_RESET_REQUIRED",
@@ -14598,21 +14527,21 @@ function createUsernameAuthModule(config, db, sessionManager) {
14598
14527
  403
14599
14528
  );
14600
14529
  }
14601
- return jsonResponse21({ error: "Invalid username or password" }, 401);
14530
+ return jsonResponse16({ error: "Invalid username or password" }, 401);
14602
14531
  }
14603
14532
  }
14604
14533
  if (pathname === "/auth/username/change-password") {
14605
14534
  if (typeof b.userId !== "string" || typeof b.current !== "string" || typeof b.newPassword !== "string") {
14606
- return jsonResponse21(
14535
+ return jsonResponse16(
14607
14536
  { error: "Missing required fields: userId, current, newPassword" },
14608
14537
  400
14609
14538
  );
14610
14539
  }
14611
14540
  try {
14612
14541
  const result = await changePassword(b.userId, b.current, b.newPassword);
14613
- return jsonResponse21(result);
14542
+ return jsonResponse16(result);
14614
14543
  } catch (err2) {
14615
- return jsonResponse21(
14544
+ return jsonResponse16(
14616
14545
  { error: err2 instanceof Error ? err2.message : "Change password failed" },
14617
14546
  400
14618
14547
  );
@@ -14620,13 +14549,13 @@ function createUsernameAuthModule(config, db, sessionManager) {
14620
14549
  }
14621
14550
  if (pathname === "/auth/username/change-username") {
14622
14551
  if (typeof b.userId !== "string" || typeof b.newUsername !== "string") {
14623
- return jsonResponse21({ error: "Missing required fields: userId, newUsername" }, 400);
14552
+ return jsonResponse16({ error: "Missing required fields: userId, newUsername" }, 400);
14624
14553
  }
14625
14554
  try {
14626
14555
  const result = await changeUsername(b.userId, b.newUsername);
14627
- return jsonResponse21(result);
14556
+ return jsonResponse16(result);
14628
14557
  } catch (err2) {
14629
- return jsonResponse21(
14558
+ return jsonResponse16(
14630
14559
  { error: err2 instanceof Error ? err2.message : "Change username failed" },
14631
14560
  400
14632
14561
  );