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.
package/dist/index.js CHANGED
@@ -1798,7 +1798,7 @@ function createAdminModule(config, db, sessionManager) {
1798
1798
  const url = new URL(request.url);
1799
1799
  const { pathname } = url;
1800
1800
  const { method } = request;
1801
- const json3 = (data, status = 200) => new Response(JSON.stringify(data), {
1801
+ const json2 = (data, status = 200) => new Response(JSON.stringify(data), {
1802
1802
  status,
1803
1803
  headers: { "Content-Type": "application/json" }
1804
1804
  });
@@ -1807,14 +1807,14 @@ function createAdminModule(config, db, sessionManager) {
1807
1807
  const offset = url.searchParams.get("offset") ? Number(url.searchParams.get("offset")) : void 0;
1808
1808
  const search = url.searchParams.get("search") ?? void 0;
1809
1809
  const result = await listUsers({ limit, offset, search });
1810
- return json3(result);
1810
+ return json2(result);
1811
1811
  }
1812
1812
  const userMatch = /^\/auth\/admin\/users\/([^/]+)$/.exec(pathname);
1813
1813
  if (method === "GET" && userMatch) {
1814
1814
  const userId = decodeURIComponent(userMatch[1] ?? "");
1815
1815
  const user = await getUser(userId);
1816
- if (!user) return json3({ error: "User not found" }, 404);
1817
- return json3(user);
1816
+ if (!user) return json2({ error: "User not found" }, 404);
1817
+ return json2(user);
1818
1818
  }
1819
1819
  const banMatch = /^\/auth\/admin\/users\/([^/]+)\/ban$/.exec(pathname);
1820
1820
  if (method === "POST" && banMatch) {
@@ -1827,19 +1827,19 @@ function createAdminModule(config, db, sessionManager) {
1827
1827
  const reason = typeof body.reason === "string" ? body.reason : void 0;
1828
1828
  const expiresAt = body.expiresAt ? new Date(body.expiresAt) : void 0;
1829
1829
  await banUser(userId, reason, expiresAt);
1830
- return json3({ success: true });
1830
+ return json2({ success: true });
1831
1831
  }
1832
1832
  const unbanMatch = /^\/auth\/admin\/users\/([^/]+)\/unban$/.exec(pathname);
1833
1833
  if (method === "POST" && unbanMatch) {
1834
1834
  const userId = decodeURIComponent(unbanMatch[1] ?? "");
1835
1835
  await unbanUser(userId);
1836
- return json3({ success: true });
1836
+ return json2({ success: true });
1837
1837
  }
1838
1838
  const deleteMatch = /^\/auth\/admin\/users\/([^/]+)$/.exec(pathname);
1839
1839
  if (method === "DELETE" && deleteMatch) {
1840
1840
  const userId = decodeURIComponent(deleteMatch[1] ?? "");
1841
1841
  await deleteUser(userId);
1842
- return json3({ success: true });
1842
+ return json2({ success: true });
1843
1843
  }
1844
1844
  const impersonateMatch = /^\/auth\/admin\/impersonate\/([^/]+)$/.exec(pathname);
1845
1845
  if (method === "POST" && impersonateMatch) {
@@ -1848,28 +1848,28 @@ function createAdminModule(config, db, sessionManager) {
1848
1848
  try {
1849
1849
  body = await request.json();
1850
1850
  } catch {
1851
- return json3({ error: "Invalid JSON body" }, 400);
1851
+ return json2({ error: "Invalid JSON body" }, 400);
1852
1852
  }
1853
1853
  const adminUserId = body.adminUserId;
1854
1854
  if (typeof adminUserId !== "string") {
1855
- return json3({ error: "Missing required field: adminUserId" }, 400);
1855
+ return json2({ error: "Missing required field: adminUserId" }, 400);
1856
1856
  }
1857
1857
  try {
1858
1858
  const result = await impersonate(adminUserId, targetUserId);
1859
- return json3(result);
1859
+ return json2(result);
1860
1860
  } catch (err2) {
1861
- return json3({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 403);
1861
+ return json2({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 403);
1862
1862
  }
1863
1863
  }
1864
1864
  if (method === "POST" && pathname === "/auth/admin/stop-impersonation") {
1865
1865
  const auth = request.headers.get("Authorization");
1866
1866
  const token = auth?.startsWith("Bearer ") ? auth.slice(7) : null;
1867
- if (!token) return json3({ error: "Missing Authorization header" }, 401);
1867
+ if (!token) return json2({ error: "Missing Authorization header" }, 401);
1868
1868
  try {
1869
1869
  await stopImpersonation(token);
1870
- return json3({ success: true });
1870
+ return json2({ success: true });
1871
1871
  } catch (err2) {
1872
- return json3({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 400);
1872
+ return json2({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 400);
1873
1873
  }
1874
1874
  }
1875
1875
  return null;
@@ -1887,78 +1887,9 @@ function createAdminModule(config, db, sessionManager) {
1887
1887
  handleRequest
1888
1888
  };
1889
1889
  }
1890
- var DEFAULT_MAX_AGE_SECONDS = 60 * 60 * 24 * 7;
1891
- function createSessionManager(config, db) {
1892
- if (!config.secret || config.secret.length < 32) {
1893
- throw new Error("SessionManager: secret must be at least 32 characters.");
1894
- }
1895
- const maxAge = config.maxAge ?? DEFAULT_MAX_AGE_SECONDS;
1896
- const keyObject = new TextEncoder().encode(config.secret);
1897
- function rowToSession2(row) {
1898
- return {
1899
- id: row.id,
1900
- userId: row.userId,
1901
- expiresAt: row.expiresAt,
1902
- createdAt: row.createdAt,
1903
- ...row.metadata !== null && { metadata: row.metadata }
1904
- };
1905
- }
1906
- async function create(userId, metadata) {
1907
- const id = generateId();
1908
- const now = /* @__PURE__ */ new Date();
1909
- const expiresAt = new Date(now.getTime() + maxAge * 1e3);
1910
- await db.insert(sessions).values({
1911
- id,
1912
- userId,
1913
- expiresAt,
1914
- metadata: metadata ?? null,
1915
- createdAt: now
1916
- });
1917
- const token = await new SignJWT({ sub: id }).setProtectedHeader({ alg: "HS256" }).setIssuedAt().setExpirationTime(Math.floor(expiresAt.getTime() / 1e3)).sign(keyObject);
1918
- const session = {
1919
- id,
1920
- userId,
1921
- expiresAt,
1922
- createdAt: now,
1923
- ...metadata !== void 0 && { metadata }
1924
- };
1925
- return { session, token };
1926
- }
1927
- async function validate(token) {
1928
- let sessionId;
1929
- try {
1930
- const { payload } = await jwtVerify(token, keyObject);
1931
- if (typeof payload.sub !== "string" || !payload.sub) return null;
1932
- sessionId = payload.sub;
1933
- } catch {
1934
- return null;
1935
- }
1936
- const now = /* @__PURE__ */ new Date();
1937
- const rows = await db.select().from(sessions).where(and(eq(sessions.id, sessionId)));
1938
- const row = rows[0];
1939
- if (!row) return null;
1940
- if (row.expiresAt <= now) {
1941
- await db.delete(sessions).where(eq(sessions.id, sessionId));
1942
- return null;
1943
- }
1944
- return rowToSession2(row);
1945
- }
1946
- async function revoke(sessionId) {
1947
- await db.delete(sessions).where(eq(sessions.id, sessionId));
1948
- }
1949
- async function revokeAll(userId) {
1950
- await db.delete(sessions).where(eq(sessions.userId, userId));
1951
- }
1952
- async function list(userId) {
1953
- const now = /* @__PURE__ */ new Date();
1954
- const rows = await db.select().from(sessions).where(and(eq(sessions.userId, userId)));
1955
- return rows.filter((row) => row.expiresAt > now).sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()).map(rowToSession2);
1956
- }
1957
- return { create, validate, revoke, revokeAll, list };
1958
- }
1959
1890
 
1960
- // src/auth/admin-plugin.ts
1961
- function jsonResponse2(body, status = 200) {
1891
+ // src/plugin/helpers.ts
1892
+ function json(body, status = 200) {
1962
1893
  return new Response(JSON.stringify(body), {
1963
1894
  status,
1964
1895
  headers: { "Content-Type": "application/json" }
@@ -1966,18 +1897,41 @@ function jsonResponse2(body, status = 200) {
1966
1897
  }
1967
1898
  async function parseBody(request) {
1968
1899
  try {
1969
- return await request.json();
1900
+ const data = await request.json();
1901
+ return { ok: true, data };
1970
1902
  } catch {
1971
- return {};
1903
+ return {
1904
+ ok: false,
1905
+ response: json({ error: "Invalid JSON body" }, 400)
1906
+ };
1907
+ }
1908
+ }
1909
+ function getCookie(request, name) {
1910
+ const header = request.headers.get("cookie");
1911
+ if (!header) return null;
1912
+ const match = header.match(new RegExp(`(?:^|;\\s*)${name}=([^;]*)`));
1913
+ return match?.[1] ? decodeURIComponent(match[1]) : null;
1914
+ }
1915
+ function buildSetCookie(name, value, maxAge, path = "/") {
1916
+ return `${name}=${encodeURIComponent(value)}; HttpOnly; Secure; SameSite=Lax; Path=${path}; Max-Age=${maxAge}`;
1917
+ }
1918
+ function buildClearCookie(name, path = "/") {
1919
+ return `${name}=; HttpOnly; Secure; SameSite=Lax; Path=${path}; Max-Age=0`;
1920
+ }
1921
+ function extractToken(request, cookieName = "kavach_session") {
1922
+ const authHeader = request.headers.get("authorization");
1923
+ if (authHeader?.startsWith("Bearer ")) {
1924
+ return authHeader.slice(7);
1972
1925
  }
1926
+ return getCookie(request, cookieName);
1973
1927
  }
1928
+
1929
+ // src/auth/admin-plugin.ts
1974
1930
  function admin(config) {
1975
1931
  return {
1976
1932
  id: "kavach-admin",
1977
1933
  async init(ctx) {
1978
- const sessionConfig = ctx.config.auth?.session;
1979
- const sessionManager = sessionConfig ? createSessionManager(sessionConfig, ctx.db) : null;
1980
- const module = createAdminModule(config ?? {}, ctx.db, sessionManager);
1934
+ const module = createAdminModule(config ?? {}, ctx.db, ctx.sessionManager ?? null);
1981
1935
  ctx.addEndpoint({
1982
1936
  method: "GET",
1983
1937
  path: "/auth/admin/users",
@@ -1988,11 +1942,11 @@ function admin(config) {
1988
1942
  async handler(request, endpointCtx) {
1989
1943
  const user = await endpointCtx.getUser(request);
1990
1944
  if (!user) {
1991
- return jsonResponse2({ error: "Authentication required" }, 401);
1945
+ return json({ error: "Authentication required" }, 401);
1992
1946
  }
1993
1947
  const isAdminUser = await module.isAdmin(user.id);
1994
1948
  if (!isAdminUser) {
1995
- return jsonResponse2({ error: "Admin access required" }, 403);
1949
+ return json({ error: "Admin access required" }, 403);
1996
1950
  }
1997
1951
  const url = new URL(request.url);
1998
1952
  const limitParam = url.searchParams.get("limit");
@@ -2003,7 +1957,7 @@ function admin(config) {
2003
1957
  offset: offsetParam ? Number(offsetParam) : void 0,
2004
1958
  search
2005
1959
  });
2006
- return jsonResponse2(result);
1960
+ return json(result);
2007
1961
  }
2008
1962
  });
2009
1963
  ctx.addEndpoint({
@@ -2016,23 +1970,23 @@ function admin(config) {
2016
1970
  async handler(request, endpointCtx) {
2017
1971
  const user = await endpointCtx.getUser(request);
2018
1972
  if (!user) {
2019
- return jsonResponse2({ error: "Authentication required" }, 401);
1973
+ return json({ error: "Authentication required" }, 401);
2020
1974
  }
2021
1975
  const isAdminUser = await module.isAdmin(user.id);
2022
1976
  if (!isAdminUser) {
2023
- return jsonResponse2({ error: "Admin access required" }, 403);
1977
+ return json({ error: "Admin access required" }, 403);
2024
1978
  }
2025
1979
  const url = new URL(request.url);
2026
1980
  const segments = url.pathname.split("/").filter(Boolean);
2027
1981
  const targetId = segments[3];
2028
1982
  if (!targetId) {
2029
- return jsonResponse2({ error: "Missing user ID in path" }, 400);
1983
+ return json({ error: "Missing user ID in path" }, 400);
2030
1984
  }
2031
1985
  const found = await module.getUser(decodeURIComponent(targetId));
2032
1986
  if (!found) {
2033
- return jsonResponse2({ error: "User not found" }, 404);
1987
+ return json({ error: "User not found" }, 404);
2034
1988
  }
2035
- return jsonResponse2(found);
1989
+ return json(found);
2036
1990
  }
2037
1991
  });
2038
1992
  ctx.addEndpoint({
@@ -2045,23 +1999,24 @@ function admin(config) {
2045
1999
  async handler(request, endpointCtx) {
2046
2000
  const user = await endpointCtx.getUser(request);
2047
2001
  if (!user) {
2048
- return jsonResponse2({ error: "Authentication required" }, 401);
2002
+ return json({ error: "Authentication required" }, 401);
2049
2003
  }
2050
2004
  const isAdminUser = await module.isAdmin(user.id);
2051
2005
  if (!isAdminUser) {
2052
- return jsonResponse2({ error: "Admin access required" }, 403);
2006
+ return json({ error: "Admin access required" }, 403);
2053
2007
  }
2054
2008
  const url = new URL(request.url);
2055
2009
  const segments = url.pathname.split("/").filter(Boolean);
2056
2010
  const targetId = segments[3];
2057
2011
  if (!targetId) {
2058
- return jsonResponse2({ error: "Missing user ID in path" }, 400);
2012
+ return json({ error: "Missing user ID in path" }, 400);
2059
2013
  }
2060
- const body = await parseBody(request);
2061
- const reason = typeof body.reason === "string" ? body.reason : void 0;
2062
- const expiresAt = body.expiresAt ? new Date(body.expiresAt) : void 0;
2014
+ const bodyResult = await parseBody(request);
2015
+ if (!bodyResult.ok) return bodyResult.response;
2016
+ const reason = typeof bodyResult.data.reason === "string" ? bodyResult.data.reason : void 0;
2017
+ const expiresAt = bodyResult.data.expiresAt ? new Date(bodyResult.data.expiresAt) : void 0;
2063
2018
  await module.banUser(decodeURIComponent(targetId), reason, expiresAt);
2064
- return jsonResponse2({ success: true });
2019
+ return json({ success: true });
2065
2020
  }
2066
2021
  });
2067
2022
  ctx.addEndpoint({
@@ -2074,20 +2029,20 @@ function admin(config) {
2074
2029
  async handler(request, endpointCtx) {
2075
2030
  const user = await endpointCtx.getUser(request);
2076
2031
  if (!user) {
2077
- return jsonResponse2({ error: "Authentication required" }, 401);
2032
+ return json({ error: "Authentication required" }, 401);
2078
2033
  }
2079
2034
  const isAdminUser = await module.isAdmin(user.id);
2080
2035
  if (!isAdminUser) {
2081
- return jsonResponse2({ error: "Admin access required" }, 403);
2036
+ return json({ error: "Admin access required" }, 403);
2082
2037
  }
2083
2038
  const url = new URL(request.url);
2084
2039
  const segments = url.pathname.split("/").filter(Boolean);
2085
2040
  const targetId = segments[3];
2086
2041
  if (!targetId) {
2087
- return jsonResponse2({ error: "Missing user ID in path" }, 400);
2042
+ return json({ error: "Missing user ID in path" }, 400);
2088
2043
  }
2089
2044
  await module.unbanUser(decodeURIComponent(targetId));
2090
- return jsonResponse2({ success: true });
2045
+ return json({ success: true });
2091
2046
  }
2092
2047
  });
2093
2048
  ctx.addEndpoint({
@@ -2100,20 +2055,20 @@ function admin(config) {
2100
2055
  async handler(request, endpointCtx) {
2101
2056
  const user = await endpointCtx.getUser(request);
2102
2057
  if (!user) {
2103
- return jsonResponse2({ error: "Authentication required" }, 401);
2058
+ return json({ error: "Authentication required" }, 401);
2104
2059
  }
2105
2060
  const isAdminUser = await module.isAdmin(user.id);
2106
2061
  if (!isAdminUser) {
2107
- return jsonResponse2({ error: "Admin access required" }, 403);
2062
+ return json({ error: "Admin access required" }, 403);
2108
2063
  }
2109
2064
  const url = new URL(request.url);
2110
2065
  const segments = url.pathname.split("/").filter(Boolean);
2111
2066
  const targetId = segments[3];
2112
2067
  if (!targetId) {
2113
- return jsonResponse2({ error: "Missing user ID in path" }, 400);
2068
+ return json({ error: "Missing user ID in path" }, 400);
2114
2069
  }
2115
2070
  await module.deleteUser(decodeURIComponent(targetId));
2116
- return jsonResponse2({ success: true });
2071
+ return json({ success: true });
2117
2072
  }
2118
2073
  });
2119
2074
  ctx.addEndpoint({
@@ -2126,23 +2081,23 @@ function admin(config) {
2126
2081
  async handler(request, endpointCtx) {
2127
2082
  const user = await endpointCtx.getUser(request);
2128
2083
  if (!user) {
2129
- return jsonResponse2({ error: "Authentication required" }, 401);
2084
+ return json({ error: "Authentication required" }, 401);
2130
2085
  }
2131
2086
  const isAdminUser = await module.isAdmin(user.id);
2132
2087
  if (!isAdminUser) {
2133
- return jsonResponse2({ error: "Admin access required" }, 403);
2088
+ return json({ error: "Admin access required" }, 403);
2134
2089
  }
2135
2090
  const url = new URL(request.url);
2136
2091
  const segments = url.pathname.split("/").filter(Boolean);
2137
2092
  const targetId = segments[3];
2138
2093
  if (!targetId) {
2139
- return jsonResponse2({ error: "Missing user ID in path" }, 400);
2094
+ return json({ error: "Missing user ID in path" }, 400);
2140
2095
  }
2141
2096
  try {
2142
2097
  const result = await module.impersonate(user.id, decodeURIComponent(targetId));
2143
- return jsonResponse2(result);
2098
+ return json(result);
2144
2099
  } catch (err2) {
2145
- return jsonResponse2(
2100
+ return json(
2146
2101
  { error: err2 instanceof Error ? err2.message : "Impersonation failed" },
2147
2102
  403
2148
2103
  );
@@ -2221,29 +2176,14 @@ function createAnonymousAuthModule(config, db, sessionManager) {
2221
2176
  }
2222
2177
 
2223
2178
  // src/auth/anonymous-plugin.ts
2224
- function jsonResponse3(body, status = 200) {
2225
- return new Response(JSON.stringify(body), {
2226
- status,
2227
- headers: { "Content-Type": "application/json" }
2228
- });
2229
- }
2230
- async function parseBody2(request) {
2231
- try {
2232
- return await request.json();
2233
- } catch {
2234
- return {};
2235
- }
2236
- }
2237
2179
  function anonymousAuth(config) {
2238
2180
  return {
2239
2181
  id: "kavach-anonymous",
2240
2182
  async init(ctx) {
2241
- const sessionSecret = ctx.config.auth?.session?.secret;
2242
- if (!sessionSecret) {
2183
+ if (!ctx.sessionManager) {
2243
2184
  throw new Error("anonymousAuth plugin requires auth.session.secret to be configured");
2244
2185
  }
2245
- const sessionManager = createSessionManager({ secret: sessionSecret }, ctx.db);
2246
- const mod = createAnonymousAuthModule(config ?? {}, ctx.db, sessionManager);
2186
+ const mod = createAnonymousAuthModule(config ?? {}, ctx.db, ctx.sessionManager);
2247
2187
  ctx.addEndpoint({
2248
2188
  method: "POST",
2249
2189
  path: "/auth/anonymous",
@@ -2254,9 +2194,9 @@ function anonymousAuth(config) {
2254
2194
  async handler(_request, _endpointCtx) {
2255
2195
  try {
2256
2196
  const result = await mod.createAnonymousUser();
2257
- return jsonResponse3({ userId: result.userId, sessionToken: result.sessionToken });
2197
+ return json({ userId: result.userId, sessionToken: result.sessionToken });
2258
2198
  } catch (err2) {
2259
- return jsonResponse3(
2199
+ return json(
2260
2200
  { error: err2 instanceof Error ? err2.message : "Failed to create anonymous user" },
2261
2201
  500
2262
2202
  );
@@ -2273,21 +2213,22 @@ function anonymousAuth(config) {
2273
2213
  async handler(request, endpointCtx) {
2274
2214
  const user = await endpointCtx.getUser(request);
2275
2215
  if (!user) {
2276
- return jsonResponse3({ error: "Authentication required" }, 401);
2216
+ return json({ error: "Authentication required" }, 401);
2277
2217
  }
2278
- const body = await parseBody2(request);
2279
- const email = typeof body.email === "string" ? body.email.trim() : null;
2280
- const name = typeof body.name === "string" ? body.name.trim() : void 0;
2218
+ const bodyResult = await parseBody(request);
2219
+ if (!bodyResult.ok) return bodyResult.response;
2220
+ const email = typeof bodyResult.data.email === "string" ? bodyResult.data.email.trim() : null;
2221
+ const name = typeof bodyResult.data.name === "string" ? bodyResult.data.name.trim() : void 0;
2281
2222
  if (!email) {
2282
- return jsonResponse3({ error: "Missing required field: email" }, 400);
2223
+ return json({ error: "Missing required field: email" }, 400);
2283
2224
  }
2284
2225
  try {
2285
2226
  await mod.upgradeUser(user.id, { email, name });
2286
- return jsonResponse3({ upgraded: true });
2227
+ return json({ upgraded: true });
2287
2228
  } catch (err2) {
2288
2229
  const message = err2 instanceof Error ? err2.message : "Upgrade failed";
2289
2230
  const status = message.includes("not an anonymous user") ? 400 : 500;
2290
- return jsonResponse3({ error: message }, status);
2231
+ return json({ error: message }, status);
2291
2232
  }
2292
2233
  }
2293
2234
  });
@@ -2301,10 +2242,10 @@ function anonymousAuth(config) {
2301
2242
  async handler(request, endpointCtx) {
2302
2243
  const user = await endpointCtx.getUser(request);
2303
2244
  if (!user) {
2304
- return jsonResponse3({ error: "Authentication required" }, 401);
2245
+ return json({ error: "Authentication required" }, 401);
2305
2246
  }
2306
2247
  const anonymous = await mod.isAnonymous(user.id);
2307
- return jsonResponse3({ anonymous });
2248
+ return json({ anonymous });
2308
2249
  }
2309
2250
  });
2310
2251
  }
@@ -2410,7 +2351,7 @@ function createApiKeyManagerModule(config, db) {
2410
2351
  const url = new URL(request.url);
2411
2352
  const { pathname } = url;
2412
2353
  const { method } = request;
2413
- const json3 = (data, status = 200) => new Response(JSON.stringify(data), {
2354
+ const json2 = (data, status = 200) => new Response(JSON.stringify(data), {
2414
2355
  status,
2415
2356
  headers: { "Content-Type": "application/json" }
2416
2357
  });
@@ -2419,11 +2360,11 @@ function createApiKeyManagerModule(config, db) {
2419
2360
  try {
2420
2361
  body = await request.json();
2421
2362
  } catch {
2422
- return json3({ error: "Invalid JSON body" }, 400);
2363
+ return json2({ error: "Invalid JSON body" }, 400);
2423
2364
  }
2424
2365
  const b = body;
2425
2366
  if (typeof b.userId !== "string" || typeof b.name !== "string" || !Array.isArray(b.permissions)) {
2426
- return json3({ error: "Missing required fields: userId, name, permissions" }, 400);
2367
+ return json2({ error: "Missing required fields: userId, name, permissions" }, 400);
2427
2368
  }
2428
2369
  const expiresAt = b.expiresAt ? new Date(b.expiresAt) : void 0;
2429
2370
  const result = await create({
@@ -2432,28 +2373,28 @@ function createApiKeyManagerModule(config, db) {
2432
2373
  permissions: b.permissions,
2433
2374
  expiresAt
2434
2375
  });
2435
- return json3(result, 201);
2376
+ return json2(result, 201);
2436
2377
  }
2437
2378
  const listMatch = /^\/auth\/api-keys\/([^/]+)$/.exec(pathname);
2438
2379
  if (method === "GET" && listMatch) {
2439
2380
  const userId = decodeURIComponent(listMatch[1] ?? "");
2440
2381
  const keys = await list(userId);
2441
- return json3(keys);
2382
+ return json2(keys);
2442
2383
  }
2443
2384
  const deleteMatch = /^\/auth\/api-keys\/([^/]+)$/.exec(pathname);
2444
2385
  if (method === "DELETE" && deleteMatch) {
2445
2386
  const keyId = decodeURIComponent(deleteMatch[1] ?? "");
2446
2387
  await revoke(keyId);
2447
- return json3({ success: true });
2388
+ return json2({ success: true });
2448
2389
  }
2449
2390
  const rotateMatch = /^\/auth\/api-keys\/([^/]+)\/rotate$/.exec(pathname);
2450
2391
  if (method === "POST" && rotateMatch) {
2451
2392
  const keyId = decodeURIComponent(rotateMatch[1] ?? "");
2452
2393
  try {
2453
2394
  const result = await rotate(keyId);
2454
- return json3(result);
2395
+ return json2(result);
2455
2396
  } catch (err2) {
2456
- return json3({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 404);
2397
+ return json2({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 404);
2457
2398
  }
2458
2399
  }
2459
2400
  return null;
@@ -2470,19 +2411,6 @@ function createApiKeyManagerModule(config, db) {
2470
2411
  }
2471
2412
 
2472
2413
  // src/auth/api-key-plugin.ts
2473
- function jsonResponse4(body, status = 200) {
2474
- return new Response(JSON.stringify(body), {
2475
- status,
2476
- headers: { "Content-Type": "application/json" }
2477
- });
2478
- }
2479
- async function parseBody3(request) {
2480
- try {
2481
- return await request.json();
2482
- } catch {
2483
- return {};
2484
- }
2485
- }
2486
2414
  function apiKeys2(config) {
2487
2415
  return {
2488
2416
  id: "kavach-api-key",
@@ -2498,15 +2426,16 @@ function apiKeys2(config) {
2498
2426
  async handler(request, endpointCtx) {
2499
2427
  const user = await endpointCtx.getUser(request);
2500
2428
  if (!user) {
2501
- return jsonResponse4({ error: "Authentication required" }, 401);
2429
+ return json({ error: "Authentication required" }, 401);
2502
2430
  }
2503
- const body = await parseBody3(request);
2504
- const name = typeof body.name === "string" ? body.name.trim() : null;
2505
- const permissions2 = Array.isArray(body.permissions) ? body.permissions : null;
2431
+ const bodyResult = await parseBody(request);
2432
+ if (!bodyResult.ok) return bodyResult.response;
2433
+ const name = typeof bodyResult.data.name === "string" ? bodyResult.data.name.trim() : null;
2434
+ const permissions2 = Array.isArray(bodyResult.data.permissions) ? bodyResult.data.permissions : null;
2506
2435
  if (!name || !permissions2) {
2507
- return jsonResponse4({ error: "Missing required fields: name, permissions" }, 400);
2436
+ return json({ error: "Missing required fields: name, permissions" }, 400);
2508
2437
  }
2509
- const expiresAt = body.expiresAt ? new Date(body.expiresAt) : void 0;
2438
+ const expiresAt = bodyResult.data.expiresAt ? new Date(bodyResult.data.expiresAt) : void 0;
2510
2439
  try {
2511
2440
  const result = await module.create({
2512
2441
  userId: user.id,
@@ -2514,9 +2443,9 @@ function apiKeys2(config) {
2514
2443
  permissions: permissions2,
2515
2444
  expiresAt
2516
2445
  });
2517
- return jsonResponse4(result, 201);
2446
+ return json(result, 201);
2518
2447
  } catch (err2) {
2519
- return jsonResponse4(
2448
+ return json(
2520
2449
  { error: err2 instanceof Error ? err2.message : "Failed to create API key" },
2521
2450
  500
2522
2451
  );
@@ -2533,10 +2462,10 @@ function apiKeys2(config) {
2533
2462
  async handler(request, endpointCtx) {
2534
2463
  const user = await endpointCtx.getUser(request);
2535
2464
  if (!user) {
2536
- return jsonResponse4({ error: "Authentication required" }, 401);
2465
+ return json({ error: "Authentication required" }, 401);
2537
2466
  }
2538
2467
  const keys = await module.list(user.id);
2539
- return jsonResponse4({ apiKeys: keys });
2468
+ return json({ apiKeys: keys });
2540
2469
  }
2541
2470
  });
2542
2471
  ctx.addEndpoint({
@@ -2549,21 +2478,21 @@ function apiKeys2(config) {
2549
2478
  async handler(request, endpointCtx) {
2550
2479
  const user = await endpointCtx.getUser(request);
2551
2480
  if (!user) {
2552
- return jsonResponse4({ error: "Authentication required" }, 401);
2481
+ return json({ error: "Authentication required" }, 401);
2553
2482
  }
2554
2483
  const url = new URL(request.url);
2555
2484
  const segments = url.pathname.split("/").filter(Boolean);
2556
2485
  const keyId = segments[2];
2557
2486
  if (!keyId) {
2558
- return jsonResponse4({ error: "Missing API key ID in path" }, 400);
2487
+ return json({ error: "Missing API key ID in path" }, 400);
2559
2488
  }
2560
2489
  const keys = await module.list(user.id);
2561
2490
  const owned = keys.some((k) => k.id === decodeURIComponent(keyId));
2562
2491
  if (!owned) {
2563
- return jsonResponse4({ error: "API key not found" }, 404);
2492
+ return json({ error: "API key not found" }, 404);
2564
2493
  }
2565
2494
  await module.revoke(decodeURIComponent(keyId));
2566
- return jsonResponse4({ revoked: true });
2495
+ return json({ revoked: true });
2567
2496
  }
2568
2497
  });
2569
2498
  ctx.addEndpoint({
@@ -2576,24 +2505,24 @@ function apiKeys2(config) {
2576
2505
  async handler(request, endpointCtx) {
2577
2506
  const user = await endpointCtx.getUser(request);
2578
2507
  if (!user) {
2579
- return jsonResponse4({ error: "Authentication required" }, 401);
2508
+ return json({ error: "Authentication required" }, 401);
2580
2509
  }
2581
2510
  const url = new URL(request.url);
2582
2511
  const segments = url.pathname.split("/").filter(Boolean);
2583
2512
  const keyId = segments[2];
2584
2513
  if (!keyId) {
2585
- return jsonResponse4({ error: "Missing API key ID in path" }, 400);
2514
+ return json({ error: "Missing API key ID in path" }, 400);
2586
2515
  }
2587
2516
  const keys = await module.list(user.id);
2588
2517
  const owned = keys.some((k) => k.id === decodeURIComponent(keyId));
2589
2518
  if (!owned) {
2590
- return jsonResponse4({ error: "API key not found" }, 404);
2519
+ return json({ error: "API key not found" }, 404);
2591
2520
  }
2592
2521
  try {
2593
2522
  const result = await module.rotate(decodeURIComponent(keyId));
2594
- return jsonResponse4(result);
2523
+ return json(result);
2595
2524
  } catch (err2) {
2596
- return jsonResponse4(
2525
+ return json(
2597
2526
  { error: err2 instanceof Error ? err2.message : "Failed to rotate API key" },
2598
2527
  400
2599
2528
  );
@@ -2983,13 +2912,13 @@ function customSession(config = {}) {
2983
2912
  const url = new URL(request.url);
2984
2913
  const sessionId = url.searchParams.get("sessionId");
2985
2914
  if (!sessionId) {
2986
- return jsonResponse5({ error: "Missing required query parameter: sessionId" }, 400);
2915
+ return jsonResponse2({ error: "Missing required query parameter: sessionId" }, 400);
2987
2916
  }
2988
2917
  try {
2989
2918
  const fields = await mod.getSessionFields(sessionId);
2990
- return jsonResponse5({ fields: fields ?? {} });
2919
+ return jsonResponse2({ fields: fields ?? {} });
2991
2920
  } catch (err2) {
2992
- return jsonResponse5(
2921
+ return jsonResponse2(
2993
2922
  { error: err2 instanceof Error ? err2.message : "Failed to get session fields" },
2994
2923
  500
2995
2924
  );
@@ -3008,23 +2937,23 @@ function customSession(config = {}) {
3008
2937
  try {
3009
2938
  body = await request.json();
3010
2939
  } catch {
3011
- return jsonResponse5({ error: "Invalid JSON body" }, 400);
2940
+ return jsonResponse2({ error: "Invalid JSON body" }, 400);
3012
2941
  }
3013
2942
  const sessionId = typeof body.sessionId === "string" ? body.sessionId : null;
3014
2943
  if (!sessionId) {
3015
- return jsonResponse5({ error: "Missing required field: sessionId" }, 400);
2944
+ return jsonResponse2({ error: "Missing required field: sessionId" }, 400);
3016
2945
  }
3017
2946
  const fields = body.fields !== null && body.fields !== void 0 && typeof body.fields === "object" && !Array.isArray(body.fields) ? body.fields : null;
3018
2947
  if (!fields) {
3019
- return jsonResponse5({ error: "Missing or invalid field: fields" }, 400);
2948
+ return jsonResponse2({ error: "Missing or invalid field: fields" }, 400);
3020
2949
  }
3021
2950
  try {
3022
2951
  await mod.updateSessionFields(sessionId, fields);
3023
- return jsonResponse5({ updated: true });
2952
+ return jsonResponse2({ updated: true });
3024
2953
  } catch (err2) {
3025
2954
  const message = err2 instanceof Error ? err2.message : "Update failed";
3026
2955
  const status = message.includes("not found") ? 404 : 500;
3027
- return jsonResponse5({ error: message }, status);
2956
+ return jsonResponse2({ error: message }, status);
3028
2957
  }
3029
2958
  }
3030
2959
  });
@@ -3034,7 +2963,7 @@ function customSession(config = {}) {
3034
2963
  }
3035
2964
  };
3036
2965
  }
3037
- function jsonResponse5(body, status = 200) {
2966
+ function jsonResponse2(body, status = 200) {
3038
2967
  return new Response(JSON.stringify(body), {
3039
2968
  status,
3040
2969
  headers: { "Content-Type": "application/json" }
@@ -3047,13 +2976,13 @@ var DEFAULT_CODE_EXPIRY_SECONDS = 900;
3047
2976
  var DEFAULT_POLL_INTERVAL_SECONDS = 5;
3048
2977
  var USER_CODE_ALPHABET = "BCDFGHJKLMNPQRSTVWXZ";
3049
2978
  var SLOW_DOWN_THRESHOLD_MS = 4e3;
3050
- function jsonResponse6(body, status = 200) {
2979
+ function jsonResponse3(body, status = 200) {
3051
2980
  return new Response(JSON.stringify(body), {
3052
2981
  status,
3053
2982
  headers: { "Content-Type": "application/json" }
3054
2983
  });
3055
2984
  }
3056
- async function parseBody4(request) {
2985
+ async function parseBody2(request) {
3057
2986
  try {
3058
2987
  return await request.json();
3059
2988
  } catch {
@@ -3177,7 +3106,7 @@ function createDeviceAuthModule(config) {
3177
3106
  const { method, pathname } = { method: request.method, pathname: url.pathname };
3178
3107
  if (method === "POST" && pathname.endsWith("/auth/device/code")) {
3179
3108
  const response = await requestCode();
3180
- return jsonResponse6({
3109
+ return jsonResponse3({
3181
3110
  device_code: response.deviceCode,
3182
3111
  user_code: response.userCode,
3183
3112
  verification_uri: response.verificationUri,
@@ -3187,17 +3116,17 @@ function createDeviceAuthModule(config) {
3187
3116
  });
3188
3117
  }
3189
3118
  if (method === "POST" && pathname.endsWith("/auth/device/token")) {
3190
- const body = await parseBody4(request);
3119
+ const body = await parseBody2(request);
3191
3120
  const deviceCode = typeof body.device_code === "string" ? body.device_code : null;
3192
3121
  if (!deviceCode) {
3193
- return jsonResponse6(
3122
+ return jsonResponse3(
3194
3123
  { error: "invalid_request", error_description: "Missing device_code" },
3195
3124
  400
3196
3125
  );
3197
3126
  }
3198
3127
  const grant = grantsByDevice.get(deviceCode);
3199
3128
  if (grant?.lastPolledAt && Date.now() - grant.lastPolledAt < SLOW_DOWN_THRESHOLD_MS) {
3200
- return jsonResponse6(
3129
+ return jsonResponse3(
3201
3130
  {
3202
3131
  error: "slow_down",
3203
3132
  error_description: "Polling too frequently",
@@ -3208,10 +3137,10 @@ function createDeviceAuthModule(config) {
3208
3137
  }
3209
3138
  const status = await checkAuthorization(deviceCode);
3210
3139
  if (status.status === "authorized") {
3211
- return jsonResponse6({ authorized: true, user_id: status.userId });
3140
+ return jsonResponse3({ authorized: true, user_id: status.userId });
3212
3141
  }
3213
3142
  if (status.status === "pending") {
3214
- return jsonResponse6(
3143
+ return jsonResponse3(
3215
3144
  {
3216
3145
  error: "authorization_pending",
3217
3146
  error_description: "The user has not yet authorized the device"
@@ -3220,7 +3149,7 @@ function createDeviceAuthModule(config) {
3220
3149
  );
3221
3150
  }
3222
3151
  if (status.status === "denied") {
3223
- return jsonResponse6(
3152
+ return jsonResponse3(
3224
3153
  {
3225
3154
  error: "access_denied",
3226
3155
  error_description: "The user denied the authorization request"
@@ -3228,7 +3157,7 @@ function createDeviceAuthModule(config) {
3228
3157
  400
3229
3158
  );
3230
3159
  }
3231
- return jsonResponse6(
3160
+ return jsonResponse3(
3232
3161
  {
3233
3162
  error: "expired_token",
3234
3163
  error_description: "The device code has expired"
@@ -3237,12 +3166,12 @@ function createDeviceAuthModule(config) {
3237
3166
  );
3238
3167
  }
3239
3168
  if (method === "POST" && pathname.endsWith("/auth/device/authorize")) {
3240
- const body = await parseBody4(request);
3169
+ const body = await parseBody2(request);
3241
3170
  const userCode = typeof body.user_code === "string" ? body.user_code : null;
3242
3171
  const userId = typeof body.user_id === "string" ? body.user_id : null;
3243
3172
  const action = typeof body.action === "string" ? body.action : "approve";
3244
3173
  if (!userCode || !userId) {
3245
- return jsonResponse6(
3174
+ return jsonResponse3(
3246
3175
  { error: "invalid_request", error_description: "Missing user_code or user_id" },
3247
3176
  400
3248
3177
  );
@@ -3250,12 +3179,12 @@ function createDeviceAuthModule(config) {
3250
3179
  try {
3251
3180
  if (action === "deny") {
3252
3181
  await deny(userCode);
3253
- return jsonResponse6({ denied: true });
3182
+ return jsonResponse3({ denied: true });
3254
3183
  }
3255
3184
  await authorize(userCode, userId);
3256
- return jsonResponse6({ authorized: true });
3185
+ return jsonResponse3({ authorized: true });
3257
3186
  } catch (err2) {
3258
- return jsonResponse6(
3187
+ return jsonResponse3(
3259
3188
  {
3260
3189
  error: "invalid_request",
3261
3190
  error_description: err2 instanceof Error ? err2.message : "Authorization failed"
@@ -3536,31 +3465,16 @@ function createEmailOtpModule(config, db, sessionManager) {
3536
3465
  }
3537
3466
 
3538
3467
  // src/auth/email-otp-plugin.ts
3539
- function jsonResponse7(body, status = 200) {
3540
- return new Response(JSON.stringify(body), {
3541
- status,
3542
- headers: { "Content-Type": "application/json" }
3543
- });
3544
- }
3545
- async function parseBody5(request) {
3546
- try {
3547
- return await request.json();
3548
- } catch {
3549
- return {};
3550
- }
3551
- }
3552
3468
  function emailOtp(config) {
3553
3469
  return {
3554
3470
  id: "kavach-email-otp",
3555
3471
  async init(ctx) {
3556
- const sessionConfig = ctx.config.auth?.session;
3557
- if (!sessionConfig) {
3472
+ if (!ctx.sessionManager) {
3558
3473
  throw new Error(
3559
3474
  "kavach-email-otp plugin requires auth.session to be configured so that sessions can be issued on successful verification."
3560
3475
  );
3561
3476
  }
3562
- const sessionManager = createSessionManager(sessionConfig, ctx.db);
3563
- const module = createEmailOtpModule(config, ctx.db, sessionManager);
3477
+ const module = createEmailOtpModule(config, ctx.db, ctx.sessionManager);
3564
3478
  ctx.addEndpoint({
3565
3479
  method: "POST",
3566
3480
  path: "/auth/email-otp/send",
@@ -3569,19 +3483,17 @@ function emailOtp(config) {
3569
3483
  description: "Send a one-time passcode to the provided email address"
3570
3484
  },
3571
3485
  async handler(request) {
3572
- const body = await parseBody5(request);
3573
- const rawEmail = typeof body.email === "string" ? body.email.trim().toLowerCase() : null;
3486
+ const bodyResult = await parseBody(request);
3487
+ if (!bodyResult.ok) return bodyResult.response;
3488
+ const rawEmail = typeof bodyResult.data.email === "string" ? bodyResult.data.email.trim().toLowerCase() : null;
3574
3489
  if (!rawEmail) {
3575
- return jsonResponse7({ error: "Missing required field: email" }, 400);
3490
+ return json({ error: "Missing required field: email" }, 400);
3576
3491
  }
3577
3492
  try {
3578
3493
  const result = await module.sendCode(rawEmail);
3579
- return jsonResponse7(result);
3494
+ return json(result);
3580
3495
  } catch (err2) {
3581
- return jsonResponse7(
3582
- { error: err2 instanceof Error ? err2.message : "Failed to send OTP" },
3583
- 500
3584
- );
3496
+ return json({ error: err2 instanceof Error ? err2.message : "Failed to send OTP" }, 500);
3585
3497
  }
3586
3498
  }
3587
3499
  });
@@ -3593,17 +3505,18 @@ function emailOtp(config) {
3593
3505
  description: "Verify an OTP code and return a session on success"
3594
3506
  },
3595
3507
  async handler(request) {
3596
- const body = await parseBody5(request);
3597
- const rawEmail = typeof body.email === "string" ? body.email.trim().toLowerCase() : null;
3598
- const code2 = typeof body.code === "string" ? body.code.trim() : null;
3508
+ const bodyResult = await parseBody(request);
3509
+ if (!bodyResult.ok) return bodyResult.response;
3510
+ const rawEmail = typeof bodyResult.data.email === "string" ? bodyResult.data.email.trim().toLowerCase() : null;
3511
+ const code2 = typeof bodyResult.data.code === "string" ? bodyResult.data.code.trim() : null;
3599
3512
  if (!rawEmail || !code2) {
3600
- return jsonResponse7({ error: "Missing required fields: email, code" }, 400);
3513
+ return json({ error: "Missing required fields: email, code" }, 400);
3601
3514
  }
3602
3515
  const result = await module.verifyCode(rawEmail, code2);
3603
3516
  if (!result) {
3604
- return jsonResponse7({ error: "Invalid or expired OTP code" }, 401);
3517
+ return json({ error: "Invalid or expired OTP code" }, 401);
3605
3518
  }
3606
- return jsonResponse7(result);
3519
+ return json(result);
3607
3520
  }
3608
3521
  });
3609
3522
  }
@@ -3614,7 +3527,7 @@ var TOKEN_PURPOSE = "email-verify";
3614
3527
  function makeError(code2, message, details) {
3615
3528
  return { code: code2, message, ...details !== void 0 ? { details } : {} };
3616
3529
  }
3617
- function jsonResponse8(body, status = 200) {
3530
+ function jsonResponse4(body, status = 200) {
3618
3531
  return new Response(JSON.stringify(body), {
3619
3532
  status,
3620
3533
  headers: { "Content-Type": "application/json" }
@@ -3706,29 +3619,29 @@ function createEmailVerificationModule(config, db, tokenModule) {
3706
3619
  try {
3707
3620
  body = await request.json();
3708
3621
  } catch {
3709
- return jsonResponse8({ error: "Invalid JSON body" }, 400);
3622
+ return jsonResponse4({ error: "Invalid JSON body" }, 400);
3710
3623
  }
3711
3624
  const b = body;
3712
3625
  if (pathname === "/auth/verify-email/send") {
3713
3626
  if (typeof b.userId !== "string" || typeof b.email !== "string") {
3714
- return jsonResponse8({ error: "Missing required fields: userId, email" }, 400);
3627
+ return jsonResponse4({ error: "Missing required fields: userId, email" }, 400);
3715
3628
  }
3716
3629
  const result = await sendVerification(b.userId, b.email);
3717
3630
  if (!result.success) {
3718
3631
  const status = result.error.code === "USER_NOT_FOUND" ? 404 : 500;
3719
- return jsonResponse8({ error: result.error.message }, status);
3632
+ return jsonResponse4({ error: result.error.message }, status);
3720
3633
  }
3721
3634
  return new Response(null, { status: 204 });
3722
3635
  }
3723
3636
  if (pathname === "/auth/verify-email/confirm") {
3724
3637
  if (typeof b.token !== "string") {
3725
- return jsonResponse8({ error: "Missing required field: token" }, 400);
3638
+ return jsonResponse4({ error: "Missing required field: token" }, 400);
3726
3639
  }
3727
3640
  const result = await verify(b.token);
3728
3641
  if (!result.success) {
3729
- return jsonResponse8({ error: result.error.message }, 400);
3642
+ return jsonResponse4({ error: result.error.message }, 400);
3730
3643
  }
3731
- return jsonResponse8({ userId: result.data.userId, email: result.data.email });
3644
+ return jsonResponse4({ userId: result.data.userId, email: result.data.email });
3732
3645
  }
3733
3646
  return null;
3734
3647
  }
@@ -4041,7 +3954,7 @@ data: ${data}
4041
3954
 
4042
3955
  `;
4043
3956
  }
4044
- function extractToken(request) {
3957
+ function extractToken2(request) {
4045
3958
  const auth = request.headers.get("authorization");
4046
3959
  if (auth?.startsWith("Bearer ")) {
4047
3960
  return auth.slice(7).trim() || null;
@@ -4157,7 +4070,7 @@ function createEventStreamModule(config) {
4157
4070
  start(controller) {
4158
4071
  void (async () => {
4159
4072
  if (requireAuth) {
4160
- const token = extractToken(request) ?? params.token ?? null;
4073
+ const token = extractToken2(request) ?? params.token ?? null;
4161
4074
  if (!token) {
4162
4075
  controller.enqueue(
4163
4076
  new TextEncoder().encode(
@@ -4762,19 +4675,6 @@ function createGdprModule(db) {
4762
4675
  }
4763
4676
 
4764
4677
  // src/auth/gdpr-plugin.ts
4765
- function jsonResponse9(body, status = 200) {
4766
- return new Response(JSON.stringify(body), {
4767
- status,
4768
- headers: { "Content-Type": "application/json" }
4769
- });
4770
- }
4771
- async function parseBody6(request) {
4772
- try {
4773
- return await request.json();
4774
- } catch {
4775
- return {};
4776
- }
4777
- }
4778
4678
  function gdpr() {
4779
4679
  return {
4780
4680
  id: "kavach-gdpr",
@@ -4790,16 +4690,13 @@ function gdpr() {
4790
4690
  async handler(request, endpointCtx) {
4791
4691
  const user = await endpointCtx.getUser(request);
4792
4692
  if (!user) {
4793
- return jsonResponse9({ error: "Authentication required" }, 401);
4693
+ return json({ error: "Authentication required" }, 401);
4794
4694
  }
4795
4695
  try {
4796
4696
  const data = await module.exportUserData(user.id);
4797
- return jsonResponse9(data);
4697
+ return json(data);
4798
4698
  } catch (err2) {
4799
- return jsonResponse9(
4800
- { error: err2 instanceof Error ? err2.message : "Export failed" },
4801
- 500
4802
- );
4699
+ return json({ error: err2 instanceof Error ? err2.message : "Export failed" }, 500);
4803
4700
  }
4804
4701
  }
4805
4702
  });
@@ -4813,30 +4710,28 @@ function gdpr() {
4813
4710
  async handler(request, endpointCtx) {
4814
4711
  const user = await endpointCtx.getUser(request);
4815
4712
  if (!user) {
4816
- return jsonResponse9({ error: "Authentication required" }, 401);
4713
+ return json({ error: "Authentication required" }, 401);
4817
4714
  }
4818
- const body = await parseBody6(request);
4819
- if (body.confirm !== "delete my account") {
4820
- return jsonResponse9(
4715
+ const bodyResult = await parseBody(request);
4716
+ if (!bodyResult.ok) return bodyResult.response;
4717
+ if (bodyResult.data.confirm !== "delete my account") {
4718
+ return json(
4821
4719
  {
4822
4720
  error: 'Confirmation required. Send { "confirm": "delete my account" } in the request body.'
4823
4721
  },
4824
4722
  400
4825
4723
  );
4826
4724
  }
4827
- const keepAuditLogs = typeof body.keepAuditLogs === "boolean" ? body.keepAuditLogs : true;
4828
- const deleteOrganizations = typeof body.deleteOrganizations === "boolean" ? body.deleteOrganizations : false;
4725
+ const keepAuditLogs = typeof bodyResult.data.keepAuditLogs === "boolean" ? bodyResult.data.keepAuditLogs : true;
4726
+ const deleteOrganizations = typeof bodyResult.data.deleteOrganizations === "boolean" ? bodyResult.data.deleteOrganizations : false;
4829
4727
  try {
4830
4728
  const result = await module.deleteUser(user.id, {
4831
4729
  keepAuditLogs,
4832
4730
  deleteOrganizations
4833
4731
  });
4834
- return jsonResponse9({ success: true, ...result });
4732
+ return json({ success: true, ...result });
4835
4733
  } catch (err2) {
4836
- return jsonResponse9(
4837
- { error: err2 instanceof Error ? err2.message : "Deletion failed" },
4838
- 500
4839
- );
4734
+ return json({ error: err2 instanceof Error ? err2.message : "Deletion failed" }, 500);
4840
4735
  }
4841
4736
  }
4842
4737
  });
@@ -4850,13 +4745,13 @@ function gdpr() {
4850
4745
  async handler(request, endpointCtx) {
4851
4746
  const user = await endpointCtx.getUser(request);
4852
4747
  if (!user) {
4853
- return jsonResponse9({ error: "Authentication required" }, 401);
4748
+ return json({ error: "Authentication required" }, 401);
4854
4749
  }
4855
4750
  try {
4856
4751
  await module.anonymizeUser(user.id);
4857
- return jsonResponse9({ success: true });
4752
+ return json({ success: true });
4858
4753
  } catch (err2) {
4859
- return jsonResponse9(
4754
+ return json(
4860
4755
  { error: err2 instanceof Error ? err2.message : "Anonymization failed" },
4861
4756
  500
4862
4757
  );
@@ -5492,14 +5387,12 @@ function magicLink(config) {
5492
5387
  return {
5493
5388
  id: "kavach-magic-link",
5494
5389
  async init(ctx) {
5495
- const sessionConfig = ctx.config.auth?.session;
5496
- if (!sessionConfig) {
5390
+ if (!ctx.sessionManager) {
5497
5391
  throw new Error(
5498
5392
  "kavach-magic-link plugin requires auth.session to be configured so that sessions can be issued on successful verification."
5499
5393
  );
5500
5394
  }
5501
- const sessionManager = createSessionManager(sessionConfig, ctx.db);
5502
- const module = createMagicLinkModule(config, ctx.db, sessionManager);
5395
+ const module = createMagicLinkModule(config, ctx.db, ctx.sessionManager);
5503
5396
  const sendLimiter = createRateLimiter({ max: 5, window: 60 });
5504
5397
  ctx.addEndpoint({
5505
5398
  method: "POST",
@@ -5509,35 +5402,19 @@ function magicLink(config) {
5509
5402
  description: "Send a magic link to the provided email address"
5510
5403
  },
5511
5404
  handler: withRateLimit(async (request) => {
5512
- let body;
5513
- try {
5514
- body = await request.json();
5515
- } catch {
5516
- return new Response(JSON.stringify({ error: "Invalid JSON body" }), {
5517
- status: 400,
5518
- headers: { "Content-Type": "application/json" }
5519
- });
5520
- }
5521
- const b = body;
5522
- const rawEmail = typeof b.email === "string" ? b.email.trim().toLowerCase() : null;
5405
+ const bodyResult = await parseBody(request);
5406
+ if (!bodyResult.ok) return bodyResult.response;
5407
+ const rawEmail = typeof bodyResult.data.email === "string" ? bodyResult.data.email.trim().toLowerCase() : null;
5523
5408
  if (!rawEmail) {
5524
- return new Response(JSON.stringify({ error: "Missing required field: email" }), {
5525
- status: 400,
5526
- headers: { "Content-Type": "application/json" }
5527
- });
5409
+ return json({ error: "Missing required field: email" }, 400);
5528
5410
  }
5529
5411
  try {
5530
5412
  const result = await module.sendLink(rawEmail);
5531
- return new Response(JSON.stringify(result), {
5532
- status: 200,
5533
- headers: { "Content-Type": "application/json" }
5534
- });
5413
+ return json(result);
5535
5414
  } catch (err2) {
5536
- return new Response(
5537
- JSON.stringify({
5538
- error: err2 instanceof Error ? err2.message : "Failed to send magic link"
5539
- }),
5540
- { status: 500, headers: { "Content-Type": "application/json" } }
5415
+ return json(
5416
+ { error: err2 instanceof Error ? err2.message : "Failed to send magic link" },
5417
+ 500
5541
5418
  );
5542
5419
  }
5543
5420
  }, sendLimiter)
@@ -5552,22 +5429,13 @@ function magicLink(config) {
5552
5429
  const url = new URL(request.url);
5553
5430
  const token = url.searchParams.get("token");
5554
5431
  if (!token) {
5555
- return new Response(JSON.stringify({ error: "Missing token query parameter" }), {
5556
- status: 400,
5557
- headers: { "Content-Type": "application/json" }
5558
- });
5432
+ return json({ error: "Missing token query parameter" }, 400);
5559
5433
  }
5560
5434
  const result = await module.verify(token);
5561
5435
  if (!result) {
5562
- return new Response(JSON.stringify({ error: "Invalid or expired magic link" }), {
5563
- status: 401,
5564
- headers: { "Content-Type": "application/json" }
5565
- });
5436
+ return json({ error: "Invalid or expired magic link" }, 401);
5566
5437
  }
5567
- return new Response(JSON.stringify(result), {
5568
- status: 200,
5569
- headers: { "Content-Type": "application/json" }
5570
- });
5438
+ return json(result);
5571
5439
  }
5572
5440
  });
5573
5441
  }
@@ -5792,7 +5660,7 @@ function createOAuthModule(db, config) {
5792
5660
  pruneExpiredStates
5793
5661
  };
5794
5662
  }
5795
- function jsonResponse10(body, status = 200) {
5663
+ function jsonResponse5(body, status = 200) {
5796
5664
  return new Response(JSON.stringify(body), {
5797
5665
  status,
5798
5666
  headers: { "Content-Type": "application/json" }
@@ -5810,8 +5678,12 @@ function oauth(config) {
5810
5678
  async init(ctx) {
5811
5679
  const module = createOAuthModule(ctx.db, config);
5812
5680
  const baseUrl = ctx.config.baseUrl ?? "";
5813
- const sessionConfig = ctx.config.auth?.session;
5814
- const sessionManager = sessionConfig ? createSessionManager(sessionConfig, ctx.db) : null;
5681
+ const sessionManager = ctx.sessionManager;
5682
+ if (!sessionManager) {
5683
+ throw new Error(
5684
+ "kavach-oauth plugin requires auth.session to be configured so that sessions can be issued on successful OAuth callback."
5685
+ );
5686
+ }
5815
5687
  const authorizeLimiter = createRateLimiter({ max: 20, window: 60 });
5816
5688
  function getRedirectUri(provider) {
5817
5689
  if (config.buildRedirectUri) {
@@ -5830,14 +5702,14 @@ function oauth(config) {
5830
5702
  const url = new URL(request.url);
5831
5703
  const provider = url.searchParams.get("_param_provider");
5832
5704
  if (!provider) {
5833
- return jsonResponse10({ error: "Missing provider parameter" }, 400);
5705
+ return jsonResponse5({ error: "Missing provider parameter" }, 400);
5834
5706
  }
5835
5707
  const redirectUri = getRedirectUri(provider);
5836
5708
  try {
5837
5709
  const { url: authUrl } = await module.getAuthorizationUrl(provider, redirectUri);
5838
5710
  return redirectResponse(authUrl);
5839
5711
  } catch (err2) {
5840
- return jsonResponse10(
5712
+ return jsonResponse5(
5841
5713
  { error: err2 instanceof Error ? err2.message : "Failed to build authorization URL" },
5842
5714
  400
5843
5715
  );
@@ -5854,10 +5726,10 @@ function oauth(config) {
5854
5726
  const code2 = url.searchParams.get("code");
5855
5727
  const state = url.searchParams.get("state");
5856
5728
  if (!provider) {
5857
- return jsonResponse10({ error: "Missing provider parameter" }, 400);
5729
+ return jsonResponse5({ error: "Missing provider parameter" }, 400);
5858
5730
  }
5859
5731
  if (!code2 || !state) {
5860
- return jsonResponse10({ error: "Missing code or state query parameter" }, 400);
5732
+ return jsonResponse5({ error: "Missing code or state query parameter" }, 400);
5861
5733
  }
5862
5734
  const redirectUri = getRedirectUri(provider);
5863
5735
  try {
@@ -5889,18 +5761,27 @@ function oauth(config) {
5889
5761
  raw: {}
5890
5762
  });
5891
5763
  }
5892
- if (sessionManager && userId !== "__pending__") {
5764
+ if (userId !== "__pending__") {
5893
5765
  const { session, token } = await sessionManager.create(userId);
5894
- const callbackUrl = `${baseUrl}/?session=${encodeURIComponent(JSON.stringify({ token, user: { id: userId, email }, expiresAt: session.expiresAt }))}`;
5895
- return redirectResponse(callbackUrl);
5766
+ const maxAge = Math.floor((session.expiresAt.getTime() - Date.now()) / 1e3);
5767
+ const cookie = buildSetCookie("kavach_session", token, maxAge);
5768
+ const userInfo = encodeURIComponent(JSON.stringify({ id: userId, email }));
5769
+ const callbackUrl = `${baseUrl}/?auth_user=${userInfo}`;
5770
+ return new Response(null, {
5771
+ status: 302,
5772
+ headers: {
5773
+ Location: callbackUrl,
5774
+ "Set-Cookie": cookie
5775
+ }
5776
+ });
5896
5777
  }
5897
- return jsonResponse10({
5778
+ return jsonResponse5({
5898
5779
  isNewAccount: result.isNewAccount,
5899
5780
  account: result.account,
5900
5781
  userInfo: result.userInfo
5901
5782
  });
5902
5783
  } catch (err2) {
5903
- return jsonResponse10(
5784
+ return jsonResponse5(
5904
5785
  { error: err2 instanceof Error ? err2.message : "OAuth callback failed" },
5905
5786
  400
5906
5787
  );
@@ -5917,29 +5798,29 @@ function oauth(config) {
5917
5798
  async handler(request, endpointCtx) {
5918
5799
  const user = await endpointCtx.getUser(request);
5919
5800
  if (!user) {
5920
- return jsonResponse10({ error: "Authentication required" }, 401);
5801
+ return jsonResponse5({ error: "Authentication required" }, 401);
5921
5802
  }
5922
5803
  let body;
5923
5804
  try {
5924
5805
  body = await request.json();
5925
5806
  } catch {
5926
- return jsonResponse10({ error: "Invalid JSON body" }, 400);
5807
+ return jsonResponse5({ error: "Invalid JSON body" }, 400);
5927
5808
  }
5928
5809
  const b = body;
5929
5810
  const provider = typeof b.provider === "string" ? b.provider : null;
5930
5811
  const userInfo = typeof b.userInfo === "object" && b.userInfo !== null ? b.userInfo : null;
5931
5812
  const tokens = typeof b.tokens === "object" && b.tokens !== null ? b.tokens : null;
5932
5813
  if (!provider || !userInfo || !tokens) {
5933
- return jsonResponse10(
5814
+ return jsonResponse5(
5934
5815
  { error: "Missing required fields: provider, userInfo, tokens" },
5935
5816
  400
5936
5817
  );
5937
5818
  }
5938
5819
  try {
5939
5820
  const account = await module.linkAccount(user.id, provider, userInfo, tokens);
5940
- return jsonResponse10({ account });
5821
+ return jsonResponse5({ account });
5941
5822
  } catch (err2) {
5942
- return jsonResponse10(
5823
+ return jsonResponse5(
5943
5824
  { error: err2 instanceof Error ? err2.message : "Failed to link account" },
5944
5825
  400
5945
5826
  );
@@ -5955,7 +5836,7 @@ function oauth(config) {
5955
5836
  id: p2.id,
5956
5837
  name: p2.name
5957
5838
  }));
5958
- return jsonResponse10({ providers });
5839
+ return jsonResponse5({ providers });
5959
5840
  }
5960
5841
  });
5961
5842
  }
@@ -7752,25 +7633,25 @@ function createOneTapModule(config, db, sessionManager) {
7752
7633
  const text3 = await request.text();
7753
7634
  formData = new URLSearchParams(text3);
7754
7635
  } catch {
7755
- return jsonResponse11({ error: "Failed to parse request body" }, 400);
7636
+ return jsonResponse6({ error: "Failed to parse request body" }, 400);
7756
7637
  }
7757
7638
  const credential = formData.get("credential");
7758
7639
  const bodyToken = formData.get(csrfCookieName);
7759
7640
  if (!credential) {
7760
- return jsonResponse11({ error: "Missing credential field" }, 400);
7641
+ return jsonResponse6({ error: "Missing credential field" }, 400);
7761
7642
  }
7762
7643
  const cookieToken = getCsrfCookie(request);
7763
7644
  if (!cookieToken || !bodyToken || cookieToken !== bodyToken) {
7764
- return jsonResponse11({ error: "CSRF token mismatch" }, 403);
7645
+ return jsonResponse6({ error: "CSRF token mismatch" }, 403);
7765
7646
  }
7766
7647
  let googleUser;
7767
7648
  try {
7768
7649
  googleUser = await verify(credential);
7769
7650
  } catch (err2) {
7770
7651
  if (err2 instanceof OneTapVerifyError && err2.code === "USER_NOT_FOUND") {
7771
- return jsonResponse11({ error: err2.message }, 403);
7652
+ return jsonResponse6({ error: err2.message }, 403);
7772
7653
  }
7773
- return jsonResponse11(
7654
+ return jsonResponse6(
7774
7655
  { error: err2 instanceof Error ? err2.message : "Token verification failed" },
7775
7656
  401
7776
7657
  );
@@ -7780,27 +7661,96 @@ function createOneTapModule(config, db, sessionManager) {
7780
7661
  user = await findOrCreateUser(googleUser);
7781
7662
  } catch (err2) {
7782
7663
  if (err2 instanceof OneTapVerifyError && err2.code === "USER_NOT_FOUND") {
7783
- return jsonResponse11({ error: err2.message }, 403);
7664
+ return jsonResponse6({ error: err2.message }, 403);
7784
7665
  }
7785
- return jsonResponse11(
7666
+ return jsonResponse6(
7786
7667
  { error: err2 instanceof Error ? err2.message : "Failed to resolve user" },
7787
7668
  500
7788
7669
  );
7789
7670
  }
7790
7671
  const { token: sessionToken, session } = await sessionManager.create(user.id);
7791
- return jsonResponse11({
7672
+ return jsonResponse6({
7792
7673
  user: { id: user.id, email: user.email },
7793
7674
  session: { token: sessionToken, expiresAt: session.expiresAt }
7794
7675
  });
7795
7676
  }
7796
7677
  return { verify, handleRequest };
7797
7678
  }
7798
- function jsonResponse11(body, status = 200) {
7679
+ function jsonResponse6(body, status = 200) {
7799
7680
  return new Response(JSON.stringify(body), {
7800
7681
  status,
7801
7682
  headers: { "Content-Type": "application/json" }
7802
7683
  });
7803
7684
  }
7685
+ var DEFAULT_MAX_AGE_SECONDS = 60 * 60 * 24 * 7;
7686
+ function createSessionManager(config, db) {
7687
+ if (!config.secret || config.secret.length < 32) {
7688
+ throw new Error("SessionManager: secret must be at least 32 characters.");
7689
+ }
7690
+ const maxAge = config.maxAge ?? DEFAULT_MAX_AGE_SECONDS;
7691
+ const keyObject = new TextEncoder().encode(config.secret);
7692
+ function rowToSession2(row) {
7693
+ return {
7694
+ id: row.id,
7695
+ userId: row.userId,
7696
+ expiresAt: row.expiresAt,
7697
+ createdAt: row.createdAt,
7698
+ ...row.metadata !== null && { metadata: row.metadata }
7699
+ };
7700
+ }
7701
+ async function create(userId, metadata) {
7702
+ const id = generateId();
7703
+ const now = /* @__PURE__ */ new Date();
7704
+ const expiresAt = new Date(now.getTime() + maxAge * 1e3);
7705
+ await db.insert(sessions).values({
7706
+ id,
7707
+ userId,
7708
+ expiresAt,
7709
+ metadata: metadata ?? null,
7710
+ createdAt: now
7711
+ });
7712
+ const token = await new SignJWT({ sub: id }).setProtectedHeader({ alg: "HS256" }).setIssuedAt().setExpirationTime(Math.floor(expiresAt.getTime() / 1e3)).sign(keyObject);
7713
+ const session = {
7714
+ id,
7715
+ userId,
7716
+ expiresAt,
7717
+ createdAt: now,
7718
+ ...metadata !== void 0 && { metadata }
7719
+ };
7720
+ return { session, token };
7721
+ }
7722
+ async function validate(token) {
7723
+ let sessionId;
7724
+ try {
7725
+ const { payload } = await jwtVerify(token, keyObject);
7726
+ if (typeof payload.sub !== "string" || !payload.sub) return null;
7727
+ sessionId = payload.sub;
7728
+ } catch {
7729
+ return null;
7730
+ }
7731
+ const now = /* @__PURE__ */ new Date();
7732
+ const rows = await db.select().from(sessions).where(and(eq(sessions.id, sessionId)));
7733
+ const row = rows[0];
7734
+ if (!row) return null;
7735
+ if (row.expiresAt <= now) {
7736
+ await db.delete(sessions).where(eq(sessions.id, sessionId));
7737
+ return null;
7738
+ }
7739
+ return rowToSession2(row);
7740
+ }
7741
+ async function revoke(sessionId) {
7742
+ await db.delete(sessions).where(eq(sessions.id, sessionId));
7743
+ }
7744
+ async function revokeAll(userId) {
7745
+ await db.delete(sessions).where(eq(sessions.userId, userId));
7746
+ }
7747
+ async function list(userId) {
7748
+ const now = /* @__PURE__ */ new Date();
7749
+ const rows = await db.select().from(sessions).where(and(eq(sessions.userId, userId)));
7750
+ return rows.filter((row) => row.expiresAt > now).sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()).map(rowToSession2);
7751
+ }
7752
+ return { create, validate, revoke, revokeAll, list };
7753
+ }
7804
7754
 
7805
7755
  // src/auth/one-tap-plugin.ts
7806
7756
  function oneTap(config) {
@@ -9092,14 +9042,14 @@ function rowToInvitation(row) {
9092
9042
  createdAt: row.createdAt
9093
9043
  };
9094
9044
  }
9095
- function jsonResponse12(body, status = 200) {
9045
+ function jsonResponse7(body, status = 200) {
9096
9046
  return new Response(JSON.stringify(body), {
9097
9047
  status,
9098
9048
  headers: { "Content-Type": "application/json" }
9099
9049
  });
9100
9050
  }
9101
9051
  function errorResponse(message, status) {
9102
- return jsonResponse12({ error: message }, status);
9052
+ return jsonResponse7({ error: message }, status);
9103
9053
  }
9104
9054
  function createOrgModule(config, db) {
9105
9055
  const maxMembers = config.maxMembers ?? DEFAULT_MAX_MEMBERS;
@@ -9405,7 +9355,7 @@ function createOrgModule(config, db) {
9405
9355
  try {
9406
9356
  const body = await request.json();
9407
9357
  const org = await create(body);
9408
- return jsonResponse12(org, 201);
9358
+ return jsonResponse7(org, 201);
9409
9359
  } catch (err2) {
9410
9360
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
9411
9361
  }
@@ -9415,7 +9365,7 @@ function createOrgModule(config, db) {
9415
9365
  const userId = userOrgMatch[1];
9416
9366
  if (!userId) return errorResponse("Missing userId", 400);
9417
9367
  const orgs = await list(userId);
9418
- return jsonResponse12(orgs);
9368
+ return jsonResponse7(orgs);
9419
9369
  }
9420
9370
  const orgBaseMatch = pathname.match(/^\/auth\/org\/([^/]+)(\/.*)?$/);
9421
9371
  if (!orgBaseMatch) return null;
@@ -9425,13 +9375,13 @@ function createOrgModule(config, db) {
9425
9375
  if (method === "GET" && subPath === "") {
9426
9376
  const org = await get(orgId);
9427
9377
  if (!org) return errorResponse("Organization not found", 404);
9428
- return jsonResponse12(org);
9378
+ return jsonResponse7(org);
9429
9379
  }
9430
9380
  if (method === "PATCH" && subPath === "") {
9431
9381
  try {
9432
9382
  const body = await request.json();
9433
9383
  const org = await update(orgId, body);
9434
- return jsonResponse12(org);
9384
+ return jsonResponse7(org);
9435
9385
  } catch (err2) {
9436
9386
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
9437
9387
  }
@@ -9439,7 +9389,7 @@ function createOrgModule(config, db) {
9439
9389
  if (method === "DELETE" && subPath === "") {
9440
9390
  try {
9441
9391
  await remove(orgId);
9442
- return jsonResponse12({ success: true });
9392
+ return jsonResponse7({ success: true });
9443
9393
  } catch (err2) {
9444
9394
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
9445
9395
  }
@@ -9448,14 +9398,14 @@ function createOrgModule(config, db) {
9448
9398
  try {
9449
9399
  const body = await request.json();
9450
9400
  const member = await addMember(orgId, body.userId, body.role);
9451
- return jsonResponse12(member, 201);
9401
+ return jsonResponse7(member, 201);
9452
9402
  } catch (err2) {
9453
9403
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
9454
9404
  }
9455
9405
  }
9456
9406
  if (method === "GET" && subPath === "/members") {
9457
9407
  const members = await getMembers(orgId);
9458
- return jsonResponse12(members);
9408
+ return jsonResponse7(members);
9459
9409
  }
9460
9410
  const memberMatch = subPath.match(/^\/members\/([^/]+)$/);
9461
9411
  if (method === "PATCH" && memberMatch) {
@@ -9464,7 +9414,7 @@ function createOrgModule(config, db) {
9464
9414
  try {
9465
9415
  const body = await request.json();
9466
9416
  const member = await updateMemberRole(orgId, userId, body.role);
9467
- return jsonResponse12(member);
9417
+ return jsonResponse7(member);
9468
9418
  } catch (err2) {
9469
9419
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
9470
9420
  }
@@ -9473,20 +9423,20 @@ function createOrgModule(config, db) {
9473
9423
  const userId = memberMatch[1];
9474
9424
  if (!userId) return errorResponse("Missing userId", 400);
9475
9425
  await removeMember(orgId, userId);
9476
- return jsonResponse12({ success: true });
9426
+ return jsonResponse7({ success: true });
9477
9427
  }
9478
9428
  if (method === "POST" && subPath === "/invite") {
9479
9429
  try {
9480
9430
  const body = await request.json();
9481
9431
  const invitation = await invite({ orgId, ...body });
9482
- return jsonResponse12(invitation, 201);
9432
+ return jsonResponse7(invitation, 201);
9483
9433
  } catch (err2) {
9484
9434
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
9485
9435
  }
9486
9436
  }
9487
9437
  if (method === "GET" && subPath === "/invitations") {
9488
9438
  const invitations = await listInvitations(orgId);
9489
- return jsonResponse12(invitations);
9439
+ return jsonResponse7(invitations);
9490
9440
  }
9491
9441
  const permMatch = subPath.match(/^\/permissions\/([^/]+)\/([^/]+)$/);
9492
9442
  if (method === "GET" && permMatch) {
@@ -9494,20 +9444,20 @@ function createOrgModule(config, db) {
9494
9444
  const permission = permMatch[2];
9495
9445
  if (!userId || !permission) return errorResponse("Missing userId or permission", 400);
9496
9446
  const allowed = await hasPermission(orgId, userId, permission);
9497
- return jsonResponse12({ allowed });
9447
+ return jsonResponse7({ allowed });
9498
9448
  }
9499
9449
  if (method === "POST" && subPath === "/roles") {
9500
9450
  try {
9501
9451
  const body = await request.json();
9502
9452
  const role = await createRole(orgId, body);
9503
- return jsonResponse12(role, 201);
9453
+ return jsonResponse7(role, 201);
9504
9454
  } catch (err2) {
9505
9455
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
9506
9456
  }
9507
9457
  }
9508
9458
  if (method === "GET" && subPath === "/roles") {
9509
9459
  const roles = await getRoles(orgId);
9510
- return jsonResponse12(roles);
9460
+ return jsonResponse7(roles);
9511
9461
  }
9512
9462
  return null;
9513
9463
  }
@@ -9522,7 +9472,7 @@ function createOrgModule(config, db) {
9522
9472
  try {
9523
9473
  const body = await request.json();
9524
9474
  const member = await acceptInvitation(invitationId, body.userId);
9525
- return jsonResponse12(member, 201);
9475
+ return jsonResponse7(member, 201);
9526
9476
  } catch (err2) {
9527
9477
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
9528
9478
  }
@@ -9532,7 +9482,7 @@ function createOrgModule(config, db) {
9532
9482
  const invitationId = revokeMatch[1];
9533
9483
  if (!invitationId) return errorResponse("Missing invitationId", 400);
9534
9484
  await revokeInvitation(invitationId);
9535
- return jsonResponse12({ success: true });
9485
+ return jsonResponse7({ success: true });
9536
9486
  }
9537
9487
  return handleRequest(request);
9538
9488
  }
@@ -9563,13 +9513,13 @@ function createOrgModule(config, db) {
9563
9513
  }
9564
9514
 
9565
9515
  // src/auth/organization-plugin.ts
9566
- function jsonResponse13(body, status = 200) {
9516
+ function jsonResponse8(body, status = 200) {
9567
9517
  return new Response(JSON.stringify(body), {
9568
9518
  status,
9569
9519
  headers: { "Content-Type": "application/json" }
9570
9520
  });
9571
9521
  }
9572
- async function parseBody7(request) {
9522
+ async function parseBody3(request) {
9573
9523
  try {
9574
9524
  return await request.json();
9575
9525
  } catch {
@@ -9592,20 +9542,20 @@ function organization(config) {
9592
9542
  async handler(request, endpointCtx) {
9593
9543
  const user = await endpointCtx.getUser(request);
9594
9544
  if (!user) {
9595
- return jsonResponse13({ error: "Authentication required" }, 401);
9545
+ return jsonResponse8({ error: "Authentication required" }, 401);
9596
9546
  }
9597
- const body = await parseBody7(request);
9547
+ const body = await parseBody3(request);
9598
9548
  const name = typeof body.name === "string" ? body.name.trim() : null;
9599
9549
  const slug = typeof body.slug === "string" ? body.slug.trim() : null;
9600
9550
  if (!name || !slug) {
9601
- return jsonResponse13({ error: "Missing required fields: name, slug" }, 400);
9551
+ return jsonResponse8({ error: "Missing required fields: name, slug" }, 400);
9602
9552
  }
9603
9553
  const metadata = body.metadata !== void 0 && typeof body.metadata === "object" && body.metadata !== null ? body.metadata : void 0;
9604
9554
  try {
9605
9555
  const org = await module.create({ name, slug, ownerId: user.id, metadata });
9606
- return jsonResponse13(org, 201);
9556
+ return jsonResponse8(org, 201);
9607
9557
  } catch (err2) {
9608
- return jsonResponse13(
9558
+ return jsonResponse8(
9609
9559
  { error: err2 instanceof Error ? err2.message : "Failed to create organization" },
9610
9560
  400
9611
9561
  );
@@ -9622,10 +9572,10 @@ function organization(config) {
9622
9572
  async handler(request, endpointCtx) {
9623
9573
  const user = await endpointCtx.getUser(request);
9624
9574
  if (!user) {
9625
- return jsonResponse13({ error: "Authentication required" }, 401);
9575
+ return jsonResponse8({ error: "Authentication required" }, 401);
9626
9576
  }
9627
9577
  const orgs = await module.list(user.id);
9628
- return jsonResponse13({ organizations: orgs });
9578
+ return jsonResponse8({ organizations: orgs });
9629
9579
  }
9630
9580
  });
9631
9581
  ctx.addEndpoint({
@@ -9638,23 +9588,23 @@ function organization(config) {
9638
9588
  async handler(request, endpointCtx) {
9639
9589
  const user = await endpointCtx.getUser(request);
9640
9590
  if (!user) {
9641
- return jsonResponse13({ error: "Authentication required" }, 401);
9591
+ return jsonResponse8({ error: "Authentication required" }, 401);
9642
9592
  }
9643
9593
  const url = new URL(request.url);
9644
9594
  const segments = url.pathname.split("/").filter(Boolean);
9645
9595
  const orgId = segments[2];
9646
9596
  if (!orgId) {
9647
- return jsonResponse13({ error: "Missing organization ID in path" }, 400);
9597
+ return jsonResponse8({ error: "Missing organization ID in path" }, 400);
9648
9598
  }
9649
9599
  const member = await module.getMember(orgId, user.id);
9650
9600
  if (!member || !ADMIN_ROLES.has(member.role)) {
9651
- return jsonResponse13({ error: "Admin or owner role required" }, 403);
9601
+ return jsonResponse8({ error: "Admin or owner role required" }, 403);
9652
9602
  }
9653
- const body = await parseBody7(request);
9603
+ const body = await parseBody3(request);
9654
9604
  const email = typeof body.email === "string" ? body.email.trim().toLowerCase() : null;
9655
9605
  const role = typeof body.role === "string" ? body.role : "member";
9656
9606
  if (!email) {
9657
- return jsonResponse13({ error: "Missing required field: email" }, 400);
9607
+ return jsonResponse8({ error: "Missing required field: email" }, 400);
9658
9608
  }
9659
9609
  try {
9660
9610
  const invitation = await module.invite({
@@ -9663,9 +9613,9 @@ function organization(config) {
9663
9613
  role,
9664
9614
  invitedBy: user.id
9665
9615
  });
9666
- return jsonResponse13(invitation, 201);
9616
+ return jsonResponse8(invitation, 201);
9667
9617
  } catch (err2) {
9668
- return jsonResponse13(
9618
+ return jsonResponse8(
9669
9619
  { error: err2 instanceof Error ? err2.message : "Failed to send invitation" },
9670
9620
  400
9671
9621
  );
@@ -9682,20 +9632,20 @@ function organization(config) {
9682
9632
  async handler(request, endpointCtx) {
9683
9633
  const user = await endpointCtx.getUser(request);
9684
9634
  if (!user) {
9685
- return jsonResponse13({ error: "Authentication required" }, 401);
9635
+ return jsonResponse8({ error: "Authentication required" }, 401);
9686
9636
  }
9687
9637
  const url = new URL(request.url);
9688
9638
  const segments = url.pathname.split("/").filter(Boolean);
9689
9639
  const orgId = segments[2];
9690
9640
  if (!orgId) {
9691
- return jsonResponse13({ error: "Missing organization ID in path" }, 400);
9641
+ return jsonResponse8({ error: "Missing organization ID in path" }, 400);
9692
9642
  }
9693
9643
  const callerMember = await module.getMember(orgId, user.id);
9694
9644
  if (!callerMember) {
9695
- return jsonResponse13({ error: "You are not a member of this organization" }, 403);
9645
+ return jsonResponse8({ error: "You are not a member of this organization" }, 403);
9696
9646
  }
9697
9647
  const members = await module.getMembers(orgId);
9698
- return jsonResponse13({ members });
9648
+ return jsonResponse8({ members });
9699
9649
  }
9700
9650
  });
9701
9651
  ctx.addEndpoint({
@@ -9708,29 +9658,29 @@ function organization(config) {
9708
9658
  async handler(request, endpointCtx) {
9709
9659
  const user = await endpointCtx.getUser(request);
9710
9660
  if (!user) {
9711
- return jsonResponse13({ error: "Authentication required" }, 401);
9661
+ return jsonResponse8({ error: "Authentication required" }, 401);
9712
9662
  }
9713
9663
  const url = new URL(request.url);
9714
9664
  const segments = url.pathname.split("/").filter(Boolean);
9715
9665
  const orgId = segments[2];
9716
9666
  const targetUserId = segments[4];
9717
9667
  if (!orgId || !targetUserId) {
9718
- return jsonResponse13({ error: "Missing organization ID or user ID in path" }, 400);
9668
+ return jsonResponse8({ error: "Missing organization ID or user ID in path" }, 400);
9719
9669
  }
9720
9670
  const callerMember = await module.getMember(orgId, user.id);
9721
9671
  if (!callerMember || !ADMIN_ROLES.has(callerMember.role)) {
9722
- return jsonResponse13({ error: "Admin or owner role required" }, 403);
9672
+ return jsonResponse8({ error: "Admin or owner role required" }, 403);
9723
9673
  }
9724
- const body = await parseBody7(request);
9674
+ const body = await parseBody3(request);
9725
9675
  const role = typeof body.role === "string" ? body.role : null;
9726
9676
  if (!role) {
9727
- return jsonResponse13({ error: "Missing required field: role" }, 400);
9677
+ return jsonResponse8({ error: "Missing required field: role" }, 400);
9728
9678
  }
9729
9679
  try {
9730
9680
  const member = await module.updateMemberRole(orgId, targetUserId, role);
9731
- return jsonResponse13(member);
9681
+ return jsonResponse8(member);
9732
9682
  } catch (err2) {
9733
- return jsonResponse13(
9683
+ return jsonResponse8(
9734
9684
  { error: err2 instanceof Error ? err2.message : "Failed to update member role" },
9735
9685
  400
9736
9686
  );
@@ -9747,24 +9697,24 @@ function organization(config) {
9747
9697
  async handler(request, endpointCtx) {
9748
9698
  const user = await endpointCtx.getUser(request);
9749
9699
  if (!user) {
9750
- return jsonResponse13({ error: "Authentication required" }, 401);
9700
+ return jsonResponse8({ error: "Authentication required" }, 401);
9751
9701
  }
9752
9702
  const url = new URL(request.url);
9753
9703
  const segments = url.pathname.split("/").filter(Boolean);
9754
9704
  const orgId = segments[2];
9755
9705
  const targetUserId = segments[4];
9756
9706
  if (!orgId || !targetUserId) {
9757
- return jsonResponse13({ error: "Missing organization ID or user ID in path" }, 400);
9707
+ return jsonResponse8({ error: "Missing organization ID or user ID in path" }, 400);
9758
9708
  }
9759
9709
  const callerMember = await module.getMember(orgId, user.id);
9760
9710
  if (!callerMember || !ADMIN_ROLES.has(callerMember.role)) {
9761
- return jsonResponse13({ error: "Admin or owner role required" }, 403);
9711
+ return jsonResponse8({ error: "Admin or owner role required" }, 403);
9762
9712
  }
9763
9713
  try {
9764
9714
  await module.removeMember(orgId, targetUserId);
9765
- return jsonResponse13({ removed: true });
9715
+ return jsonResponse8({ removed: true });
9766
9716
  } catch (err2) {
9767
- return jsonResponse13(
9717
+ return jsonResponse8(
9768
9718
  { error: err2 instanceof Error ? err2.message : "Failed to remove member" },
9769
9719
  400
9770
9720
  );
@@ -10169,13 +10119,13 @@ function parseAuthData(authData) {
10169
10119
  }
10170
10120
  return { rpIdHash, flags, signCount, attestedCredentialData };
10171
10121
  }
10172
- function jsonResponse14(body, status = 200) {
10122
+ function jsonResponse9(body, status = 200) {
10173
10123
  return new Response(JSON.stringify(body), {
10174
10124
  status,
10175
10125
  headers: { "Content-Type": "application/json" }
10176
10126
  });
10177
10127
  }
10178
- async function parseBody8(request) {
10128
+ async function parseBody4(request) {
10179
10129
  try {
10180
10130
  return await request.json();
10181
10131
  } catch {
@@ -10513,84 +10463,84 @@ function createPasskeyModule(config, db) {
10513
10463
  const method = request.method.toUpperCase();
10514
10464
  const segments = getPathSegments(url);
10515
10465
  if (method === "POST" && segments.length === 4 && segments[1] === "passkey" && segments[2] === "register" && segments[3] === "options") {
10516
- const body = await parseBody8(request);
10466
+ const body = await parseBody4(request);
10517
10467
  const userId = typeof body.userId === "string" ? body.userId : null;
10518
10468
  const userName = typeof body.userName === "string" ? body.userName : null;
10519
10469
  if (!userId || !userName) {
10520
- return jsonResponse14({ error: "userId and userName required" }, 400);
10470
+ return jsonResponse9({ error: "userId and userName required" }, 400);
10521
10471
  }
10522
10472
  try {
10523
10473
  const options = await getRegistrationOptions(userId, userName);
10524
- return jsonResponse14(options);
10474
+ return jsonResponse9(options);
10525
10475
  } catch (err2) {
10526
10476
  const message = err2 instanceof Error ? err2.message : "Failed to generate options";
10527
10477
  const code2 = err2 instanceof PasskeyError ? err2.code : "INTERNAL_ERROR";
10528
- return jsonResponse14({ error: message, code: code2 }, 500);
10478
+ return jsonResponse9({ error: message, code: code2 }, 500);
10529
10479
  }
10530
10480
  }
10531
10481
  if (method === "POST" && segments.length === 4 && segments[1] === "passkey" && segments[2] === "register" && segments[3] === "verify") {
10532
- const body = await parseBody8(request);
10482
+ const body = await parseBody4(request);
10533
10483
  const userId = typeof body.userId === "string" ? body.userId : null;
10534
- if (!userId) return jsonResponse14({ error: "userId required" }, 400);
10484
+ if (!userId) return jsonResponse9({ error: "userId required" }, 400);
10535
10485
  const resp = body.response;
10536
- if (!resp) return jsonResponse14({ error: "response required" }, 400);
10486
+ if (!resp) return jsonResponse9({ error: "response required" }, 400);
10537
10487
  try {
10538
10488
  const result = await verifyRegistration(userId, resp);
10539
- return jsonResponse14(result);
10489
+ return jsonResponse9(result);
10540
10490
  } catch (err2) {
10541
10491
  const message = err2 instanceof Error ? err2.message : "Registration failed";
10542
10492
  const code2 = err2 instanceof PasskeyError ? err2.code : "INTERNAL_ERROR";
10543
- return jsonResponse14({ error: message, code: code2 }, 400);
10493
+ return jsonResponse9({ error: message, code: code2 }, 400);
10544
10494
  }
10545
10495
  }
10546
10496
  if (method === "POST" && segments.length === 4 && segments[1] === "passkey" && segments[2] === "login" && segments[3] === "options") {
10547
- const body = await parseBody8(request);
10497
+ const body = await parseBody4(request);
10548
10498
  const userId = typeof body.userId === "string" ? body.userId : void 0;
10549
10499
  try {
10550
10500
  const options = await getAuthenticationOptions(userId);
10551
- return jsonResponse14(options);
10501
+ return jsonResponse9(options);
10552
10502
  } catch (err2) {
10553
10503
  const message = err2 instanceof Error ? err2.message : "Failed to generate options";
10554
10504
  const code2 = err2 instanceof PasskeyError ? err2.code : "INTERNAL_ERROR";
10555
- return jsonResponse14({ error: message, code: code2 }, 500);
10505
+ return jsonResponse9({ error: message, code: code2 }, 500);
10556
10506
  }
10557
10507
  }
10558
10508
  if (method === "POST" && segments.length === 4 && segments[1] === "passkey" && segments[2] === "login" && segments[3] === "verify") {
10559
- const body = await parseBody8(request);
10509
+ const body = await parseBody4(request);
10560
10510
  const resp = body.response;
10561
- if (!resp) return jsonResponse14({ error: "response required" }, 400);
10511
+ if (!resp) return jsonResponse9({ error: "response required" }, 400);
10562
10512
  try {
10563
10513
  const result = await verifyAuthentication(resp);
10564
- return jsonResponse14(result);
10514
+ return jsonResponse9(result);
10565
10515
  } catch (err2) {
10566
10516
  const message = err2 instanceof Error ? err2.message : "Authentication failed";
10567
10517
  const code2 = err2 instanceof PasskeyError ? err2.code : "INTERNAL_ERROR";
10568
- return jsonResponse14({ error: message, code: code2 }, 401);
10518
+ return jsonResponse9({ error: message, code: code2 }, 401);
10569
10519
  }
10570
10520
  }
10571
10521
  if (method === "GET" && segments.length === 3 && segments[1] === "passkey" && segments[2] === "credentials") {
10572
10522
  const userId = url.searchParams.get("userId");
10573
- if (!userId) return jsonResponse14({ error: "userId query param required" }, 400);
10523
+ if (!userId) return jsonResponse9({ error: "userId query param required" }, 400);
10574
10524
  try {
10575
10525
  const creds = await listCredentials(userId);
10576
- return jsonResponse14({ credentials: creds });
10526
+ return jsonResponse9({ credentials: creds });
10577
10527
  } catch (err2) {
10578
10528
  const message = err2 instanceof Error ? err2.message : "Failed to list credentials";
10579
- return jsonResponse14({ error: message }, 500);
10529
+ return jsonResponse9({ error: message }, 500);
10580
10530
  }
10581
10531
  }
10582
10532
  if (method === "DELETE" && segments.length === 4 && segments[1] === "passkey" && segments[2] === "credentials") {
10583
10533
  const credentialId = segments[3];
10584
- if (!credentialId) return jsonResponse14({ error: "Credential ID required" }, 400);
10585
- const body = await parseBody8(request);
10534
+ if (!credentialId) return jsonResponse9({ error: "Credential ID required" }, 400);
10535
+ const body = await parseBody4(request);
10586
10536
  const userId = typeof body.userId === "string" ? body.userId : null;
10587
- if (!userId) return jsonResponse14({ error: "userId required" }, 400);
10537
+ if (!userId) return jsonResponse9({ error: "userId required" }, 400);
10588
10538
  try {
10589
10539
  await removeCredential(credentialId, userId);
10590
- return jsonResponse14({ removed: true });
10540
+ return jsonResponse9({ removed: true });
10591
10541
  } catch (err2) {
10592
10542
  const message = err2 instanceof Error ? err2.message : "Failed to remove credential";
10593
- return jsonResponse14({ error: message }, 500);
10543
+ return jsonResponse9({ error: message }, 500);
10594
10544
  }
10595
10545
  }
10596
10546
  return null;
@@ -10607,13 +10557,13 @@ function createPasskeyModule(config, db) {
10607
10557
  }
10608
10558
 
10609
10559
  // src/auth/passkey-plugin.ts
10610
- function jsonResponse15(body, status = 200) {
10560
+ function jsonResponse10(body, status = 200) {
10611
10561
  return new Response(JSON.stringify(body), {
10612
10562
  status,
10613
10563
  headers: { "Content-Type": "application/json" }
10614
10564
  });
10615
10565
  }
10616
- async function parseBody9(request) {
10566
+ async function parseBody5(request) {
10617
10567
  try {
10618
10568
  return await request.json();
10619
10569
  } catch {
@@ -10635,16 +10585,16 @@ function passkey(config) {
10635
10585
  async handler(request, endpointCtx) {
10636
10586
  const user = await endpointCtx.getUser(request);
10637
10587
  if (!user) {
10638
- return jsonResponse15({ error: "Authentication required" }, 401);
10588
+ return jsonResponse10({ error: "Authentication required" }, 401);
10639
10589
  }
10640
- const body = await parseBody9(request);
10590
+ const body = await parseBody5(request);
10641
10591
  const userId = typeof body.userId === "string" ? body.userId : user.id;
10642
10592
  const userName = typeof body.userName === "string" ? body.userName : user.email ?? user.id;
10643
10593
  try {
10644
10594
  const options = await module.getRegistrationOptions(userId, userName);
10645
- return jsonResponse15(options);
10595
+ return jsonResponse10(options);
10646
10596
  } catch (err2) {
10647
- return jsonResponse15(
10597
+ return jsonResponse10(
10648
10598
  { error: err2 instanceof Error ? err2.message : "Failed to generate options" },
10649
10599
  500
10650
10600
  );
@@ -10661,19 +10611,19 @@ function passkey(config) {
10661
10611
  async handler(request, endpointCtx) {
10662
10612
  const user = await endpointCtx.getUser(request);
10663
10613
  if (!user) {
10664
- return jsonResponse15({ error: "Authentication required" }, 401);
10614
+ return jsonResponse10({ error: "Authentication required" }, 401);
10665
10615
  }
10666
- const body = await parseBody9(request);
10616
+ const body = await parseBody5(request);
10667
10617
  const userId = typeof body.userId === "string" ? body.userId : user.id;
10668
10618
  const response = body.response;
10669
10619
  if (!response) {
10670
- return jsonResponse15({ error: "Missing required field: response" }, 400);
10620
+ return jsonResponse10({ error: "Missing required field: response" }, 400);
10671
10621
  }
10672
10622
  try {
10673
10623
  const result = await module.verifyRegistration(userId, response);
10674
- return jsonResponse15(result);
10624
+ return jsonResponse10(result);
10675
10625
  } catch (err2) {
10676
- return jsonResponse15(
10626
+ return jsonResponse10(
10677
10627
  { error: err2 instanceof Error ? err2.message : "Registration failed" },
10678
10628
  400
10679
10629
  );
@@ -10687,13 +10637,13 @@ function passkey(config) {
10687
10637
  description: "Get WebAuthn authentication options"
10688
10638
  },
10689
10639
  async handler(request) {
10690
- const body = await parseBody9(request);
10640
+ const body = await parseBody5(request);
10691
10641
  const userId = typeof body.userId === "string" ? body.userId : void 0;
10692
10642
  try {
10693
10643
  const options = await module.getAuthenticationOptions(userId);
10694
- return jsonResponse15(options);
10644
+ return jsonResponse10(options);
10695
10645
  } catch (err2) {
10696
- return jsonResponse15(
10646
+ return jsonResponse10(
10697
10647
  { error: err2 instanceof Error ? err2.message : "Failed to generate options" },
10698
10648
  500
10699
10649
  );
@@ -10707,19 +10657,37 @@ function passkey(config) {
10707
10657
  description: "Verify a WebAuthn assertion and return the authenticated user"
10708
10658
  },
10709
10659
  async handler(request) {
10710
- const body = await parseBody9(request);
10660
+ const body = await parseBody5(request);
10711
10661
  const response = body.response;
10712
10662
  if (!response) {
10713
- return jsonResponse15({ error: "Missing required field: response" }, 400);
10663
+ return jsonResponse10({ error: "Missing required field: response" }, 400);
10714
10664
  }
10715
10665
  try {
10716
10666
  const result = await module.verifyAuthentication(response);
10717
10667
  if (!result) {
10718
- return jsonResponse15({ error: "Authentication failed" }, 401);
10668
+ return jsonResponse10({ error: "Authentication failed" }, 401);
10719
10669
  }
10720
- return jsonResponse15(result);
10670
+ if (ctx.sessionManager) {
10671
+ const { session, token } = await ctx.sessionManager.create(result.userId);
10672
+ const maxAge = Math.floor((session.expiresAt.getTime() - Date.now()) / 1e3);
10673
+ return new Response(
10674
+ JSON.stringify({
10675
+ user: { id: result.userId },
10676
+ session: { token, expiresAt: session.expiresAt },
10677
+ credential: result.credential
10678
+ }),
10679
+ {
10680
+ status: 200,
10681
+ headers: {
10682
+ "Content-Type": "application/json",
10683
+ "Set-Cookie": buildSetCookie("kavach_session", token, maxAge)
10684
+ }
10685
+ }
10686
+ );
10687
+ }
10688
+ return jsonResponse10(result);
10721
10689
  } catch (err2) {
10722
- return jsonResponse15(
10690
+ return jsonResponse10(
10723
10691
  { error: err2 instanceof Error ? err2.message : "Authentication failed" },
10724
10692
  401
10725
10693
  );
@@ -10736,13 +10704,13 @@ function passkey(config) {
10736
10704
  async handler(request, endpointCtx) {
10737
10705
  const user = await endpointCtx.getUser(request);
10738
10706
  if (!user) {
10739
- return jsonResponse15({ error: "Authentication required" }, 401);
10707
+ return jsonResponse10({ error: "Authentication required" }, 401);
10740
10708
  }
10741
10709
  try {
10742
10710
  const credentials = await module.listCredentials(user.id);
10743
- return jsonResponse15({ credentials });
10711
+ return jsonResponse10({ credentials });
10744
10712
  } catch (err2) {
10745
- return jsonResponse15(
10713
+ return jsonResponse10(
10746
10714
  { error: err2 instanceof Error ? err2.message : "Failed to list credentials" },
10747
10715
  500
10748
10716
  );
@@ -10759,19 +10727,19 @@ function passkey(config) {
10759
10727
  async handler(request, endpointCtx) {
10760
10728
  const user = await endpointCtx.getUser(request);
10761
10729
  if (!user) {
10762
- return jsonResponse15({ error: "Authentication required" }, 401);
10730
+ return jsonResponse10({ error: "Authentication required" }, 401);
10763
10731
  }
10764
10732
  const url = new URL(request.url);
10765
10733
  const segments = url.pathname.split("/").filter(Boolean);
10766
10734
  const credentialId = segments[3];
10767
10735
  if (!credentialId) {
10768
- return jsonResponse15({ error: "Missing credential ID in path" }, 400);
10736
+ return jsonResponse10({ error: "Missing credential ID in path" }, 400);
10769
10737
  }
10770
10738
  try {
10771
10739
  await module.removeCredential(credentialId, user.id);
10772
- return jsonResponse15({ removed: true });
10740
+ return jsonResponse10({ removed: true });
10773
10741
  } catch (err2) {
10774
- return jsonResponse15(
10742
+ return jsonResponse10(
10775
10743
  { error: err2 instanceof Error ? err2.message : "Failed to remove credential" },
10776
10744
  500
10777
10745
  );
@@ -10788,7 +10756,7 @@ var TOKEN_PURPOSE2 = "password-reset";
10788
10756
  function makeError7(code2, message, details) {
10789
10757
  return { code: code2, message, ...details !== void 0 ? { details } : {} };
10790
10758
  }
10791
- function jsonResponse16(body, status = 200) {
10759
+ function jsonResponse11(body, status = 200) {
10792
10760
  return new Response(JSON.stringify(body), {
10793
10761
  status,
10794
10762
  headers: { "Content-Type": "application/json" }
@@ -10904,27 +10872,27 @@ function createPasswordResetModule(config, db, sessionManager, tokenModule) {
10904
10872
  try {
10905
10873
  body = await request.json();
10906
10874
  } catch {
10907
- return jsonResponse16({ error: "Invalid JSON body" }, 400);
10875
+ return jsonResponse11({ error: "Invalid JSON body" }, 400);
10908
10876
  }
10909
10877
  const b = body;
10910
10878
  if (pathname === "/auth/forgot-password") {
10911
10879
  if (typeof b.email !== "string") {
10912
- return jsonResponse16({ error: "Missing required field: email" }, 400);
10880
+ return jsonResponse11({ error: "Missing required field: email" }, 400);
10913
10881
  }
10914
10882
  const result = await requestReset(b.email);
10915
10883
  if (!result.success) {
10916
- return jsonResponse16({ error: result.error.message }, 500);
10884
+ return jsonResponse11({ error: result.error.message }, 500);
10917
10885
  }
10918
10886
  return new Response(null, { status: 204 });
10919
10887
  }
10920
10888
  if (pathname === "/auth/reset-password") {
10921
10889
  if (typeof b.token !== "string" || typeof b.password !== "string") {
10922
- return jsonResponse16({ error: "Missing required fields: token, password" }, 400);
10890
+ return jsonResponse11({ error: "Missing required fields: token, password" }, 400);
10923
10891
  }
10924
10892
  const result = await resetPassword(b.token, b.password);
10925
10893
  if (!result.success) {
10926
10894
  const status = result.error.code === "INVALID_PASSWORD" ? 400 : 400;
10927
- return jsonResponse16({ error: result.error.message }, status);
10895
+ return jsonResponse11({ error: result.error.message }, status);
10928
10896
  }
10929
10897
  return new Response(null, { status: 204 });
10930
10898
  }
@@ -10959,7 +10927,7 @@ function generateNumericCode2(length) {
10959
10927
  function normalisePhone(phone) {
10960
10928
  return phone.replace(/\s+/g, "");
10961
10929
  }
10962
- function jsonResponse17(body, status = 200) {
10930
+ function jsonResponse12(body, status = 200) {
10963
10931
  return new Response(JSON.stringify(body), {
10964
10932
  status,
10965
10933
  headers: { "Content-Type": "application/json" }
@@ -11031,25 +10999,25 @@ function createPhoneAuthModule(config, db, sessionManager) {
11031
10999
  try {
11032
11000
  body = await request.json();
11033
11001
  } catch {
11034
- return jsonResponse17({ error: "Invalid JSON body" }, 400);
11002
+ return jsonResponse12({ error: "Invalid JSON body" }, 400);
11035
11003
  }
11036
11004
  const b = body;
11037
11005
  if (pathname === "/auth/phone/send-code") {
11038
11006
  if (typeof b.phoneNumber !== "string") {
11039
- return jsonResponse17({ error: "Missing required field: phoneNumber" }, 400);
11007
+ return jsonResponse12({ error: "Missing required field: phoneNumber" }, 400);
11040
11008
  }
11041
11009
  const result = await sendCode(b.phoneNumber);
11042
- return jsonResponse17(result);
11010
+ return jsonResponse12(result);
11043
11011
  }
11044
11012
  if (pathname === "/auth/phone/verify") {
11045
11013
  if (typeof b.phoneNumber !== "string" || typeof b.code !== "string") {
11046
- return jsonResponse17({ error: "Missing required fields: phoneNumber, code" }, 400);
11014
+ return jsonResponse12({ error: "Missing required fields: phoneNumber, code" }, 400);
11047
11015
  }
11048
11016
  const result = await verifyCode(b.phoneNumber, b.code);
11049
11017
  if (!result) {
11050
- return jsonResponse17({ error: "Invalid or expired code" }, 401);
11018
+ return jsonResponse12({ error: "Invalid or expired code" }, 401);
11051
11019
  }
11052
- return jsonResponse17(result);
11020
+ return jsonResponse12(result);
11053
11021
  }
11054
11022
  return null;
11055
11023
  }
@@ -11069,12 +11037,12 @@ async function polarRequest(accessToken, baseUrl, method, path, body) {
11069
11037
  headers,
11070
11038
  body: body !== void 0 ? JSON.stringify(body) : void 0
11071
11039
  });
11072
- const json3 = await response.json();
11040
+ const json2 = await response.json();
11073
11041
  if (!response.ok) {
11074
- const message = json3.detail ?? json3.message ?? `Polar API error: ${response.status}`;
11042
+ const message = json2.detail ?? json2.message ?? `Polar API error: ${response.status}`;
11075
11043
  throw new Error(message);
11076
11044
  }
11077
- return json3;
11045
+ return json2;
11078
11046
  }
11079
11047
  async function verifyWebhookSignature(payload, signatureHeader, webhookSecret) {
11080
11048
  const prefix = "sha256=";
@@ -11297,19 +11265,6 @@ function createPolarModule(config, db) {
11297
11265
  }
11298
11266
 
11299
11267
  // src/auth/polar-plugin.ts
11300
- function json(body, status = 200) {
11301
- return new Response(JSON.stringify(body), {
11302
- status,
11303
- headers: { "Content-Type": "application/json" }
11304
- });
11305
- }
11306
- async function parseBody10(request) {
11307
- try {
11308
- return await request.json();
11309
- } catch {
11310
- return {};
11311
- }
11312
- }
11313
11268
  function polar(config) {
11314
11269
  return {
11315
11270
  id: "kavach-polar",
@@ -11327,13 +11282,14 @@ function polar(config) {
11327
11282
  if (!user) {
11328
11283
  return json({ error: "Authentication required" }, 401);
11329
11284
  }
11330
- const body = await parseBody10(request);
11331
- const productId = typeof body.productId === "string" ? body.productId.trim() : null;
11285
+ const bodyResult = await parseBody(request);
11286
+ if (!bodyResult.ok) return bodyResult.response;
11287
+ const productId = typeof bodyResult.data.productId === "string" ? bodyResult.data.productId.trim() : null;
11332
11288
  if (!productId) {
11333
11289
  return json({ error: "Missing required field: productId" }, 400);
11334
11290
  }
11335
- const successUrl = typeof body.successUrl === "string" ? body.successUrl : void 0;
11336
- const customerEmail = typeof body.customerEmail === "string" ? body.customerEmail : void 0;
11291
+ const successUrl = typeof bodyResult.data.successUrl === "string" ? bodyResult.data.successUrl : void 0;
11292
+ const customerEmail = typeof bodyResult.data.customerEmail === "string" ? bodyResult.data.customerEmail : void 0;
11337
11293
  try {
11338
11294
  const result = await module.createCheckout(user.id, productId, {
11339
11295
  successUrl,
@@ -12778,13 +12734,13 @@ function scim(config) {
12778
12734
  // src/auth/siwe.ts
12779
12735
  var DEFAULT_NONCE_TTL_SECONDS = 300;
12780
12736
  var SIWE_VERSION = "1";
12781
- function jsonResponse18(body, status = 200) {
12737
+ function jsonResponse13(body, status = 200) {
12782
12738
  return new Response(JSON.stringify(body), {
12783
12739
  status,
12784
12740
  headers: { "Content-Type": "application/json" }
12785
12741
  });
12786
12742
  }
12787
- async function parseBody11(request) {
12743
+ async function parseBody6(request) {
12788
12744
  try {
12789
12745
  return await request.json();
12790
12746
  } catch {
@@ -12919,20 +12875,20 @@ function createSiweModule(config) {
12919
12875
  const { method, pathname } = { method: request.method, pathname: url.pathname };
12920
12876
  if (method === "GET" && pathname.endsWith("/auth/siwe/nonce")) {
12921
12877
  const nonce = await generateNonce();
12922
- return jsonResponse18({ nonce });
12878
+ return jsonResponse13({ nonce });
12923
12879
  }
12924
12880
  if (method === "POST" && pathname.endsWith("/auth/siwe/verify")) {
12925
- const body = await parseBody11(request);
12881
+ const body = await parseBody6(request);
12926
12882
  const message = typeof body.message === "string" ? body.message : null;
12927
12883
  const signature = typeof body.signature === "string" ? body.signature : null;
12928
12884
  if (!message || !signature) {
12929
- return jsonResponse18({ error: "Missing required fields: message, signature" }, 400);
12885
+ return jsonResponse13({ error: "Missing required fields: message, signature" }, 400);
12930
12886
  }
12931
12887
  try {
12932
12888
  const result = await verify(message, signature);
12933
- return jsonResponse18({ address: result.address, chainId: result.chainId });
12889
+ return jsonResponse13({ address: result.address, chainId: result.chainId });
12934
12890
  } catch (err2) {
12935
- return jsonResponse18(
12891
+ return jsonResponse13(
12936
12892
  { error: err2 instanceof Error ? err2.message : "Verification failed" },
12937
12893
  400
12938
12894
  );
@@ -13969,7 +13925,7 @@ function createSsoModule(config, db) {
13969
13925
  const url = new URL(request.url);
13970
13926
  const { pathname } = url;
13971
13927
  const { method } = request;
13972
- const json3 = (data, status = 200) => new Response(JSON.stringify(data), {
13928
+ const json2 = (data, status = 200) => new Response(JSON.stringify(data), {
13973
13929
  status,
13974
13930
  headers: { "Content-Type": "application/json" }
13975
13931
  });
@@ -13978,14 +13934,14 @@ function createSsoModule(config, db) {
13978
13934
  try {
13979
13935
  body = await request.json();
13980
13936
  } catch {
13981
- return json3({ error: "Invalid JSON body" }, 400);
13937
+ return json2({ error: "Invalid JSON body" }, 400);
13982
13938
  }
13983
13939
  const b = body;
13984
13940
  if (typeof b.orgId !== "string" || typeof b.providerId !== "string" || typeof b.type !== "string" || typeof b.domain !== "string") {
13985
- return json3({ error: "Missing required fields: orgId, providerId, type, domain" }, 400);
13941
+ return json2({ error: "Missing required fields: orgId, providerId, type, domain" }, 400);
13986
13942
  }
13987
13943
  if (b.type !== "saml" && b.type !== "oidc") {
13988
- return json3({ error: "type must be 'saml' or 'oidc'" }, 400);
13944
+ return json2({ error: "type must be 'saml' or 'oidc'" }, 400);
13989
13945
  }
13990
13946
  const conn = await createConnection({
13991
13947
  orgId: b.orgId,
@@ -13993,19 +13949,19 @@ function createSsoModule(config, db) {
13993
13949
  type: b.type,
13994
13950
  domain: b.domain
13995
13951
  });
13996
- return json3(conn, 201);
13952
+ return json2(conn, 201);
13997
13953
  }
13998
13954
  const listMatch = /^\/auth\/sso\/connections\/([^/]+)$/.exec(pathname);
13999
13955
  if (method === "GET" && listMatch) {
14000
13956
  const orgId = decodeURIComponent(listMatch[1] ?? "");
14001
13957
  const conns = await listConnections(orgId);
14002
- return json3(conns);
13958
+ return json2(conns);
14003
13959
  }
14004
13960
  const deleteMatch = /^\/auth\/sso\/connections\/([^/]+)$/.exec(pathname);
14005
13961
  if (method === "DELETE" && deleteMatch) {
14006
13962
  const connId = decodeURIComponent(deleteMatch[1] ?? "");
14007
13963
  await removeConnection(connId);
14008
- return json3({ success: true });
13964
+ return json2({ success: true });
14009
13965
  }
14010
13966
  const samlInitMatch = /^\/auth\/sso\/saml\/([^/]+)$/.exec(pathname);
14011
13967
  if (method === "GET" && samlInitMatch) {
@@ -14015,7 +13971,7 @@ function createSsoModule(config, db) {
14015
13971
  const authUrl = await getSamlAuthUrl(connId, relayState);
14016
13972
  return new Response(null, { status: 302, headers: { Location: authUrl } });
14017
13973
  } catch (err2) {
14018
- return json3({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 400);
13974
+ return json2({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 400);
14019
13975
  }
14020
13976
  }
14021
13977
  const samlAcsMatch = /^\/auth\/sso\/saml\/([^/]+)\/acs$/.exec(pathname);
@@ -14028,14 +13984,14 @@ function createSsoModule(config, db) {
14028
13984
  if (typeof val !== "string") throw new Error("Missing SAMLResponse");
14029
13985
  samlResponse = val;
14030
13986
  } catch {
14031
- return json3({ error: "Missing or invalid SAMLResponse" }, 400);
13987
+ return json2({ error: "Missing or invalid SAMLResponse" }, 400);
14032
13988
  }
14033
13989
  try {
14034
13990
  const result = await handleSamlResponse(connId, samlResponse);
14035
- return json3(result);
13991
+ return json2(result);
14036
13992
  } catch (err2) {
14037
13993
  const status = err2 instanceof SsoError && err2.code === SSO_ERROR.RATE_LIMITED ? 429 : 401;
14038
- return json3(
13994
+ return json2(
14039
13995
  {
14040
13996
  error: err2 instanceof Error ? err2.message : "SAML error",
14041
13997
  code: err2 instanceof SsoError ? err2.code : "SAML_ERROR"
@@ -14053,20 +14009,20 @@ function createSsoModule(config, db) {
14053
14009
  const authUrl = await getOidcAuthUrl(connId, state, nonce);
14054
14010
  return new Response(null, { status: 302, headers: { Location: authUrl } });
14055
14011
  } catch (err2) {
14056
- return json3({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 400);
14012
+ return json2({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 400);
14057
14013
  }
14058
14014
  }
14059
14015
  const oidcCbMatch = /^\/auth\/sso\/oidc\/([^/]+)\/callback$/.exec(pathname);
14060
14016
  if (method === "GET" && oidcCbMatch) {
14061
14017
  const connId = decodeURIComponent(oidcCbMatch[1] ?? "");
14062
14018
  const code2 = url.searchParams.get("code");
14063
- if (!code2) return json3({ error: "Missing code parameter" }, 400);
14019
+ if (!code2) return json2({ error: "Missing code parameter" }, 400);
14064
14020
  try {
14065
14021
  const result = await handleOidcCallback(connId, code2);
14066
- return json3(result);
14022
+ return json2(result);
14067
14023
  } catch (err2) {
14068
14024
  const status = err2 instanceof SsoError && err2.code === SSO_ERROR.RATE_LIMITED ? 429 : 401;
14069
- return json3(
14025
+ return json2(
14070
14026
  {
14071
14027
  error: err2 instanceof Error ? err2.message : "OIDC error",
14072
14028
  code: err2 instanceof SsoError ? err2.code : "OIDC_ERROR"
@@ -14167,12 +14123,12 @@ async function stripeRequest(secretKey, apiVersion, method, path, body) {
14167
14123
  headers,
14168
14124
  body: bodyStr
14169
14125
  });
14170
- const json3 = await response.json();
14126
+ const json2 = await response.json();
14171
14127
  if (!response.ok) {
14172
- const message = json3.error?.message ?? `Stripe API error: ${response.status}`;
14128
+ const message = json2.error?.message ?? `Stripe API error: ${response.status}`;
14173
14129
  throw new Error(message);
14174
14130
  }
14175
- return json3;
14131
+ return json2;
14176
14132
  }
14177
14133
  async function verifyWebhookSignature2(payload, signatureHeader, webhookSecret) {
14178
14134
  const parts = {};
@@ -14482,19 +14438,6 @@ function createStripeModule(config, db) {
14482
14438
  }
14483
14439
 
14484
14440
  // src/auth/stripe-plugin.ts
14485
- function json2(body, status = 200) {
14486
- return new Response(JSON.stringify(body), {
14487
- status,
14488
- headers: { "Content-Type": "application/json" }
14489
- });
14490
- }
14491
- async function parseBody12(request) {
14492
- try {
14493
- return await request.json();
14494
- } catch {
14495
- return {};
14496
- }
14497
- }
14498
14441
  function stripe(config) {
14499
14442
  return {
14500
14443
  id: "kavach-stripe",
@@ -14510,17 +14453,18 @@ function stripe(config) {
14510
14453
  async handler(request, endpointCtx) {
14511
14454
  const user = await endpointCtx.getUser(request);
14512
14455
  if (!user) {
14513
- return json2({ error: "Authentication required" }, 401);
14456
+ return json({ error: "Authentication required" }, 401);
14514
14457
  }
14515
- const body = await parseBody12(request);
14516
- const priceId = typeof body.priceId === "string" ? body.priceId.trim() : null;
14458
+ const bodyResult = await parseBody(request);
14459
+ if (!bodyResult.ok) return bodyResult.response;
14460
+ const priceId = typeof bodyResult.data.priceId === "string" ? bodyResult.data.priceId.trim() : null;
14517
14461
  if (!priceId) {
14518
- return json2({ error: "Missing required field: priceId" }, 400);
14462
+ return json({ error: "Missing required field: priceId" }, 400);
14519
14463
  }
14520
- const successUrl = typeof body.successUrl === "string" ? body.successUrl : void 0;
14521
- const cancelUrl = typeof body.cancelUrl === "string" ? body.cancelUrl : void 0;
14522
- const trialDays = typeof body.trialDays === "number" ? body.trialDays : void 0;
14523
- const metadata = body.metadata != null && typeof body.metadata === "object" && !Array.isArray(body.metadata) ? body.metadata : void 0;
14464
+ const successUrl = typeof bodyResult.data.successUrl === "string" ? bodyResult.data.successUrl : void 0;
14465
+ const cancelUrl = typeof bodyResult.data.cancelUrl === "string" ? bodyResult.data.cancelUrl : void 0;
14466
+ const trialDays = typeof bodyResult.data.trialDays === "number" ? bodyResult.data.trialDays : void 0;
14467
+ const metadata = bodyResult.data.metadata != null && typeof bodyResult.data.metadata === "object" && !Array.isArray(bodyResult.data.metadata) ? bodyResult.data.metadata : void 0;
14524
14468
  try {
14525
14469
  const result = await module.createCheckoutSession(user.id, priceId, {
14526
14470
  successUrl,
@@ -14528,9 +14472,9 @@ function stripe(config) {
14528
14472
  trialDays,
14529
14473
  metadata
14530
14474
  });
14531
- return json2(result);
14475
+ return json(result);
14532
14476
  } catch (err2) {
14533
- return json2(
14477
+ return json(
14534
14478
  {
14535
14479
  error: err2 instanceof Error ? err2.message : "Failed to create checkout session"
14536
14480
  },
@@ -14549,18 +14493,19 @@ function stripe(config) {
14549
14493
  async handler(request, endpointCtx) {
14550
14494
  const user = await endpointCtx.getUser(request);
14551
14495
  if (!user) {
14552
- return json2({ error: "Authentication required" }, 401);
14496
+ return json({ error: "Authentication required" }, 401);
14553
14497
  }
14554
- const body = await parseBody12(request);
14555
- const returnUrl = typeof body.returnUrl === "string" ? body.returnUrl.trim() : null;
14498
+ const bodyResult = await parseBody(request);
14499
+ if (!bodyResult.ok) return bodyResult.response;
14500
+ const returnUrl = typeof bodyResult.data.returnUrl === "string" ? bodyResult.data.returnUrl.trim() : null;
14556
14501
  if (!returnUrl) {
14557
- return json2({ error: "Missing required field: returnUrl" }, 400);
14502
+ return json({ error: "Missing required field: returnUrl" }, 400);
14558
14503
  }
14559
14504
  try {
14560
14505
  const result = await module.createPortalSession(user.id, returnUrl);
14561
- return json2(result);
14506
+ return json(result);
14562
14507
  } catch (err2) {
14563
- return json2(
14508
+ return json(
14564
14509
  {
14565
14510
  error: err2 instanceof Error ? err2.message : "Failed to create portal session"
14566
14511
  },
@@ -14579,10 +14524,10 @@ function stripe(config) {
14579
14524
  async handler(request, endpointCtx) {
14580
14525
  const user = await endpointCtx.getUser(request);
14581
14526
  if (!user) {
14582
- return json2({ error: "Authentication required" }, 401);
14527
+ return json({ error: "Authentication required" }, 401);
14583
14528
  }
14584
14529
  const subscription = await module.getSubscription(user.id);
14585
- return json2({ subscription });
14530
+ return json({ subscription });
14586
14531
  }
14587
14532
  });
14588
14533
  ctx.addEndpoint({
@@ -14684,13 +14629,13 @@ async function generateBackupCodes(count) {
14684
14629
  }
14685
14630
  return { plain, hashed };
14686
14631
  }
14687
- function jsonResponse19(body, status = 200) {
14632
+ function jsonResponse14(body, status = 200) {
14688
14633
  return new Response(JSON.stringify(body), {
14689
14634
  status,
14690
14635
  headers: { "Content-Type": "application/json" }
14691
14636
  });
14692
14637
  }
14693
- async function parseBody13(request) {
14638
+ async function parseBody7(request) {
14694
14639
  try {
14695
14640
  return await request.json();
14696
14641
  } catch {
@@ -14788,50 +14733,50 @@ function createTotpModule(config, db) {
14788
14733
  const method = request.method.toUpperCase();
14789
14734
  if (method !== "POST") return null;
14790
14735
  if (path === "/auth/2fa/setup") {
14791
- const body = await parseBody13(request);
14736
+ const body = await parseBody7(request);
14792
14737
  const userId = typeof body.userId === "string" ? body.userId : null;
14793
- if (!userId) return jsonResponse19({ error: "userId required" }, 400);
14738
+ if (!userId) return jsonResponse14({ error: "userId required" }, 400);
14794
14739
  try {
14795
14740
  const result = await setup(userId);
14796
- return jsonResponse19(result);
14741
+ return jsonResponse14(result);
14797
14742
  } catch (err2) {
14798
- return jsonResponse19({ error: err2 instanceof Error ? err2.message : "Setup failed" }, 500);
14743
+ return jsonResponse14({ error: err2 instanceof Error ? err2.message : "Setup failed" }, 500);
14799
14744
  }
14800
14745
  }
14801
14746
  if (path === "/auth/2fa/enable") {
14802
- const body = await parseBody13(request);
14747
+ const body = await parseBody7(request);
14803
14748
  const userId = typeof body.userId === "string" ? body.userId : null;
14804
14749
  const code2 = typeof body.code === "string" ? body.code : null;
14805
- if (!userId || !code2) return jsonResponse19({ error: "userId and code required" }, 400);
14750
+ if (!userId || !code2) return jsonResponse14({ error: "userId and code required" }, 400);
14806
14751
  const result = await enable(userId, code2);
14807
- return jsonResponse19(result);
14752
+ return jsonResponse14(result);
14808
14753
  }
14809
14754
  if (path === "/auth/2fa/verify") {
14810
- const body = await parseBody13(request);
14755
+ const body = await parseBody7(request);
14811
14756
  const userId = typeof body.userId === "string" ? body.userId : null;
14812
14757
  const code2 = typeof body.code === "string" ? body.code : null;
14813
- if (!userId || !code2) return jsonResponse19({ error: "userId and code required" }, 400);
14758
+ if (!userId || !code2) return jsonResponse14({ error: "userId and code required" }, 400);
14814
14759
  const result = await verify(userId, code2);
14815
- return jsonResponse19(result);
14760
+ return jsonResponse14(result);
14816
14761
  }
14817
14762
  if (path === "/auth/2fa/disable") {
14818
- const body = await parseBody13(request);
14763
+ const body = await parseBody7(request);
14819
14764
  const userId = typeof body.userId === "string" ? body.userId : null;
14820
14765
  const code2 = typeof body.code === "string" ? body.code : null;
14821
- if (!userId || !code2) return jsonResponse19({ error: "userId and code required" }, 400);
14766
+ if (!userId || !code2) return jsonResponse14({ error: "userId and code required" }, 400);
14822
14767
  const result = await disable(userId, code2);
14823
- return jsonResponse19(result);
14768
+ return jsonResponse14(result);
14824
14769
  }
14825
14770
  if (path === "/auth/2fa/backup-codes") {
14826
- const body = await parseBody13(request);
14771
+ const body = await parseBody7(request);
14827
14772
  const userId = typeof body.userId === "string" ? body.userId : null;
14828
14773
  const code2 = typeof body.code === "string" ? body.code : null;
14829
- if (!userId || !code2) return jsonResponse19({ error: "userId and code required" }, 400);
14774
+ if (!userId || !code2) return jsonResponse14({ error: "userId and code required" }, 400);
14830
14775
  try {
14831
14776
  const result = await regenerateBackupCodes(userId, code2);
14832
- return jsonResponse19(result);
14777
+ return jsonResponse14(result);
14833
14778
  } catch (err2) {
14834
- return jsonResponse19(
14779
+ return jsonResponse14(
14835
14780
  { error: err2 instanceof Error ? err2.message : "Failed to regenerate codes" },
14836
14781
  400
14837
14782
  );
@@ -14851,13 +14796,13 @@ function createTotpModule(config, db) {
14851
14796
  }
14852
14797
 
14853
14798
  // src/auth/totp-plugin.ts
14854
- function jsonResponse20(body, status = 200) {
14799
+ function jsonResponse15(body, status = 200) {
14855
14800
  return new Response(JSON.stringify(body), {
14856
14801
  status,
14857
14802
  headers: { "Content-Type": "application/json" }
14858
14803
  });
14859
14804
  }
14860
- async function parseBody14(request) {
14805
+ async function parseBody8(request) {
14861
14806
  try {
14862
14807
  return await request.json();
14863
14808
  } catch {
@@ -14879,13 +14824,13 @@ function twoFactor(config) {
14879
14824
  async handler(request, endpointCtx) {
14880
14825
  const user = await endpointCtx.getUser(request);
14881
14826
  if (!user) {
14882
- return jsonResponse20({ error: "Authentication required" }, 401);
14827
+ return jsonResponse15({ error: "Authentication required" }, 401);
14883
14828
  }
14884
14829
  try {
14885
14830
  const setup = await module.setup(user.id);
14886
- return jsonResponse20(setup);
14831
+ return jsonResponse15(setup);
14887
14832
  } catch (err2) {
14888
- return jsonResponse20(
14833
+ return jsonResponse15(
14889
14834
  { error: err2 instanceof Error ? err2.message : "Enrollment failed" },
14890
14835
  500
14891
14836
  );
@@ -14902,23 +14847,23 @@ function twoFactor(config) {
14902
14847
  async handler(request, endpointCtx) {
14903
14848
  const user = await endpointCtx.getUser(request);
14904
14849
  if (!user) {
14905
- return jsonResponse20({ error: "Authentication required" }, 401);
14850
+ return jsonResponse15({ error: "Authentication required" }, 401);
14906
14851
  }
14907
- const body = await parseBody14(request);
14852
+ const body = await parseBody8(request);
14908
14853
  const code2 = typeof body.code === "string" ? body.code : null;
14909
14854
  if (!code2) {
14910
- return jsonResponse20({ error: "Missing required field: code" }, 400);
14855
+ return jsonResponse15({ error: "Missing required field: code" }, 400);
14911
14856
  }
14912
14857
  const enabled = await module.isEnabled(user.id);
14913
14858
  if (!enabled) {
14914
14859
  const result2 = await module.enable(user.id, code2);
14915
14860
  if (!result2.enabled) {
14916
- return jsonResponse20({ error: "Invalid TOTP code" }, 400);
14861
+ return jsonResponse15({ error: "Invalid TOTP code" }, 400);
14917
14862
  }
14918
- return jsonResponse20({ valid: true, activated: true });
14863
+ return jsonResponse15({ valid: true, activated: true });
14919
14864
  }
14920
14865
  const result = await module.verify(user.id, code2);
14921
- return jsonResponse20(result);
14866
+ return jsonResponse15(result);
14922
14867
  }
14923
14868
  });
14924
14869
  ctx.addEndpoint({
@@ -14931,18 +14876,18 @@ function twoFactor(config) {
14931
14876
  async handler(request, endpointCtx) {
14932
14877
  const user = await endpointCtx.getUser(request);
14933
14878
  if (!user) {
14934
- return jsonResponse20({ error: "Authentication required" }, 401);
14879
+ return jsonResponse15({ error: "Authentication required" }, 401);
14935
14880
  }
14936
- const body = await parseBody14(request);
14881
+ const body = await parseBody8(request);
14937
14882
  const code2 = typeof body.code === "string" ? body.code : null;
14938
14883
  if (!code2) {
14939
- return jsonResponse20({ error: "Missing required field: code" }, 400);
14884
+ return jsonResponse15({ error: "Missing required field: code" }, 400);
14940
14885
  }
14941
14886
  const result = await module.disable(user.id, code2);
14942
14887
  if (!result.disabled) {
14943
- return jsonResponse20({ error: "Invalid TOTP code" }, 400);
14888
+ return jsonResponse15({ error: "Invalid TOTP code" }, 400);
14944
14889
  }
14945
- return jsonResponse20(result);
14890
+ return jsonResponse15(result);
14946
14891
  }
14947
14892
  });
14948
14893
  ctx.addEndpoint({
@@ -14955,10 +14900,10 @@ function twoFactor(config) {
14955
14900
  async handler(request, endpointCtx) {
14956
14901
  const user = await endpointCtx.getUser(request);
14957
14902
  if (!user) {
14958
- return jsonResponse20({ error: "Authentication required" }, 401);
14903
+ return jsonResponse15({ error: "Authentication required" }, 401);
14959
14904
  }
14960
14905
  const enabled = await module.isEnabled(user.id);
14961
- return jsonResponse20({ enabled });
14906
+ return jsonResponse15({ enabled });
14962
14907
  }
14963
14908
  });
14964
14909
  ctx.addEndpoint({
@@ -14971,18 +14916,18 @@ function twoFactor(config) {
14971
14916
  async handler(request, endpointCtx) {
14972
14917
  const user = await endpointCtx.getUser(request);
14973
14918
  if (!user) {
14974
- return jsonResponse20({ error: "Authentication required" }, 401);
14919
+ return jsonResponse15({ error: "Authentication required" }, 401);
14975
14920
  }
14976
- const body = await parseBody14(request);
14921
+ const body = await parseBody8(request);
14977
14922
  const code2 = typeof body.code === "string" ? body.code : null;
14978
14923
  if (!code2) {
14979
- return jsonResponse20({ error: "Missing required field: code" }, 400);
14924
+ return jsonResponse15({ error: "Missing required field: code" }, 400);
14980
14925
  }
14981
14926
  try {
14982
14927
  const result = await module.regenerateBackupCodes(user.id, code2);
14983
- return jsonResponse20(result);
14928
+ return jsonResponse15(result);
14984
14929
  } catch (err2) {
14985
- return jsonResponse20(
14930
+ return jsonResponse15(
14986
14931
  { error: err2 instanceof Error ? err2.message : "Failed to regenerate backup codes" },
14987
14932
  400
14988
14933
  );
@@ -15101,7 +15046,7 @@ async function hashPassword(password) {
15101
15046
  async function verifyPassword(stored, candidate) {
15102
15047
  return pbkdf2Verify(candidate, stored);
15103
15048
  }
15104
- function jsonResponse21(body, status = 200) {
15049
+ function jsonResponse16(body, status = 200) {
15105
15050
  return new Response(JSON.stringify(body), {
15106
15051
  status,
15107
15052
  headers: { "Content-Type": "application/json" }
@@ -15225,12 +15170,12 @@ function createUsernameAuthModule(config, db, sessionManager) {
15225
15170
  try {
15226
15171
  body = await request.json();
15227
15172
  } catch {
15228
- return jsonResponse21({ error: "Invalid JSON body" }, 400);
15173
+ return jsonResponse16({ error: "Invalid JSON body" }, 400);
15229
15174
  }
15230
15175
  const b = body;
15231
15176
  if (pathname === "/auth/username/sign-up") {
15232
15177
  if (typeof b.username !== "string" || typeof b.password !== "string") {
15233
- return jsonResponse21({ error: "Missing required fields: username, password" }, 400);
15178
+ return jsonResponse16({ error: "Missing required fields: username, password" }, 400);
15234
15179
  }
15235
15180
  try {
15236
15181
  const result = await signUp({
@@ -15238,21 +15183,21 @@ function createUsernameAuthModule(config, db, sessionManager) {
15238
15183
  password: b.password,
15239
15184
  name: typeof b.name === "string" ? b.name : void 0
15240
15185
  });
15241
- return jsonResponse21(result, 201);
15186
+ return jsonResponse16(result, 201);
15242
15187
  } catch (err2) {
15243
- return jsonResponse21({ error: err2 instanceof Error ? err2.message : "Sign-up failed" }, 400);
15188
+ return jsonResponse16({ error: err2 instanceof Error ? err2.message : "Sign-up failed" }, 400);
15244
15189
  }
15245
15190
  }
15246
15191
  if (pathname === "/auth/username/sign-in") {
15247
15192
  if (typeof b.username !== "string" || typeof b.password !== "string") {
15248
- return jsonResponse21({ error: "Missing required fields: username, password" }, 400);
15193
+ return jsonResponse16({ error: "Missing required fields: username, password" }, 400);
15249
15194
  }
15250
15195
  try {
15251
15196
  const result = await signIn({ username: b.username, password: b.password });
15252
- return jsonResponse21(result);
15197
+ return jsonResponse16(result);
15253
15198
  } catch (err2) {
15254
15199
  if (err2 instanceof Error && err2.message === "Password reset required") {
15255
- return jsonResponse21(
15200
+ return jsonResponse16(
15256
15201
  {
15257
15202
  error: {
15258
15203
  code: "PASSWORD_RESET_REQUIRED",
@@ -15262,21 +15207,21 @@ function createUsernameAuthModule(config, db, sessionManager) {
15262
15207
  403
15263
15208
  );
15264
15209
  }
15265
- return jsonResponse21({ error: "Invalid username or password" }, 401);
15210
+ return jsonResponse16({ error: "Invalid username or password" }, 401);
15266
15211
  }
15267
15212
  }
15268
15213
  if (pathname === "/auth/username/change-password") {
15269
15214
  if (typeof b.userId !== "string" || typeof b.current !== "string" || typeof b.newPassword !== "string") {
15270
- return jsonResponse21(
15215
+ return jsonResponse16(
15271
15216
  { error: "Missing required fields: userId, current, newPassword" },
15272
15217
  400
15273
15218
  );
15274
15219
  }
15275
15220
  try {
15276
15221
  const result = await changePassword(b.userId, b.current, b.newPassword);
15277
- return jsonResponse21(result);
15222
+ return jsonResponse16(result);
15278
15223
  } catch (err2) {
15279
- return jsonResponse21(
15224
+ return jsonResponse16(
15280
15225
  { error: err2 instanceof Error ? err2.message : "Change password failed" },
15281
15226
  400
15282
15227
  );
@@ -15284,13 +15229,13 @@ function createUsernameAuthModule(config, db, sessionManager) {
15284
15229
  }
15285
15230
  if (pathname === "/auth/username/change-username") {
15286
15231
  if (typeof b.userId !== "string" || typeof b.newUsername !== "string") {
15287
- return jsonResponse21({ error: "Missing required fields: userId, newUsername" }, 400);
15232
+ return jsonResponse16({ error: "Missing required fields: userId, newUsername" }, 400);
15288
15233
  }
15289
15234
  try {
15290
15235
  const result = await changeUsername(b.userId, b.newUsername);
15291
- return jsonResponse21(result);
15236
+ return jsonResponse16(result);
15292
15237
  } catch (err2) {
15293
- return jsonResponse21(
15238
+ return jsonResponse16(
15294
15239
  { error: err2 instanceof Error ? err2.message : "Change username failed" },
15295
15240
  400
15296
15241
  );
@@ -15472,7 +15417,7 @@ function buildStatements(provider) {
15472
15417
  const isMysql = provider === "mysql";
15473
15418
  const ts = isPostgres ? "TIMESTAMPTZ" : isMysql ? "DATETIME(3)" : "INTEGER";
15474
15419
  const tsNull = ts;
15475
- const json3 = isPostgres ? "JSONB" : isMysql ? "JSON" : "TEXT";
15420
+ const json2 = isPostgres ? "JSONB" : isMysql ? "JSON" : "TEXT";
15476
15421
  const bool = isPostgres ? "BOOLEAN" : isMysql ? "TINYINT(1)" : "INTEGER";
15477
15422
  const ifne = "IF NOT EXISTS";
15478
15423
  return [
@@ -15486,7 +15431,7 @@ function buildStatements(provider) {
15486
15431
  name TEXT,
15487
15432
  external_id TEXT,
15488
15433
  external_provider TEXT,
15489
- metadata ${json3},
15434
+ metadata ${json2},
15490
15435
  banned ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
15491
15436
  ban_reason TEXT,
15492
15437
  ban_expires_at ${tsNull},
@@ -15514,7 +15459,7 @@ function buildStatements(provider) {
15514
15459
  id TEXT NOT NULL PRIMARY KEY,
15515
15460
  name TEXT NOT NULL,
15516
15461
  slug TEXT NOT NULL UNIQUE,
15517
- settings ${json3},
15462
+ settings ${json2},
15518
15463
  status TEXT NOT NULL DEFAULT 'active',
15519
15464
  created_at ${ts} NOT NULL,
15520
15465
  updated_at ${ts} NOT NULL
@@ -15533,7 +15478,7 @@ function buildStatements(provider) {
15533
15478
  token_prefix TEXT NOT NULL,
15534
15479
  expires_at ${tsNull},
15535
15480
  last_active_at ${tsNull},
15536
- metadata ${json3},
15481
+ metadata ${json2},
15537
15482
  created_at ${ts} NOT NULL,
15538
15483
  updated_at ${ts} NOT NULL
15539
15484
  )`,
@@ -15544,8 +15489,8 @@ function buildStatements(provider) {
15544
15489
  id TEXT NOT NULL PRIMARY KEY,
15545
15490
  agent_id TEXT NOT NULL REFERENCES kavach_agents(id) ON DELETE CASCADE,
15546
15491
  resource TEXT NOT NULL,
15547
- actions ${json3} NOT NULL,
15548
- constraints ${json3},
15492
+ actions ${json2} NOT NULL,
15493
+ constraints ${json2},
15549
15494
  created_at ${ts} NOT NULL
15550
15495
  )`,
15551
15496
  // ------------------------------------------------------------------
@@ -15555,7 +15500,7 @@ function buildStatements(provider) {
15555
15500
  id TEXT NOT NULL PRIMARY KEY,
15556
15501
  from_agent_id TEXT NOT NULL REFERENCES kavach_agents(id),
15557
15502
  to_agent_id TEXT NOT NULL REFERENCES kavach_agents(id),
15558
- permissions ${json3} NOT NULL,
15503
+ permissions ${json2} NOT NULL,
15559
15504
  depth INTEGER NOT NULL DEFAULT 1,
15560
15505
  max_depth INTEGER NOT NULL DEFAULT 3,
15561
15506
  status TEXT NOT NULL DEFAULT 'active',
@@ -15571,7 +15516,7 @@ function buildStatements(provider) {
15571
15516
  user_id TEXT NOT NULL REFERENCES kavach_users(id),
15572
15517
  action TEXT NOT NULL,
15573
15518
  resource TEXT NOT NULL,
15574
- parameters ${json3},
15519
+ parameters ${json2},
15575
15520
  result TEXT NOT NULL,
15576
15521
  reason TEXT,
15577
15522
  duration_ms INTEGER NOT NULL,
@@ -15597,7 +15542,7 @@ function buildStatements(provider) {
15597
15542
  id TEXT NOT NULL PRIMARY KEY,
15598
15543
  name TEXT NOT NULL,
15599
15544
  endpoint TEXT NOT NULL UNIQUE,
15600
- tools ${json3} NOT NULL,
15545
+ tools ${json2} NOT NULL,
15601
15546
  auth_required ${bool} NOT NULL DEFAULT ${isPostgres ? "TRUE" : "1"},
15602
15547
  rate_limit_rpm INTEGER,
15603
15548
  status TEXT NOT NULL DEFAULT 'active',
@@ -15611,7 +15556,7 @@ function buildStatements(provider) {
15611
15556
  id TEXT NOT NULL PRIMARY KEY,
15612
15557
  user_id TEXT NOT NULL REFERENCES kavach_users(id),
15613
15558
  expires_at ${ts} NOT NULL,
15614
- metadata ${json3},
15559
+ metadata ${json2},
15615
15560
  created_at ${ts} NOT NULL
15616
15561
  )`,
15617
15562
  // ------------------------------------------------------------------
@@ -15623,13 +15568,13 @@ function buildStatements(provider) {
15623
15568
  client_secret TEXT,
15624
15569
  client_name TEXT,
15625
15570
  client_uri TEXT,
15626
- redirect_uris ${json3} NOT NULL,
15627
- grant_types ${json3} NOT NULL,
15628
- response_types ${json3} NOT NULL,
15571
+ redirect_uris ${json2} NOT NULL,
15572
+ grant_types ${json2} NOT NULL,
15573
+ response_types ${json2} NOT NULL,
15629
15574
  token_endpoint_auth_method TEXT NOT NULL DEFAULT 'client_secret_basic',
15630
15575
  type TEXT NOT NULL DEFAULT 'confidential',
15631
15576
  disabled ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
15632
- metadata ${json3},
15577
+ metadata ${json2},
15633
15578
  created_at ${ts} NOT NULL,
15634
15579
  updated_at ${ts} NOT NULL
15635
15580
  )`,
@@ -15697,8 +15642,8 @@ function buildStatements(provider) {
15697
15642
  agent_id TEXT REFERENCES kavach_agents(id) ON DELETE CASCADE,
15698
15643
  user_id TEXT REFERENCES kavach_users(id),
15699
15644
  tenant_id TEXT REFERENCES kavach_tenants(id),
15700
- limits ${json3} NOT NULL,
15701
- current_usage ${json3} NOT NULL,
15645
+ limits ${json2} NOT NULL,
15646
+ current_usage ${json2} NOT NULL,
15702
15647
  action TEXT NOT NULL DEFAULT 'warn',
15703
15648
  status TEXT NOT NULL DEFAULT 'active',
15704
15649
  created_at ${ts} NOT NULL
@@ -15712,11 +15657,11 @@ function buildStatements(provider) {
15712
15657
  name TEXT NOT NULL,
15713
15658
  description TEXT,
15714
15659
  version TEXT NOT NULL,
15715
- protocols ${json3} NOT NULL,
15716
- capabilities ${json3} NOT NULL,
15717
- auth_requirements ${json3} NOT NULL,
15660
+ protocols ${json2} NOT NULL,
15661
+ capabilities ${json2} NOT NULL,
15662
+ auth_requirements ${json2} NOT NULL,
15718
15663
  endpoint TEXT,
15719
- metadata ${json3},
15664
+ metadata ${json2},
15720
15665
  created_at ${ts} NOT NULL,
15721
15666
  updated_at ${ts} NOT NULL
15722
15667
  )`,
@@ -15729,7 +15674,7 @@ function buildStatements(provider) {
15729
15674
  user_id TEXT NOT NULL REFERENCES kavach_users(id),
15730
15675
  action TEXT NOT NULL,
15731
15676
  resource TEXT NOT NULL,
15732
- arguments ${json3},
15677
+ arguments ${json2},
15733
15678
  status TEXT NOT NULL DEFAULT 'pending',
15734
15679
  expires_at ${ts} NOT NULL,
15735
15680
  responded_at ${tsNull},
@@ -15743,7 +15688,7 @@ function buildStatements(provider) {
15743
15688
  agent_id TEXT NOT NULL PRIMARY KEY REFERENCES kavach_agents(id) ON DELETE CASCADE,
15744
15689
  score INTEGER NOT NULL,
15745
15690
  level TEXT NOT NULL,
15746
- factors ${json3} NOT NULL,
15691
+ factors ${json2} NOT NULL,
15747
15692
  computed_at ${ts} NOT NULL
15748
15693
  )`,
15749
15694
  // ------------------------------------------------------------------
@@ -15754,7 +15699,7 @@ function buildStatements(provider) {
15754
15699
  name TEXT NOT NULL,
15755
15700
  slug TEXT NOT NULL UNIQUE,
15756
15701
  owner_id TEXT NOT NULL REFERENCES kavach_users(id),
15757
- metadata ${json3},
15702
+ metadata ${json2},
15758
15703
  created_at ${ts} NOT NULL,
15759
15704
  updated_at ${ts} NOT NULL
15760
15705
  )`,
@@ -15789,7 +15734,7 @@ function buildStatements(provider) {
15789
15734
  id TEXT NOT NULL PRIMARY KEY,
15790
15735
  org_id TEXT NOT NULL REFERENCES kavach_organizations(id) ON DELETE CASCADE,
15791
15736
  name TEXT NOT NULL,
15792
- permissions ${json3} NOT NULL,
15737
+ permissions ${json2} NOT NULL,
15793
15738
  UNIQUE(org_id, name)
15794
15739
  )`,
15795
15740
  // ------------------------------------------------------------------
@@ -15825,7 +15770,7 @@ function buildStatements(provider) {
15825
15770
  token_hash TEXT NOT NULL UNIQUE,
15826
15771
  purpose TEXT NOT NULL,
15827
15772
  identifier TEXT NOT NULL,
15828
- metadata ${json3},
15773
+ metadata ${json2},
15829
15774
  used ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
15830
15775
  expires_at ${ts} NOT NULL,
15831
15776
  created_at ${ts} NOT NULL
@@ -15870,7 +15815,7 @@ function buildStatements(provider) {
15870
15815
  user_id TEXT NOT NULL PRIMARY KEY REFERENCES kavach_users(id),
15871
15816
  secret TEXT NOT NULL,
15872
15817
  enabled ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
15873
- backup_codes ${json3} NOT NULL,
15818
+ backup_codes ${json2} NOT NULL,
15874
15819
  created_at ${ts} NOT NULL,
15875
15820
  updated_at ${ts} NOT NULL
15876
15821
  )`,
@@ -15895,7 +15840,7 @@ function buildStatements(provider) {
15895
15840
  name TEXT NOT NULL,
15896
15841
  key_hash TEXT NOT NULL,
15897
15842
  key_prefix TEXT NOT NULL,
15898
- permissions ${json3} NOT NULL,
15843
+ permissions ${json2} NOT NULL,
15899
15844
  expires_at ${tsNull},
15900
15845
  last_used_at ${tsNull},
15901
15846
  created_at ${ts} NOT NULL
@@ -15954,10 +15899,10 @@ function buildStatements(provider) {
15954
15899
  client_id TEXT NOT NULL UNIQUE,
15955
15900
  client_secret_hash TEXT NOT NULL,
15956
15901
  client_name TEXT NOT NULL,
15957
- redirect_uris ${json3} NOT NULL,
15958
- grant_types ${json3} NOT NULL,
15959
- response_types ${json3} NOT NULL,
15960
- scopes ${json3} NOT NULL,
15902
+ redirect_uris ${json2} NOT NULL,
15903
+ grant_types ${json2} NOT NULL,
15904
+ response_types ${json2} NOT NULL,
15905
+ scopes ${json2} NOT NULL,
15961
15906
  token_endpoint_auth_method TEXT NOT NULL DEFAULT 'client_secret_post',
15962
15907
  created_at ${ts} NOT NULL,
15963
15908
  updated_at ${ts} NOT NULL
@@ -16003,7 +15948,7 @@ function buildStatements(provider) {
16003
15948
  output_tokens INTEGER,
16004
15949
  cost_micros INTEGER NOT NULL,
16005
15950
  currency TEXT NOT NULL DEFAULT 'USD',
16006
- metadata ${json3},
15951
+ metadata ${json2},
16007
15952
  delegation_chain_id TEXT,
16008
15953
  recorded_at ${ts} NOT NULL
16009
15954
  )`,
@@ -16051,7 +15996,7 @@ function buildStatements(provider) {
16051
15996
  id TEXT NOT NULL PRIMARY KEY,
16052
15997
  type TEXT NOT NULL,
16053
15998
  timestamp ${ts} NOT NULL,
16054
- data ${json3} NOT NULL,
15999
+ data ${json2} NOT NULL,
16055
16000
  agent_id TEXT,
16056
16001
  user_id TEXT
16057
16002
  )`,
@@ -16112,7 +16057,7 @@ function buildStatements(provider) {
16112
16057
  source_instance_id TEXT NOT NULL,
16113
16058
  target_instance_id TEXT,
16114
16059
  direction TEXT NOT NULL,
16115
- permissions ${json3} NOT NULL,
16060
+ permissions ${json2} NOT NULL,
16116
16061
  trust_score INTEGER,
16117
16062
  expires_at ${ts} NOT NULL,
16118
16063
  created_at ${ts} NOT NULL
@@ -17430,6 +17375,18 @@ function matchPath(pattern, pathname) {
17430
17375
  return params;
17431
17376
  }
17432
17377
  function createPluginRouter(endpoints) {
17378
+ const rateLimitStore = /* @__PURE__ */ new Map();
17379
+ function checkRateLimit2(key, windowSeconds, max) {
17380
+ const now = Date.now();
17381
+ const entry = rateLimitStore.get(key);
17382
+ if (!entry || now > entry.resetAt) {
17383
+ rateLimitStore.set(key, { count: 1, resetAt: now + windowSeconds * 1e3 });
17384
+ return true;
17385
+ }
17386
+ if (entry.count >= max) return false;
17387
+ entry.count++;
17388
+ return true;
17389
+ }
17433
17390
  return {
17434
17391
  async handle(request, basePath, endpointCtx) {
17435
17392
  const url = new URL(request.url);
@@ -17449,6 +17406,20 @@ function createPluginRouter(endpoints) {
17449
17406
  if (endpoint.method !== method) continue;
17450
17407
  const params = matchPath(endpoint.path, pathname);
17451
17408
  if (params === null) continue;
17409
+ if (endpoint.metadata?.rateLimit) {
17410
+ const { window: windowSec, max } = endpoint.metadata.rateLimit;
17411
+ const ip = request.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ?? request.headers.get("x-real-ip") ?? "unknown";
17412
+ const key = `${ip}:${endpoint.path}`;
17413
+ if (!checkRateLimit2(key, windowSec, max)) {
17414
+ return json({ error: "Rate limit exceeded" }, 429);
17415
+ }
17416
+ }
17417
+ if (endpoint.metadata?.requireAuth) {
17418
+ const user = await endpointCtx.getUser(request);
17419
+ if (!user) {
17420
+ return json({ error: "Authentication required" }, 401);
17421
+ }
17422
+ }
17452
17423
  const enrichedUrl = new URL(request.url);
17453
17424
  for (const [key, value] of Object.entries(params)) {
17454
17425
  enrichedUrl.searchParams.set(`_param_${key}`, value);
@@ -17506,7 +17477,7 @@ async function runMigrations(db, provider, statements) {
17506
17477
  }
17507
17478
  throw new Error(`runMigrations: unsupported provider "${provider}"`);
17508
17479
  }
17509
- async function initializePlugins(plugins, db, config) {
17480
+ async function initializePlugins(plugins, db, config, sessionManager) {
17510
17481
  const registry = {
17511
17482
  endpoints: [],
17512
17483
  migrations: [],
@@ -17523,6 +17494,7 @@ async function initializePlugins(plugins, db, config) {
17523
17494
  const ctx = {
17524
17495
  db,
17525
17496
  config,
17497
+ sessionManager,
17526
17498
  addEndpoint(endpoint) {
17527
17499
  registry.endpoints.push(endpoint);
17528
17500
  },
@@ -17763,8 +17735,8 @@ var DEFAULT_EXCLUDE_PATHS = [
17763
17735
  var encoder = new TextEncoder();
17764
17736
  var decoder = new TextDecoder();
17765
17737
  function encodeState2(state) {
17766
- const json3 = JSON.stringify(state);
17767
- const bytes = encoder.encode(json3);
17738
+ const json2 = JSON.stringify(state);
17739
+ const bytes = encoder.encode(json2);
17768
17740
  let binary = "";
17769
17741
  for (let i = 0; i < bytes.length; i++) {
17770
17742
  binary += String.fromCharCode(bytes[i]);
@@ -17782,8 +17754,8 @@ function decodeState(encoded) {
17782
17754
  for (let i = 0; i < binary.length; i++) {
17783
17755
  bytes[i] = binary.charCodeAt(i);
17784
17756
  }
17785
- const json3 = decoder.decode(bytes);
17786
- const parsed = JSON.parse(json3);
17757
+ const json2 = decoder.decode(bytes);
17758
+ const parsed = JSON.parse(json2);
17787
17759
  if (!isValidChainState(parsed)) return null;
17788
17760
  return parsed;
17789
17761
  } catch {
@@ -17855,7 +17827,7 @@ function createRedirectChain(config) {
17855
17827
  if (cookieOpts.domain) parts.push(`Domain=${cookieOpts.domain}`);
17856
17828
  return parts.join("; ");
17857
17829
  }
17858
- function buildClearCookie() {
17830
+ function buildClearCookie2() {
17859
17831
  return buildCookieHeader("", 0);
17860
17832
  }
17861
17833
  function serializeAndSetCookie(state) {
@@ -17965,7 +17937,7 @@ function createRedirectChain(config) {
17965
17937
  pop(request) {
17966
17938
  const state = parseFromRequest(request);
17967
17939
  if (!state) {
17968
- return { url: defaultPath, done: true, clearCookie: buildClearCookie() };
17940
+ return { url: defaultPath, done: true, clearCookie: buildClearCookie2() };
17969
17941
  }
17970
17942
  if (state.steps.length > 0) {
17971
17943
  const next = state.steps.shift();
@@ -17989,7 +17961,7 @@ function createRedirectChain(config) {
17989
17961
  return {
17990
17962
  url,
17991
17963
  done: true,
17992
- clearCookie: buildClearCookie()
17964
+ clearCookie: buildClearCookie2()
17993
17965
  };
17994
17966
  },
17995
17967
  peek(request) {
@@ -18015,7 +17987,7 @@ function createRedirectChain(config) {
18015
17987
  },
18016
17988
  clear() {
18017
17989
  currentState = null;
18018
- return buildClearCookie();
17990
+ return buildClearCookie2();
18019
17991
  },
18020
17992
  parse(request) {
18021
17993
  return parseFromRequest(request);
@@ -18348,12 +18320,33 @@ async function createKavach(config) {
18348
18320
  const captchaModule = config.captcha ? createCaptchaModule(config.captcha) : null;
18349
18321
  const redirectChain = createRedirectChain(config.redirects);
18350
18322
  const webhookModule = config.webhooks && config.webhooks.length > 0 ? createWebhookModule(config.webhooks) : null;
18351
- const pluginRegistry = await initializePlugins(config.plugins ?? [], db, config);
18323
+ const pluginRegistry = await initializePlugins(config.plugins ?? [], db, config, sessionManager);
18352
18324
  const endpointCtx = {
18353
18325
  db,
18354
18326
  async getUser(request) {
18355
- if (!authAdapter) return null;
18356
- return authAdapter.resolveUser(request);
18327
+ if (authAdapter) {
18328
+ const user = await authAdapter.resolveUser(request);
18329
+ if (user) return user;
18330
+ }
18331
+ if (sessionManager) {
18332
+ const token = extractToken(request);
18333
+ if (!token) return null;
18334
+ try {
18335
+ const session = await sessionManager.validate(token);
18336
+ if (!session) return null;
18337
+ const userRows = await db.select().from(users).where(eq(users.id, session.userId));
18338
+ const user = userRows[0];
18339
+ if (!user) return null;
18340
+ return {
18341
+ id: user.id,
18342
+ email: user.email ?? void 0,
18343
+ name: user.name ?? void 0
18344
+ };
18345
+ } catch {
18346
+ return null;
18347
+ }
18348
+ }
18349
+ return null;
18357
18350
  },
18358
18351
  async getSession(token) {
18359
18352
  if (!sessionManager) return null;
@@ -18361,6 +18354,46 @@ async function createKavach(config) {
18361
18354
  }
18362
18355
  };
18363
18356
  const pluginRouter = createPluginRouter(pluginRegistry.endpoints);
18357
+ if (sessionManager) {
18358
+ pluginRegistry.endpoints.push({
18359
+ method: "POST",
18360
+ path: "/auth/sign-out",
18361
+ metadata: { description: "Revoke the current session and clear cookie" },
18362
+ async handler(request) {
18363
+ const token = extractToken(request);
18364
+ if (!token) return json({ error: "No session" }, 401);
18365
+ try {
18366
+ const session = await sessionManager.validate(token);
18367
+ if (session) {
18368
+ await sessionManager.revoke(session.id);
18369
+ }
18370
+ } catch {
18371
+ }
18372
+ return new Response(JSON.stringify({ success: true }), {
18373
+ status: 200,
18374
+ headers: {
18375
+ "Content-Type": "application/json",
18376
+ "Set-Cookie": buildClearCookie("kavach_session")
18377
+ }
18378
+ });
18379
+ }
18380
+ });
18381
+ pluginRegistry.endpoints.push({
18382
+ method: "GET",
18383
+ path: "/auth/session",
18384
+ metadata: { description: "Get current session and user info" },
18385
+ async handler(request) {
18386
+ const user = await endpointCtx.getUser(request);
18387
+ if (!user) return json({ error: "Not authenticated" }, 401);
18388
+ const token = extractToken(request);
18389
+ const session = token ? await sessionManager.validate(token) : null;
18390
+ return json({
18391
+ user,
18392
+ session: session ? { id: session.id, expiresAt: session.expiresAt } : null
18393
+ });
18394
+ }
18395
+ });
18396
+ }
18364
18397
  async function authorize(agentId, request, context) {
18365
18398
  if (hooks.beforeAuthorize) {
18366
18399
  const verdict = await hooks.beforeAuthorize({
@@ -19432,7 +19465,7 @@ function parseCookies2(header) {
19432
19465
  }
19433
19466
  return result;
19434
19467
  }
19435
- function getCookie(header, name) {
19468
+ function getCookie2(header, name) {
19436
19469
  return parseCookies2(header)[name];
19437
19470
  }
19438
19471
  function parseCookiesFromRequest(request) {
@@ -19553,7 +19586,7 @@ function createCookieSessionManager(config, db) {
19553
19586
  ...config.cookieOptions,
19554
19587
  maxAge: maxAgeSecs
19555
19588
  };
19556
- function buildSetCookie(token) {
19589
+ function buildSetCookie2(token) {
19557
19590
  return serializeCookie(sessionName, token, baseCookieOpts);
19558
19591
  }
19559
19592
  function buildDeleteCookie() {
@@ -19562,10 +19595,10 @@ function createCookieSessionManager(config, db) {
19562
19595
  }
19563
19596
  async function createSession(userId, metadata) {
19564
19597
  const { session, token } = await raw.create(userId, metadata);
19565
- return { session, setCookieHeader: buildSetCookie(token) };
19598
+ return { session, setCookieHeader: buildSetCookie2(token) };
19566
19599
  }
19567
19600
  async function validateSession(cookieHeader) {
19568
- const token = getCookie(cookieHeader, sessionName);
19601
+ const token = getCookie2(cookieHeader, sessionName);
19569
19602
  if (!token) {
19570
19603
  return { session: null, refreshCookieHeader: null };
19571
19604
  }
@@ -19591,7 +19624,7 @@ function createCookieSessionManager(config, db) {
19591
19624
  row.userId,
19592
19625
  row.metadata ?? void 0
19593
19626
  );
19594
- return { session: newSession, setCookieHeader: buildSetCookie(newToken) };
19627
+ return { session: newSession, setCookieHeader: buildSetCookie2(newToken) };
19595
19628
  }
19596
19629
  async function revokeSession(sessionId) {
19597
19630
  await raw.revoke(sessionId);
@@ -19935,7 +19968,7 @@ function createSessionRefresher(config) {
19935
19968
  }
19936
19969
  async function handleRequest(request) {
19937
19970
  const cookieHeader = request.headers.get("cookie") ?? "";
19938
- let rawToken = getCookie(cookieHeader, refreshCookieName);
19971
+ let rawToken = getCookie2(cookieHeader, refreshCookieName);
19939
19972
  if (!rawToken) {
19940
19973
  try {
19941
19974
  const body = await request.clone().json();
@@ -20666,6 +20699,6 @@ async function verifyWebhookSignature3(secret, rawBody, signature) {
20666
20699
  return diff === 0;
20667
20700
  }
20668
20701
 
20669
- export { CredentialStatusSchema, CredentialSubjectSchema, EVENT_TYPES, HibpApiError, HibpBreachedError, KAVACH_AGENT_CREDENTIAL, KAVACH_DELEGATION_CREDENTIAL, KAVACH_PERMISSION_CREDENTIAL, KVStore, MemoryStore, MultiSessionLimitError, OAuthProxyError, OneTapVerifyError, ProofSchema, RefreshTokenError, SSO_ERROR, SsoError, VC_CONTEXT_V1, VC_CONTEXT_V2, VC_TYPE_CREDENTIAL, VC_TYPE_PRESENTATION, VerifiableCredentialSchema, VerifiablePresentationSchema, additionalFields, admin, agentCards, agentDids, agents, anonymousAuth, apiKeys2 as apiKeys, apiKeys as apiKeysTable, approvalRequests, auditLogs, bearerAuth, budgetPolicies, buildDidDocument, buildSessionMetadata, classifyViolation, constantTimeEqual, createAdditionalFieldsModule, createAdminModule, createAgentModule, createAnonymousAuthModule, createApiKeyManagerModule, createAppleProvider, createApprovalModule, createAuditModule, createCaptchaModule, createCookieSessionManager, createCostAttributionModule, createCustomSessionModule, createDatabase, createDatabaseSync, createDelegationModule, createDeviceAuthModule, createDidModule, createDiscordProvider, createEmailOtpModule, createEmailTemplates, createEmailVerificationModule, createEphemeralSessionModule, createEventStreamModule, createFederationModule, createGdprModule, createGithubProvider, createGitlabProvider, createGoogleProvider, createHibpModule, createI18n, createJwtSessionModule, createKavach, createLastLoginModule, createLinkedInProvider, createMagicLinkModule, createMicrosoftProvider, createMultiSessionModule, createOAuthModule, createOAuthProxyModule, createOidcProviderModule, createOneTapModule, createOneTimeTokenModule, createOpenApiModule, createOrgModule, createPasskeyModule, createPasswordResetModule, createPermissionEngine, createPhoneAuthModule, createPluginRouter, createPolarModule, createPolicyModule, createPresentation, createPrivilegeAnalyzer, createRateLimiter, createReBACModule, createRedirectChain, createScimModule, createSessionFreshnessModule, createSessionManager, createSessionRefresher, createSiweModule, createSlackProvider, createSsoModule, createStripeModule, createTables, createTenantModule, createTokenFamilyStore, createTotpModule, createTrustModule, createTrustedDeviceModule, createTwitterProvider, createUsernameAuthModule, createVCIssuer, createVCVerifier, createWebhookModule2 as createWebhookModule, customAuth, customSession, de, delegationChains, deviceAuth, deviceLabelFromRequest, emailOtp, emailOtps, en, es, fr, fromBase64Url, fromHex, gdpr, generateCsrfToken, generateDidKey, generateDidWeb, generateId, generateOpenAPISpec, getCookie, getDidWebUrl, getPermissionTemplate, headerAuth, hmacSha1Raw, hmacSha256, hmacSha256Raw, importHmacKey, initializePlugins, ja, kvStore, magicLink, magicLinks, mcpServers, oauth, oauthAccessTokens, oauthAuthorizationCodes, oauthClients, oauthProxy, oneTap, orgInvitations, orgMembers, orgRoles, organization, organizations, parseCookies2 as parseCookies, parseCookiesFromRequest, passkey, passkeyChallenges, passkeyCredentials, pbkdf2Hash, pbkdf2Verify, permissionTemplates, permissions, polar, randomBytes, randomBytesHex, rateLimit, rateLimits, resolveDidKey, resolveDidWeb, scim, serializeCookie, serializeCookieDeletion, sessions, sha1, sha256, sha256Raw, signPayload2 as signPayload, siwe, ssoConnections, stripe, tenants, toBase64Url, toHex, totpRecords, trustScores, twoFactor, users, validateCsrfToken, validateOrigin, verifyPayload, verifyPresentation, verifyWebhookSignature3 as verifyWebhookSignature, withRateLimit, zh };
20702
+ export { CredentialStatusSchema, CredentialSubjectSchema, EVENT_TYPES, HibpApiError, HibpBreachedError, KAVACH_AGENT_CREDENTIAL, KAVACH_DELEGATION_CREDENTIAL, KAVACH_PERMISSION_CREDENTIAL, KVStore, MemoryStore, MultiSessionLimitError, OAuthProxyError, OneTapVerifyError, ProofSchema, RefreshTokenError, SSO_ERROR, SsoError, VC_CONTEXT_V1, VC_CONTEXT_V2, VC_TYPE_CREDENTIAL, VC_TYPE_PRESENTATION, VerifiableCredentialSchema, VerifiablePresentationSchema, additionalFields, admin, agentCards, agentDids, agents, anonymousAuth, apiKeys2 as apiKeys, apiKeys as apiKeysTable, approvalRequests, auditLogs, bearerAuth, budgetPolicies, buildDidDocument, buildSessionMetadata, classifyViolation, constantTimeEqual, createAdditionalFieldsModule, createAdminModule, createAgentModule, createAnonymousAuthModule, createApiKeyManagerModule, createAppleProvider, createApprovalModule, createAuditModule, createCaptchaModule, createCookieSessionManager, createCostAttributionModule, createCustomSessionModule, createDatabase, createDatabaseSync, createDelegationModule, createDeviceAuthModule, createDidModule, createDiscordProvider, createEmailOtpModule, createEmailTemplates, createEmailVerificationModule, createEphemeralSessionModule, createEventStreamModule, createFederationModule, createGdprModule, createGithubProvider, createGitlabProvider, createGoogleProvider, createHibpModule, createI18n, createJwtSessionModule, createKavach, createLastLoginModule, createLinkedInProvider, createMagicLinkModule, createMicrosoftProvider, createMultiSessionModule, createOAuthModule, createOAuthProxyModule, createOidcProviderModule, createOneTapModule, createOneTimeTokenModule, createOpenApiModule, createOrgModule, createPasskeyModule, createPasswordResetModule, createPermissionEngine, createPhoneAuthModule, createPluginRouter, createPolarModule, createPolicyModule, createPresentation, createPrivilegeAnalyzer, createRateLimiter, createReBACModule, createRedirectChain, createScimModule, createSessionFreshnessModule, createSessionManager, createSessionRefresher, createSiweModule, createSlackProvider, createSsoModule, createStripeModule, createTables, createTenantModule, createTokenFamilyStore, createTotpModule, createTrustModule, createTrustedDeviceModule, createTwitterProvider, createUsernameAuthModule, createVCIssuer, createVCVerifier, createWebhookModule2 as createWebhookModule, customAuth, customSession, de, delegationChains, deviceAuth, deviceLabelFromRequest, emailOtp, emailOtps, en, es, fr, fromBase64Url, fromHex, gdpr, generateCsrfToken, generateDidKey, generateDidWeb, generateId, generateOpenAPISpec, getCookie2 as getCookie, getDidWebUrl, getPermissionTemplate, headerAuth, hmacSha1Raw, hmacSha256, hmacSha256Raw, importHmacKey, initializePlugins, ja, kvStore, magicLink, magicLinks, mcpServers, oauth, oauthAccessTokens, oauthAuthorizationCodes, oauthClients, oauthProxy, oneTap, orgInvitations, orgMembers, orgRoles, organization, organizations, parseCookies2 as parseCookies, parseCookiesFromRequest, passkey, passkeyChallenges, passkeyCredentials, pbkdf2Hash, pbkdf2Verify, permissionTemplates, permissions, polar, randomBytes, randomBytesHex, rateLimit, rateLimits, resolveDidKey, resolveDidWeb, scim, serializeCookie, serializeCookieDeletion, sessions, sha1, sha256, sha256Raw, signPayload2 as signPayload, siwe, ssoConnections, stripe, tenants, toBase64Url, toHex, totpRecords, trustScores, twoFactor, users, validateCsrfToken, validateOrigin, verifyPayload, verifyPresentation, verifyWebhookSignature3 as verifyWebhookSignature, withRateLimit, zh };
20670
20703
  //# sourceMappingURL=index.js.map
20671
20704
  //# sourceMappingURL=index.js.map