kavachos 0.1.4 → 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,9 +5660,7 @@ function createOAuthModule(db, config) {
5792
5660
  pruneExpiredStates
5793
5661
  };
5794
5662
  }
5795
-
5796
- // src/auth/oauth/plugin.ts
5797
- function jsonResponse10(body, status = 200) {
5663
+ function jsonResponse5(body, status = 200) {
5798
5664
  return new Response(JSON.stringify(body), {
5799
5665
  status,
5800
5666
  headers: { "Content-Type": "application/json" }
@@ -5812,6 +5678,12 @@ function oauth(config) {
5812
5678
  async init(ctx) {
5813
5679
  const module = createOAuthModule(ctx.db, config);
5814
5680
  const baseUrl = ctx.config.baseUrl ?? "";
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,21 +5726,62 @@ 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 {
5864
5736
  const result = await module.handleCallback(provider, code2, state, redirectUri);
5865
- return jsonResponse10({
5737
+ const email = result.userInfo.email;
5738
+ let userId = result.account.userId;
5739
+ if (userId === "__pending__" && email && ctx.db) {
5740
+ const existing = await ctx.db.select().from(users).where(eq(users.email, email));
5741
+ if (existing[0]) {
5742
+ userId = existing[0].id;
5743
+ } else {
5744
+ const newId = crypto.randomUUID();
5745
+ await ctx.db.insert(users).values({
5746
+ id: newId,
5747
+ email,
5748
+ name: result.userInfo.name ?? null,
5749
+ externalProvider: `oauth:${provider}`,
5750
+ externalId: result.userInfo.id,
5751
+ emailVerified: 1,
5752
+ createdAt: /* @__PURE__ */ new Date(),
5753
+ updatedAt: /* @__PURE__ */ new Date()
5754
+ });
5755
+ userId = newId;
5756
+ }
5757
+ await module.linkAccount(userId, provider, result.userInfo, {
5758
+ accessToken: result.account.accessToken,
5759
+ refreshToken: result.account.refreshToken ?? void 0,
5760
+ tokenType: "Bearer",
5761
+ raw: {}
5762
+ });
5763
+ }
5764
+ if (userId !== "__pending__") {
5765
+ const { session, token } = await sessionManager.create(userId);
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
+ });
5777
+ }
5778
+ return jsonResponse5({
5866
5779
  isNewAccount: result.isNewAccount,
5867
5780
  account: result.account,
5868
5781
  userInfo: result.userInfo
5869
5782
  });
5870
5783
  } catch (err2) {
5871
- return jsonResponse10(
5784
+ return jsonResponse5(
5872
5785
  { error: err2 instanceof Error ? err2.message : "OAuth callback failed" },
5873
5786
  400
5874
5787
  );
@@ -5885,29 +5798,29 @@ function oauth(config) {
5885
5798
  async handler(request, endpointCtx) {
5886
5799
  const user = await endpointCtx.getUser(request);
5887
5800
  if (!user) {
5888
- return jsonResponse10({ error: "Authentication required" }, 401);
5801
+ return jsonResponse5({ error: "Authentication required" }, 401);
5889
5802
  }
5890
5803
  let body;
5891
5804
  try {
5892
5805
  body = await request.json();
5893
5806
  } catch {
5894
- return jsonResponse10({ error: "Invalid JSON body" }, 400);
5807
+ return jsonResponse5({ error: "Invalid JSON body" }, 400);
5895
5808
  }
5896
5809
  const b = body;
5897
5810
  const provider = typeof b.provider === "string" ? b.provider : null;
5898
5811
  const userInfo = typeof b.userInfo === "object" && b.userInfo !== null ? b.userInfo : null;
5899
5812
  const tokens = typeof b.tokens === "object" && b.tokens !== null ? b.tokens : null;
5900
5813
  if (!provider || !userInfo || !tokens) {
5901
- return jsonResponse10(
5814
+ return jsonResponse5(
5902
5815
  { error: "Missing required fields: provider, userInfo, tokens" },
5903
5816
  400
5904
5817
  );
5905
5818
  }
5906
5819
  try {
5907
5820
  const account = await module.linkAccount(user.id, provider, userInfo, tokens);
5908
- return jsonResponse10({ account });
5821
+ return jsonResponse5({ account });
5909
5822
  } catch (err2) {
5910
- return jsonResponse10(
5823
+ return jsonResponse5(
5911
5824
  { error: err2 instanceof Error ? err2.message : "Failed to link account" },
5912
5825
  400
5913
5826
  );
@@ -5923,7 +5836,7 @@ function oauth(config) {
5923
5836
  id: p2.id,
5924
5837
  name: p2.name
5925
5838
  }));
5926
- return jsonResponse10({ providers });
5839
+ return jsonResponse5({ providers });
5927
5840
  }
5928
5841
  });
5929
5842
  }
@@ -7720,25 +7633,25 @@ function createOneTapModule(config, db, sessionManager) {
7720
7633
  const text3 = await request.text();
7721
7634
  formData = new URLSearchParams(text3);
7722
7635
  } catch {
7723
- return jsonResponse11({ error: "Failed to parse request body" }, 400);
7636
+ return jsonResponse6({ error: "Failed to parse request body" }, 400);
7724
7637
  }
7725
7638
  const credential = formData.get("credential");
7726
7639
  const bodyToken = formData.get(csrfCookieName);
7727
7640
  if (!credential) {
7728
- return jsonResponse11({ error: "Missing credential field" }, 400);
7641
+ return jsonResponse6({ error: "Missing credential field" }, 400);
7729
7642
  }
7730
7643
  const cookieToken = getCsrfCookie(request);
7731
7644
  if (!cookieToken || !bodyToken || cookieToken !== bodyToken) {
7732
- return jsonResponse11({ error: "CSRF token mismatch" }, 403);
7645
+ return jsonResponse6({ error: "CSRF token mismatch" }, 403);
7733
7646
  }
7734
7647
  let googleUser;
7735
7648
  try {
7736
7649
  googleUser = await verify(credential);
7737
7650
  } catch (err2) {
7738
7651
  if (err2 instanceof OneTapVerifyError && err2.code === "USER_NOT_FOUND") {
7739
- return jsonResponse11({ error: err2.message }, 403);
7652
+ return jsonResponse6({ error: err2.message }, 403);
7740
7653
  }
7741
- return jsonResponse11(
7654
+ return jsonResponse6(
7742
7655
  { error: err2 instanceof Error ? err2.message : "Token verification failed" },
7743
7656
  401
7744
7657
  );
@@ -7748,27 +7661,96 @@ function createOneTapModule(config, db, sessionManager) {
7748
7661
  user = await findOrCreateUser(googleUser);
7749
7662
  } catch (err2) {
7750
7663
  if (err2 instanceof OneTapVerifyError && err2.code === "USER_NOT_FOUND") {
7751
- return jsonResponse11({ error: err2.message }, 403);
7664
+ return jsonResponse6({ error: err2.message }, 403);
7752
7665
  }
7753
- return jsonResponse11(
7666
+ return jsonResponse6(
7754
7667
  { error: err2 instanceof Error ? err2.message : "Failed to resolve user" },
7755
7668
  500
7756
7669
  );
7757
7670
  }
7758
7671
  const { token: sessionToken, session } = await sessionManager.create(user.id);
7759
- return jsonResponse11({
7672
+ return jsonResponse6({
7760
7673
  user: { id: user.id, email: user.email },
7761
7674
  session: { token: sessionToken, expiresAt: session.expiresAt }
7762
7675
  });
7763
7676
  }
7764
7677
  return { verify, handleRequest };
7765
7678
  }
7766
- function jsonResponse11(body, status = 200) {
7679
+ function jsonResponse6(body, status = 200) {
7767
7680
  return new Response(JSON.stringify(body), {
7768
7681
  status,
7769
7682
  headers: { "Content-Type": "application/json" }
7770
7683
  });
7771
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
+ }
7772
7754
 
7773
7755
  // src/auth/one-tap-plugin.ts
7774
7756
  function oneTap(config) {
@@ -9060,14 +9042,14 @@ function rowToInvitation(row) {
9060
9042
  createdAt: row.createdAt
9061
9043
  };
9062
9044
  }
9063
- function jsonResponse12(body, status = 200) {
9045
+ function jsonResponse7(body, status = 200) {
9064
9046
  return new Response(JSON.stringify(body), {
9065
9047
  status,
9066
9048
  headers: { "Content-Type": "application/json" }
9067
9049
  });
9068
9050
  }
9069
9051
  function errorResponse(message, status) {
9070
- return jsonResponse12({ error: message }, status);
9052
+ return jsonResponse7({ error: message }, status);
9071
9053
  }
9072
9054
  function createOrgModule(config, db) {
9073
9055
  const maxMembers = config.maxMembers ?? DEFAULT_MAX_MEMBERS;
@@ -9373,7 +9355,7 @@ function createOrgModule(config, db) {
9373
9355
  try {
9374
9356
  const body = await request.json();
9375
9357
  const org = await create(body);
9376
- return jsonResponse12(org, 201);
9358
+ return jsonResponse7(org, 201);
9377
9359
  } catch (err2) {
9378
9360
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
9379
9361
  }
@@ -9383,7 +9365,7 @@ function createOrgModule(config, db) {
9383
9365
  const userId = userOrgMatch[1];
9384
9366
  if (!userId) return errorResponse("Missing userId", 400);
9385
9367
  const orgs = await list(userId);
9386
- return jsonResponse12(orgs);
9368
+ return jsonResponse7(orgs);
9387
9369
  }
9388
9370
  const orgBaseMatch = pathname.match(/^\/auth\/org\/([^/]+)(\/.*)?$/);
9389
9371
  if (!orgBaseMatch) return null;
@@ -9393,13 +9375,13 @@ function createOrgModule(config, db) {
9393
9375
  if (method === "GET" && subPath === "") {
9394
9376
  const org = await get(orgId);
9395
9377
  if (!org) return errorResponse("Organization not found", 404);
9396
- return jsonResponse12(org);
9378
+ return jsonResponse7(org);
9397
9379
  }
9398
9380
  if (method === "PATCH" && subPath === "") {
9399
9381
  try {
9400
9382
  const body = await request.json();
9401
9383
  const org = await update(orgId, body);
9402
- return jsonResponse12(org);
9384
+ return jsonResponse7(org);
9403
9385
  } catch (err2) {
9404
9386
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
9405
9387
  }
@@ -9407,7 +9389,7 @@ function createOrgModule(config, db) {
9407
9389
  if (method === "DELETE" && subPath === "") {
9408
9390
  try {
9409
9391
  await remove(orgId);
9410
- return jsonResponse12({ success: true });
9392
+ return jsonResponse7({ success: true });
9411
9393
  } catch (err2) {
9412
9394
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
9413
9395
  }
@@ -9416,14 +9398,14 @@ function createOrgModule(config, db) {
9416
9398
  try {
9417
9399
  const body = await request.json();
9418
9400
  const member = await addMember(orgId, body.userId, body.role);
9419
- return jsonResponse12(member, 201);
9401
+ return jsonResponse7(member, 201);
9420
9402
  } catch (err2) {
9421
9403
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
9422
9404
  }
9423
9405
  }
9424
9406
  if (method === "GET" && subPath === "/members") {
9425
9407
  const members = await getMembers(orgId);
9426
- return jsonResponse12(members);
9408
+ return jsonResponse7(members);
9427
9409
  }
9428
9410
  const memberMatch = subPath.match(/^\/members\/([^/]+)$/);
9429
9411
  if (method === "PATCH" && memberMatch) {
@@ -9432,7 +9414,7 @@ function createOrgModule(config, db) {
9432
9414
  try {
9433
9415
  const body = await request.json();
9434
9416
  const member = await updateMemberRole(orgId, userId, body.role);
9435
- return jsonResponse12(member);
9417
+ return jsonResponse7(member);
9436
9418
  } catch (err2) {
9437
9419
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
9438
9420
  }
@@ -9441,20 +9423,20 @@ function createOrgModule(config, db) {
9441
9423
  const userId = memberMatch[1];
9442
9424
  if (!userId) return errorResponse("Missing userId", 400);
9443
9425
  await removeMember(orgId, userId);
9444
- return jsonResponse12({ success: true });
9426
+ return jsonResponse7({ success: true });
9445
9427
  }
9446
9428
  if (method === "POST" && subPath === "/invite") {
9447
9429
  try {
9448
9430
  const body = await request.json();
9449
9431
  const invitation = await invite({ orgId, ...body });
9450
- return jsonResponse12(invitation, 201);
9432
+ return jsonResponse7(invitation, 201);
9451
9433
  } catch (err2) {
9452
9434
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
9453
9435
  }
9454
9436
  }
9455
9437
  if (method === "GET" && subPath === "/invitations") {
9456
9438
  const invitations = await listInvitations(orgId);
9457
- return jsonResponse12(invitations);
9439
+ return jsonResponse7(invitations);
9458
9440
  }
9459
9441
  const permMatch = subPath.match(/^\/permissions\/([^/]+)\/([^/]+)$/);
9460
9442
  if (method === "GET" && permMatch) {
@@ -9462,20 +9444,20 @@ function createOrgModule(config, db) {
9462
9444
  const permission = permMatch[2];
9463
9445
  if (!userId || !permission) return errorResponse("Missing userId or permission", 400);
9464
9446
  const allowed = await hasPermission(orgId, userId, permission);
9465
- return jsonResponse12({ allowed });
9447
+ return jsonResponse7({ allowed });
9466
9448
  }
9467
9449
  if (method === "POST" && subPath === "/roles") {
9468
9450
  try {
9469
9451
  const body = await request.json();
9470
9452
  const role = await createRole(orgId, body);
9471
- return jsonResponse12(role, 201);
9453
+ return jsonResponse7(role, 201);
9472
9454
  } catch (err2) {
9473
9455
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
9474
9456
  }
9475
9457
  }
9476
9458
  if (method === "GET" && subPath === "/roles") {
9477
9459
  const roles = await getRoles(orgId);
9478
- return jsonResponse12(roles);
9460
+ return jsonResponse7(roles);
9479
9461
  }
9480
9462
  return null;
9481
9463
  }
@@ -9490,7 +9472,7 @@ function createOrgModule(config, db) {
9490
9472
  try {
9491
9473
  const body = await request.json();
9492
9474
  const member = await acceptInvitation(invitationId, body.userId);
9493
- return jsonResponse12(member, 201);
9475
+ return jsonResponse7(member, 201);
9494
9476
  } catch (err2) {
9495
9477
  return errorResponse(err2 instanceof Error ? err2.message : "Unknown error", 400);
9496
9478
  }
@@ -9500,7 +9482,7 @@ function createOrgModule(config, db) {
9500
9482
  const invitationId = revokeMatch[1];
9501
9483
  if (!invitationId) return errorResponse("Missing invitationId", 400);
9502
9484
  await revokeInvitation(invitationId);
9503
- return jsonResponse12({ success: true });
9485
+ return jsonResponse7({ success: true });
9504
9486
  }
9505
9487
  return handleRequest(request);
9506
9488
  }
@@ -9531,13 +9513,13 @@ function createOrgModule(config, db) {
9531
9513
  }
9532
9514
 
9533
9515
  // src/auth/organization-plugin.ts
9534
- function jsonResponse13(body, status = 200) {
9516
+ function jsonResponse8(body, status = 200) {
9535
9517
  return new Response(JSON.stringify(body), {
9536
9518
  status,
9537
9519
  headers: { "Content-Type": "application/json" }
9538
9520
  });
9539
9521
  }
9540
- async function parseBody7(request) {
9522
+ async function parseBody3(request) {
9541
9523
  try {
9542
9524
  return await request.json();
9543
9525
  } catch {
@@ -9560,20 +9542,20 @@ function organization(config) {
9560
9542
  async handler(request, endpointCtx) {
9561
9543
  const user = await endpointCtx.getUser(request);
9562
9544
  if (!user) {
9563
- return jsonResponse13({ error: "Authentication required" }, 401);
9545
+ return jsonResponse8({ error: "Authentication required" }, 401);
9564
9546
  }
9565
- const body = await parseBody7(request);
9547
+ const body = await parseBody3(request);
9566
9548
  const name = typeof body.name === "string" ? body.name.trim() : null;
9567
9549
  const slug = typeof body.slug === "string" ? body.slug.trim() : null;
9568
9550
  if (!name || !slug) {
9569
- return jsonResponse13({ error: "Missing required fields: name, slug" }, 400);
9551
+ return jsonResponse8({ error: "Missing required fields: name, slug" }, 400);
9570
9552
  }
9571
9553
  const metadata = body.metadata !== void 0 && typeof body.metadata === "object" && body.metadata !== null ? body.metadata : void 0;
9572
9554
  try {
9573
9555
  const org = await module.create({ name, slug, ownerId: user.id, metadata });
9574
- return jsonResponse13(org, 201);
9556
+ return jsonResponse8(org, 201);
9575
9557
  } catch (err2) {
9576
- return jsonResponse13(
9558
+ return jsonResponse8(
9577
9559
  { error: err2 instanceof Error ? err2.message : "Failed to create organization" },
9578
9560
  400
9579
9561
  );
@@ -9590,10 +9572,10 @@ function organization(config) {
9590
9572
  async handler(request, endpointCtx) {
9591
9573
  const user = await endpointCtx.getUser(request);
9592
9574
  if (!user) {
9593
- return jsonResponse13({ error: "Authentication required" }, 401);
9575
+ return jsonResponse8({ error: "Authentication required" }, 401);
9594
9576
  }
9595
9577
  const orgs = await module.list(user.id);
9596
- return jsonResponse13({ organizations: orgs });
9578
+ return jsonResponse8({ organizations: orgs });
9597
9579
  }
9598
9580
  });
9599
9581
  ctx.addEndpoint({
@@ -9606,23 +9588,23 @@ function organization(config) {
9606
9588
  async handler(request, endpointCtx) {
9607
9589
  const user = await endpointCtx.getUser(request);
9608
9590
  if (!user) {
9609
- return jsonResponse13({ error: "Authentication required" }, 401);
9591
+ return jsonResponse8({ error: "Authentication required" }, 401);
9610
9592
  }
9611
9593
  const url = new URL(request.url);
9612
9594
  const segments = url.pathname.split("/").filter(Boolean);
9613
9595
  const orgId = segments[2];
9614
9596
  if (!orgId) {
9615
- return jsonResponse13({ error: "Missing organization ID in path" }, 400);
9597
+ return jsonResponse8({ error: "Missing organization ID in path" }, 400);
9616
9598
  }
9617
9599
  const member = await module.getMember(orgId, user.id);
9618
9600
  if (!member || !ADMIN_ROLES.has(member.role)) {
9619
- return jsonResponse13({ error: "Admin or owner role required" }, 403);
9601
+ return jsonResponse8({ error: "Admin or owner role required" }, 403);
9620
9602
  }
9621
- const body = await parseBody7(request);
9603
+ const body = await parseBody3(request);
9622
9604
  const email = typeof body.email === "string" ? body.email.trim().toLowerCase() : null;
9623
9605
  const role = typeof body.role === "string" ? body.role : "member";
9624
9606
  if (!email) {
9625
- return jsonResponse13({ error: "Missing required field: email" }, 400);
9607
+ return jsonResponse8({ error: "Missing required field: email" }, 400);
9626
9608
  }
9627
9609
  try {
9628
9610
  const invitation = await module.invite({
@@ -9631,9 +9613,9 @@ function organization(config) {
9631
9613
  role,
9632
9614
  invitedBy: user.id
9633
9615
  });
9634
- return jsonResponse13(invitation, 201);
9616
+ return jsonResponse8(invitation, 201);
9635
9617
  } catch (err2) {
9636
- return jsonResponse13(
9618
+ return jsonResponse8(
9637
9619
  { error: err2 instanceof Error ? err2.message : "Failed to send invitation" },
9638
9620
  400
9639
9621
  );
@@ -9650,20 +9632,20 @@ function organization(config) {
9650
9632
  async handler(request, endpointCtx) {
9651
9633
  const user = await endpointCtx.getUser(request);
9652
9634
  if (!user) {
9653
- return jsonResponse13({ error: "Authentication required" }, 401);
9635
+ return jsonResponse8({ error: "Authentication required" }, 401);
9654
9636
  }
9655
9637
  const url = new URL(request.url);
9656
9638
  const segments = url.pathname.split("/").filter(Boolean);
9657
9639
  const orgId = segments[2];
9658
9640
  if (!orgId) {
9659
- return jsonResponse13({ error: "Missing organization ID in path" }, 400);
9641
+ return jsonResponse8({ error: "Missing organization ID in path" }, 400);
9660
9642
  }
9661
9643
  const callerMember = await module.getMember(orgId, user.id);
9662
9644
  if (!callerMember) {
9663
- 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);
9664
9646
  }
9665
9647
  const members = await module.getMembers(orgId);
9666
- return jsonResponse13({ members });
9648
+ return jsonResponse8({ members });
9667
9649
  }
9668
9650
  });
9669
9651
  ctx.addEndpoint({
@@ -9676,29 +9658,29 @@ function organization(config) {
9676
9658
  async handler(request, endpointCtx) {
9677
9659
  const user = await endpointCtx.getUser(request);
9678
9660
  if (!user) {
9679
- return jsonResponse13({ error: "Authentication required" }, 401);
9661
+ return jsonResponse8({ error: "Authentication required" }, 401);
9680
9662
  }
9681
9663
  const url = new URL(request.url);
9682
9664
  const segments = url.pathname.split("/").filter(Boolean);
9683
9665
  const orgId = segments[2];
9684
9666
  const targetUserId = segments[4];
9685
9667
  if (!orgId || !targetUserId) {
9686
- 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);
9687
9669
  }
9688
9670
  const callerMember = await module.getMember(orgId, user.id);
9689
9671
  if (!callerMember || !ADMIN_ROLES.has(callerMember.role)) {
9690
- return jsonResponse13({ error: "Admin or owner role required" }, 403);
9672
+ return jsonResponse8({ error: "Admin or owner role required" }, 403);
9691
9673
  }
9692
- const body = await parseBody7(request);
9674
+ const body = await parseBody3(request);
9693
9675
  const role = typeof body.role === "string" ? body.role : null;
9694
9676
  if (!role) {
9695
- return jsonResponse13({ error: "Missing required field: role" }, 400);
9677
+ return jsonResponse8({ error: "Missing required field: role" }, 400);
9696
9678
  }
9697
9679
  try {
9698
9680
  const member = await module.updateMemberRole(orgId, targetUserId, role);
9699
- return jsonResponse13(member);
9681
+ return jsonResponse8(member);
9700
9682
  } catch (err2) {
9701
- return jsonResponse13(
9683
+ return jsonResponse8(
9702
9684
  { error: err2 instanceof Error ? err2.message : "Failed to update member role" },
9703
9685
  400
9704
9686
  );
@@ -9715,24 +9697,24 @@ function organization(config) {
9715
9697
  async handler(request, endpointCtx) {
9716
9698
  const user = await endpointCtx.getUser(request);
9717
9699
  if (!user) {
9718
- return jsonResponse13({ error: "Authentication required" }, 401);
9700
+ return jsonResponse8({ error: "Authentication required" }, 401);
9719
9701
  }
9720
9702
  const url = new URL(request.url);
9721
9703
  const segments = url.pathname.split("/").filter(Boolean);
9722
9704
  const orgId = segments[2];
9723
9705
  const targetUserId = segments[4];
9724
9706
  if (!orgId || !targetUserId) {
9725
- 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);
9726
9708
  }
9727
9709
  const callerMember = await module.getMember(orgId, user.id);
9728
9710
  if (!callerMember || !ADMIN_ROLES.has(callerMember.role)) {
9729
- return jsonResponse13({ error: "Admin or owner role required" }, 403);
9711
+ return jsonResponse8({ error: "Admin or owner role required" }, 403);
9730
9712
  }
9731
9713
  try {
9732
9714
  await module.removeMember(orgId, targetUserId);
9733
- return jsonResponse13({ removed: true });
9715
+ return jsonResponse8({ removed: true });
9734
9716
  } catch (err2) {
9735
- return jsonResponse13(
9717
+ return jsonResponse8(
9736
9718
  { error: err2 instanceof Error ? err2.message : "Failed to remove member" },
9737
9719
  400
9738
9720
  );
@@ -10137,13 +10119,13 @@ function parseAuthData(authData) {
10137
10119
  }
10138
10120
  return { rpIdHash, flags, signCount, attestedCredentialData };
10139
10121
  }
10140
- function jsonResponse14(body, status = 200) {
10122
+ function jsonResponse9(body, status = 200) {
10141
10123
  return new Response(JSON.stringify(body), {
10142
10124
  status,
10143
10125
  headers: { "Content-Type": "application/json" }
10144
10126
  });
10145
10127
  }
10146
- async function parseBody8(request) {
10128
+ async function parseBody4(request) {
10147
10129
  try {
10148
10130
  return await request.json();
10149
10131
  } catch {
@@ -10481,84 +10463,84 @@ function createPasskeyModule(config, db) {
10481
10463
  const method = request.method.toUpperCase();
10482
10464
  const segments = getPathSegments(url);
10483
10465
  if (method === "POST" && segments.length === 4 && segments[1] === "passkey" && segments[2] === "register" && segments[3] === "options") {
10484
- const body = await parseBody8(request);
10466
+ const body = await parseBody4(request);
10485
10467
  const userId = typeof body.userId === "string" ? body.userId : null;
10486
10468
  const userName = typeof body.userName === "string" ? body.userName : null;
10487
10469
  if (!userId || !userName) {
10488
- return jsonResponse14({ error: "userId and userName required" }, 400);
10470
+ return jsonResponse9({ error: "userId and userName required" }, 400);
10489
10471
  }
10490
10472
  try {
10491
10473
  const options = await getRegistrationOptions(userId, userName);
10492
- return jsonResponse14(options);
10474
+ return jsonResponse9(options);
10493
10475
  } catch (err2) {
10494
10476
  const message = err2 instanceof Error ? err2.message : "Failed to generate options";
10495
10477
  const code2 = err2 instanceof PasskeyError ? err2.code : "INTERNAL_ERROR";
10496
- return jsonResponse14({ error: message, code: code2 }, 500);
10478
+ return jsonResponse9({ error: message, code: code2 }, 500);
10497
10479
  }
10498
10480
  }
10499
10481
  if (method === "POST" && segments.length === 4 && segments[1] === "passkey" && segments[2] === "register" && segments[3] === "verify") {
10500
- const body = await parseBody8(request);
10482
+ const body = await parseBody4(request);
10501
10483
  const userId = typeof body.userId === "string" ? body.userId : null;
10502
- if (!userId) return jsonResponse14({ error: "userId required" }, 400);
10484
+ if (!userId) return jsonResponse9({ error: "userId required" }, 400);
10503
10485
  const resp = body.response;
10504
- if (!resp) return jsonResponse14({ error: "response required" }, 400);
10486
+ if (!resp) return jsonResponse9({ error: "response required" }, 400);
10505
10487
  try {
10506
10488
  const result = await verifyRegistration(userId, resp);
10507
- return jsonResponse14(result);
10489
+ return jsonResponse9(result);
10508
10490
  } catch (err2) {
10509
10491
  const message = err2 instanceof Error ? err2.message : "Registration failed";
10510
10492
  const code2 = err2 instanceof PasskeyError ? err2.code : "INTERNAL_ERROR";
10511
- return jsonResponse14({ error: message, code: code2 }, 400);
10493
+ return jsonResponse9({ error: message, code: code2 }, 400);
10512
10494
  }
10513
10495
  }
10514
10496
  if (method === "POST" && segments.length === 4 && segments[1] === "passkey" && segments[2] === "login" && segments[3] === "options") {
10515
- const body = await parseBody8(request);
10497
+ const body = await parseBody4(request);
10516
10498
  const userId = typeof body.userId === "string" ? body.userId : void 0;
10517
10499
  try {
10518
10500
  const options = await getAuthenticationOptions(userId);
10519
- return jsonResponse14(options);
10501
+ return jsonResponse9(options);
10520
10502
  } catch (err2) {
10521
10503
  const message = err2 instanceof Error ? err2.message : "Failed to generate options";
10522
10504
  const code2 = err2 instanceof PasskeyError ? err2.code : "INTERNAL_ERROR";
10523
- return jsonResponse14({ error: message, code: code2 }, 500);
10505
+ return jsonResponse9({ error: message, code: code2 }, 500);
10524
10506
  }
10525
10507
  }
10526
10508
  if (method === "POST" && segments.length === 4 && segments[1] === "passkey" && segments[2] === "login" && segments[3] === "verify") {
10527
- const body = await parseBody8(request);
10509
+ const body = await parseBody4(request);
10528
10510
  const resp = body.response;
10529
- if (!resp) return jsonResponse14({ error: "response required" }, 400);
10511
+ if (!resp) return jsonResponse9({ error: "response required" }, 400);
10530
10512
  try {
10531
10513
  const result = await verifyAuthentication(resp);
10532
- return jsonResponse14(result);
10514
+ return jsonResponse9(result);
10533
10515
  } catch (err2) {
10534
10516
  const message = err2 instanceof Error ? err2.message : "Authentication failed";
10535
10517
  const code2 = err2 instanceof PasskeyError ? err2.code : "INTERNAL_ERROR";
10536
- return jsonResponse14({ error: message, code: code2 }, 401);
10518
+ return jsonResponse9({ error: message, code: code2 }, 401);
10537
10519
  }
10538
10520
  }
10539
10521
  if (method === "GET" && segments.length === 3 && segments[1] === "passkey" && segments[2] === "credentials") {
10540
10522
  const userId = url.searchParams.get("userId");
10541
- if (!userId) return jsonResponse14({ error: "userId query param required" }, 400);
10523
+ if (!userId) return jsonResponse9({ error: "userId query param required" }, 400);
10542
10524
  try {
10543
10525
  const creds = await listCredentials(userId);
10544
- return jsonResponse14({ credentials: creds });
10526
+ return jsonResponse9({ credentials: creds });
10545
10527
  } catch (err2) {
10546
10528
  const message = err2 instanceof Error ? err2.message : "Failed to list credentials";
10547
- return jsonResponse14({ error: message }, 500);
10529
+ return jsonResponse9({ error: message }, 500);
10548
10530
  }
10549
10531
  }
10550
10532
  if (method === "DELETE" && segments.length === 4 && segments[1] === "passkey" && segments[2] === "credentials") {
10551
10533
  const credentialId = segments[3];
10552
- if (!credentialId) return jsonResponse14({ error: "Credential ID required" }, 400);
10553
- const body = await parseBody8(request);
10534
+ if (!credentialId) return jsonResponse9({ error: "Credential ID required" }, 400);
10535
+ const body = await parseBody4(request);
10554
10536
  const userId = typeof body.userId === "string" ? body.userId : null;
10555
- if (!userId) return jsonResponse14({ error: "userId required" }, 400);
10537
+ if (!userId) return jsonResponse9({ error: "userId required" }, 400);
10556
10538
  try {
10557
10539
  await removeCredential(credentialId, userId);
10558
- return jsonResponse14({ removed: true });
10540
+ return jsonResponse9({ removed: true });
10559
10541
  } catch (err2) {
10560
10542
  const message = err2 instanceof Error ? err2.message : "Failed to remove credential";
10561
- return jsonResponse14({ error: message }, 500);
10543
+ return jsonResponse9({ error: message }, 500);
10562
10544
  }
10563
10545
  }
10564
10546
  return null;
@@ -10575,13 +10557,13 @@ function createPasskeyModule(config, db) {
10575
10557
  }
10576
10558
 
10577
10559
  // src/auth/passkey-plugin.ts
10578
- function jsonResponse15(body, status = 200) {
10560
+ function jsonResponse10(body, status = 200) {
10579
10561
  return new Response(JSON.stringify(body), {
10580
10562
  status,
10581
10563
  headers: { "Content-Type": "application/json" }
10582
10564
  });
10583
10565
  }
10584
- async function parseBody9(request) {
10566
+ async function parseBody5(request) {
10585
10567
  try {
10586
10568
  return await request.json();
10587
10569
  } catch {
@@ -10603,16 +10585,16 @@ function passkey(config) {
10603
10585
  async handler(request, endpointCtx) {
10604
10586
  const user = await endpointCtx.getUser(request);
10605
10587
  if (!user) {
10606
- return jsonResponse15({ error: "Authentication required" }, 401);
10588
+ return jsonResponse10({ error: "Authentication required" }, 401);
10607
10589
  }
10608
- const body = await parseBody9(request);
10590
+ const body = await parseBody5(request);
10609
10591
  const userId = typeof body.userId === "string" ? body.userId : user.id;
10610
10592
  const userName = typeof body.userName === "string" ? body.userName : user.email ?? user.id;
10611
10593
  try {
10612
10594
  const options = await module.getRegistrationOptions(userId, userName);
10613
- return jsonResponse15(options);
10595
+ return jsonResponse10(options);
10614
10596
  } catch (err2) {
10615
- return jsonResponse15(
10597
+ return jsonResponse10(
10616
10598
  { error: err2 instanceof Error ? err2.message : "Failed to generate options" },
10617
10599
  500
10618
10600
  );
@@ -10629,19 +10611,19 @@ function passkey(config) {
10629
10611
  async handler(request, endpointCtx) {
10630
10612
  const user = await endpointCtx.getUser(request);
10631
10613
  if (!user) {
10632
- return jsonResponse15({ error: "Authentication required" }, 401);
10614
+ return jsonResponse10({ error: "Authentication required" }, 401);
10633
10615
  }
10634
- const body = await parseBody9(request);
10616
+ const body = await parseBody5(request);
10635
10617
  const userId = typeof body.userId === "string" ? body.userId : user.id;
10636
10618
  const response = body.response;
10637
10619
  if (!response) {
10638
- return jsonResponse15({ error: "Missing required field: response" }, 400);
10620
+ return jsonResponse10({ error: "Missing required field: response" }, 400);
10639
10621
  }
10640
10622
  try {
10641
10623
  const result = await module.verifyRegistration(userId, response);
10642
- return jsonResponse15(result);
10624
+ return jsonResponse10(result);
10643
10625
  } catch (err2) {
10644
- return jsonResponse15(
10626
+ return jsonResponse10(
10645
10627
  { error: err2 instanceof Error ? err2.message : "Registration failed" },
10646
10628
  400
10647
10629
  );
@@ -10655,13 +10637,13 @@ function passkey(config) {
10655
10637
  description: "Get WebAuthn authentication options"
10656
10638
  },
10657
10639
  async handler(request) {
10658
- const body = await parseBody9(request);
10640
+ const body = await parseBody5(request);
10659
10641
  const userId = typeof body.userId === "string" ? body.userId : void 0;
10660
10642
  try {
10661
10643
  const options = await module.getAuthenticationOptions(userId);
10662
- return jsonResponse15(options);
10644
+ return jsonResponse10(options);
10663
10645
  } catch (err2) {
10664
- return jsonResponse15(
10646
+ return jsonResponse10(
10665
10647
  { error: err2 instanceof Error ? err2.message : "Failed to generate options" },
10666
10648
  500
10667
10649
  );
@@ -10675,19 +10657,37 @@ function passkey(config) {
10675
10657
  description: "Verify a WebAuthn assertion and return the authenticated user"
10676
10658
  },
10677
10659
  async handler(request) {
10678
- const body = await parseBody9(request);
10660
+ const body = await parseBody5(request);
10679
10661
  const response = body.response;
10680
10662
  if (!response) {
10681
- return jsonResponse15({ error: "Missing required field: response" }, 400);
10663
+ return jsonResponse10({ error: "Missing required field: response" }, 400);
10682
10664
  }
10683
10665
  try {
10684
10666
  const result = await module.verifyAuthentication(response);
10685
10667
  if (!result) {
10686
- return jsonResponse15({ error: "Authentication failed" }, 401);
10668
+ return jsonResponse10({ error: "Authentication failed" }, 401);
10687
10669
  }
10688
- 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);
10689
10689
  } catch (err2) {
10690
- return jsonResponse15(
10690
+ return jsonResponse10(
10691
10691
  { error: err2 instanceof Error ? err2.message : "Authentication failed" },
10692
10692
  401
10693
10693
  );
@@ -10704,13 +10704,13 @@ function passkey(config) {
10704
10704
  async handler(request, endpointCtx) {
10705
10705
  const user = await endpointCtx.getUser(request);
10706
10706
  if (!user) {
10707
- return jsonResponse15({ error: "Authentication required" }, 401);
10707
+ return jsonResponse10({ error: "Authentication required" }, 401);
10708
10708
  }
10709
10709
  try {
10710
10710
  const credentials = await module.listCredentials(user.id);
10711
- return jsonResponse15({ credentials });
10711
+ return jsonResponse10({ credentials });
10712
10712
  } catch (err2) {
10713
- return jsonResponse15(
10713
+ return jsonResponse10(
10714
10714
  { error: err2 instanceof Error ? err2.message : "Failed to list credentials" },
10715
10715
  500
10716
10716
  );
@@ -10727,19 +10727,19 @@ function passkey(config) {
10727
10727
  async handler(request, endpointCtx) {
10728
10728
  const user = await endpointCtx.getUser(request);
10729
10729
  if (!user) {
10730
- return jsonResponse15({ error: "Authentication required" }, 401);
10730
+ return jsonResponse10({ error: "Authentication required" }, 401);
10731
10731
  }
10732
10732
  const url = new URL(request.url);
10733
10733
  const segments = url.pathname.split("/").filter(Boolean);
10734
10734
  const credentialId = segments[3];
10735
10735
  if (!credentialId) {
10736
- return jsonResponse15({ error: "Missing credential ID in path" }, 400);
10736
+ return jsonResponse10({ error: "Missing credential ID in path" }, 400);
10737
10737
  }
10738
10738
  try {
10739
10739
  await module.removeCredential(credentialId, user.id);
10740
- return jsonResponse15({ removed: true });
10740
+ return jsonResponse10({ removed: true });
10741
10741
  } catch (err2) {
10742
- return jsonResponse15(
10742
+ return jsonResponse10(
10743
10743
  { error: err2 instanceof Error ? err2.message : "Failed to remove credential" },
10744
10744
  500
10745
10745
  );
@@ -10756,7 +10756,7 @@ var TOKEN_PURPOSE2 = "password-reset";
10756
10756
  function makeError7(code2, message, details) {
10757
10757
  return { code: code2, message, ...details !== void 0 ? { details } : {} };
10758
10758
  }
10759
- function jsonResponse16(body, status = 200) {
10759
+ function jsonResponse11(body, status = 200) {
10760
10760
  return new Response(JSON.stringify(body), {
10761
10761
  status,
10762
10762
  headers: { "Content-Type": "application/json" }
@@ -10872,27 +10872,27 @@ function createPasswordResetModule(config, db, sessionManager, tokenModule) {
10872
10872
  try {
10873
10873
  body = await request.json();
10874
10874
  } catch {
10875
- return jsonResponse16({ error: "Invalid JSON body" }, 400);
10875
+ return jsonResponse11({ error: "Invalid JSON body" }, 400);
10876
10876
  }
10877
10877
  const b = body;
10878
10878
  if (pathname === "/auth/forgot-password") {
10879
10879
  if (typeof b.email !== "string") {
10880
- return jsonResponse16({ error: "Missing required field: email" }, 400);
10880
+ return jsonResponse11({ error: "Missing required field: email" }, 400);
10881
10881
  }
10882
10882
  const result = await requestReset(b.email);
10883
10883
  if (!result.success) {
10884
- return jsonResponse16({ error: result.error.message }, 500);
10884
+ return jsonResponse11({ error: result.error.message }, 500);
10885
10885
  }
10886
10886
  return new Response(null, { status: 204 });
10887
10887
  }
10888
10888
  if (pathname === "/auth/reset-password") {
10889
10889
  if (typeof b.token !== "string" || typeof b.password !== "string") {
10890
- return jsonResponse16({ error: "Missing required fields: token, password" }, 400);
10890
+ return jsonResponse11({ error: "Missing required fields: token, password" }, 400);
10891
10891
  }
10892
10892
  const result = await resetPassword(b.token, b.password);
10893
10893
  if (!result.success) {
10894
10894
  const status = result.error.code === "INVALID_PASSWORD" ? 400 : 400;
10895
- return jsonResponse16({ error: result.error.message }, status);
10895
+ return jsonResponse11({ error: result.error.message }, status);
10896
10896
  }
10897
10897
  return new Response(null, { status: 204 });
10898
10898
  }
@@ -10927,7 +10927,7 @@ function generateNumericCode2(length) {
10927
10927
  function normalisePhone(phone) {
10928
10928
  return phone.replace(/\s+/g, "");
10929
10929
  }
10930
- function jsonResponse17(body, status = 200) {
10930
+ function jsonResponse12(body, status = 200) {
10931
10931
  return new Response(JSON.stringify(body), {
10932
10932
  status,
10933
10933
  headers: { "Content-Type": "application/json" }
@@ -10999,25 +10999,25 @@ function createPhoneAuthModule(config, db, sessionManager) {
10999
10999
  try {
11000
11000
  body = await request.json();
11001
11001
  } catch {
11002
- return jsonResponse17({ error: "Invalid JSON body" }, 400);
11002
+ return jsonResponse12({ error: "Invalid JSON body" }, 400);
11003
11003
  }
11004
11004
  const b = body;
11005
11005
  if (pathname === "/auth/phone/send-code") {
11006
11006
  if (typeof b.phoneNumber !== "string") {
11007
- return jsonResponse17({ error: "Missing required field: phoneNumber" }, 400);
11007
+ return jsonResponse12({ error: "Missing required field: phoneNumber" }, 400);
11008
11008
  }
11009
11009
  const result = await sendCode(b.phoneNumber);
11010
- return jsonResponse17(result);
11010
+ return jsonResponse12(result);
11011
11011
  }
11012
11012
  if (pathname === "/auth/phone/verify") {
11013
11013
  if (typeof b.phoneNumber !== "string" || typeof b.code !== "string") {
11014
- return jsonResponse17({ error: "Missing required fields: phoneNumber, code" }, 400);
11014
+ return jsonResponse12({ error: "Missing required fields: phoneNumber, code" }, 400);
11015
11015
  }
11016
11016
  const result = await verifyCode(b.phoneNumber, b.code);
11017
11017
  if (!result) {
11018
- return jsonResponse17({ error: "Invalid or expired code" }, 401);
11018
+ return jsonResponse12({ error: "Invalid or expired code" }, 401);
11019
11019
  }
11020
- return jsonResponse17(result);
11020
+ return jsonResponse12(result);
11021
11021
  }
11022
11022
  return null;
11023
11023
  }
@@ -11037,12 +11037,12 @@ async function polarRequest(accessToken, baseUrl, method, path, body) {
11037
11037
  headers,
11038
11038
  body: body !== void 0 ? JSON.stringify(body) : void 0
11039
11039
  });
11040
- const json3 = await response.json();
11040
+ const json2 = await response.json();
11041
11041
  if (!response.ok) {
11042
- const message = json3.detail ?? json3.message ?? `Polar API error: ${response.status}`;
11042
+ const message = json2.detail ?? json2.message ?? `Polar API error: ${response.status}`;
11043
11043
  throw new Error(message);
11044
11044
  }
11045
- return json3;
11045
+ return json2;
11046
11046
  }
11047
11047
  async function verifyWebhookSignature(payload, signatureHeader, webhookSecret) {
11048
11048
  const prefix = "sha256=";
@@ -11265,19 +11265,6 @@ function createPolarModule(config, db) {
11265
11265
  }
11266
11266
 
11267
11267
  // src/auth/polar-plugin.ts
11268
- function json(body, status = 200) {
11269
- return new Response(JSON.stringify(body), {
11270
- status,
11271
- headers: { "Content-Type": "application/json" }
11272
- });
11273
- }
11274
- async function parseBody10(request) {
11275
- try {
11276
- return await request.json();
11277
- } catch {
11278
- return {};
11279
- }
11280
- }
11281
11268
  function polar(config) {
11282
11269
  return {
11283
11270
  id: "kavach-polar",
@@ -11295,13 +11282,14 @@ function polar(config) {
11295
11282
  if (!user) {
11296
11283
  return json({ error: "Authentication required" }, 401);
11297
11284
  }
11298
- const body = await parseBody10(request);
11299
- 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;
11300
11288
  if (!productId) {
11301
11289
  return json({ error: "Missing required field: productId" }, 400);
11302
11290
  }
11303
- const successUrl = typeof body.successUrl === "string" ? body.successUrl : void 0;
11304
- 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;
11305
11293
  try {
11306
11294
  const result = await module.createCheckout(user.id, productId, {
11307
11295
  successUrl,
@@ -12746,13 +12734,13 @@ function scim(config) {
12746
12734
  // src/auth/siwe.ts
12747
12735
  var DEFAULT_NONCE_TTL_SECONDS = 300;
12748
12736
  var SIWE_VERSION = "1";
12749
- function jsonResponse18(body, status = 200) {
12737
+ function jsonResponse13(body, status = 200) {
12750
12738
  return new Response(JSON.stringify(body), {
12751
12739
  status,
12752
12740
  headers: { "Content-Type": "application/json" }
12753
12741
  });
12754
12742
  }
12755
- async function parseBody11(request) {
12743
+ async function parseBody6(request) {
12756
12744
  try {
12757
12745
  return await request.json();
12758
12746
  } catch {
@@ -12887,20 +12875,20 @@ function createSiweModule(config) {
12887
12875
  const { method, pathname } = { method: request.method, pathname: url.pathname };
12888
12876
  if (method === "GET" && pathname.endsWith("/auth/siwe/nonce")) {
12889
12877
  const nonce = await generateNonce();
12890
- return jsonResponse18({ nonce });
12878
+ return jsonResponse13({ nonce });
12891
12879
  }
12892
12880
  if (method === "POST" && pathname.endsWith("/auth/siwe/verify")) {
12893
- const body = await parseBody11(request);
12881
+ const body = await parseBody6(request);
12894
12882
  const message = typeof body.message === "string" ? body.message : null;
12895
12883
  const signature = typeof body.signature === "string" ? body.signature : null;
12896
12884
  if (!message || !signature) {
12897
- return jsonResponse18({ error: "Missing required fields: message, signature" }, 400);
12885
+ return jsonResponse13({ error: "Missing required fields: message, signature" }, 400);
12898
12886
  }
12899
12887
  try {
12900
12888
  const result = await verify(message, signature);
12901
- return jsonResponse18({ address: result.address, chainId: result.chainId });
12889
+ return jsonResponse13({ address: result.address, chainId: result.chainId });
12902
12890
  } catch (err2) {
12903
- return jsonResponse18(
12891
+ return jsonResponse13(
12904
12892
  { error: err2 instanceof Error ? err2.message : "Verification failed" },
12905
12893
  400
12906
12894
  );
@@ -13937,7 +13925,7 @@ function createSsoModule(config, db) {
13937
13925
  const url = new URL(request.url);
13938
13926
  const { pathname } = url;
13939
13927
  const { method } = request;
13940
- const json3 = (data, status = 200) => new Response(JSON.stringify(data), {
13928
+ const json2 = (data, status = 200) => new Response(JSON.stringify(data), {
13941
13929
  status,
13942
13930
  headers: { "Content-Type": "application/json" }
13943
13931
  });
@@ -13946,14 +13934,14 @@ function createSsoModule(config, db) {
13946
13934
  try {
13947
13935
  body = await request.json();
13948
13936
  } catch {
13949
- return json3({ error: "Invalid JSON body" }, 400);
13937
+ return json2({ error: "Invalid JSON body" }, 400);
13950
13938
  }
13951
13939
  const b = body;
13952
13940
  if (typeof b.orgId !== "string" || typeof b.providerId !== "string" || typeof b.type !== "string" || typeof b.domain !== "string") {
13953
- return json3({ error: "Missing required fields: orgId, providerId, type, domain" }, 400);
13941
+ return json2({ error: "Missing required fields: orgId, providerId, type, domain" }, 400);
13954
13942
  }
13955
13943
  if (b.type !== "saml" && b.type !== "oidc") {
13956
- return json3({ error: "type must be 'saml' or 'oidc'" }, 400);
13944
+ return json2({ error: "type must be 'saml' or 'oidc'" }, 400);
13957
13945
  }
13958
13946
  const conn = await createConnection({
13959
13947
  orgId: b.orgId,
@@ -13961,19 +13949,19 @@ function createSsoModule(config, db) {
13961
13949
  type: b.type,
13962
13950
  domain: b.domain
13963
13951
  });
13964
- return json3(conn, 201);
13952
+ return json2(conn, 201);
13965
13953
  }
13966
13954
  const listMatch = /^\/auth\/sso\/connections\/([^/]+)$/.exec(pathname);
13967
13955
  if (method === "GET" && listMatch) {
13968
13956
  const orgId = decodeURIComponent(listMatch[1] ?? "");
13969
13957
  const conns = await listConnections(orgId);
13970
- return json3(conns);
13958
+ return json2(conns);
13971
13959
  }
13972
13960
  const deleteMatch = /^\/auth\/sso\/connections\/([^/]+)$/.exec(pathname);
13973
13961
  if (method === "DELETE" && deleteMatch) {
13974
13962
  const connId = decodeURIComponent(deleteMatch[1] ?? "");
13975
13963
  await removeConnection(connId);
13976
- return json3({ success: true });
13964
+ return json2({ success: true });
13977
13965
  }
13978
13966
  const samlInitMatch = /^\/auth\/sso\/saml\/([^/]+)$/.exec(pathname);
13979
13967
  if (method === "GET" && samlInitMatch) {
@@ -13983,7 +13971,7 @@ function createSsoModule(config, db) {
13983
13971
  const authUrl = await getSamlAuthUrl(connId, relayState);
13984
13972
  return new Response(null, { status: 302, headers: { Location: authUrl } });
13985
13973
  } catch (err2) {
13986
- return json3({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 400);
13974
+ return json2({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 400);
13987
13975
  }
13988
13976
  }
13989
13977
  const samlAcsMatch = /^\/auth\/sso\/saml\/([^/]+)\/acs$/.exec(pathname);
@@ -13996,14 +13984,14 @@ function createSsoModule(config, db) {
13996
13984
  if (typeof val !== "string") throw new Error("Missing SAMLResponse");
13997
13985
  samlResponse = val;
13998
13986
  } catch {
13999
- return json3({ error: "Missing or invalid SAMLResponse" }, 400);
13987
+ return json2({ error: "Missing or invalid SAMLResponse" }, 400);
14000
13988
  }
14001
13989
  try {
14002
13990
  const result = await handleSamlResponse(connId, samlResponse);
14003
- return json3(result);
13991
+ return json2(result);
14004
13992
  } catch (err2) {
14005
13993
  const status = err2 instanceof SsoError && err2.code === SSO_ERROR.RATE_LIMITED ? 429 : 401;
14006
- return json3(
13994
+ return json2(
14007
13995
  {
14008
13996
  error: err2 instanceof Error ? err2.message : "SAML error",
14009
13997
  code: err2 instanceof SsoError ? err2.code : "SAML_ERROR"
@@ -14021,20 +14009,20 @@ function createSsoModule(config, db) {
14021
14009
  const authUrl = await getOidcAuthUrl(connId, state, nonce);
14022
14010
  return new Response(null, { status: 302, headers: { Location: authUrl } });
14023
14011
  } catch (err2) {
14024
- return json3({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 400);
14012
+ return json2({ error: err2 instanceof Error ? err2.message : "Unknown error" }, 400);
14025
14013
  }
14026
14014
  }
14027
14015
  const oidcCbMatch = /^\/auth\/sso\/oidc\/([^/]+)\/callback$/.exec(pathname);
14028
14016
  if (method === "GET" && oidcCbMatch) {
14029
14017
  const connId = decodeURIComponent(oidcCbMatch[1] ?? "");
14030
14018
  const code2 = url.searchParams.get("code");
14031
- if (!code2) return json3({ error: "Missing code parameter" }, 400);
14019
+ if (!code2) return json2({ error: "Missing code parameter" }, 400);
14032
14020
  try {
14033
14021
  const result = await handleOidcCallback(connId, code2);
14034
- return json3(result);
14022
+ return json2(result);
14035
14023
  } catch (err2) {
14036
14024
  const status = err2 instanceof SsoError && err2.code === SSO_ERROR.RATE_LIMITED ? 429 : 401;
14037
- return json3(
14025
+ return json2(
14038
14026
  {
14039
14027
  error: err2 instanceof Error ? err2.message : "OIDC error",
14040
14028
  code: err2 instanceof SsoError ? err2.code : "OIDC_ERROR"
@@ -14135,12 +14123,12 @@ async function stripeRequest(secretKey, apiVersion, method, path, body) {
14135
14123
  headers,
14136
14124
  body: bodyStr
14137
14125
  });
14138
- const json3 = await response.json();
14126
+ const json2 = await response.json();
14139
14127
  if (!response.ok) {
14140
- const message = json3.error?.message ?? `Stripe API error: ${response.status}`;
14128
+ const message = json2.error?.message ?? `Stripe API error: ${response.status}`;
14141
14129
  throw new Error(message);
14142
14130
  }
14143
- return json3;
14131
+ return json2;
14144
14132
  }
14145
14133
  async function verifyWebhookSignature2(payload, signatureHeader, webhookSecret) {
14146
14134
  const parts = {};
@@ -14450,19 +14438,6 @@ function createStripeModule(config, db) {
14450
14438
  }
14451
14439
 
14452
14440
  // src/auth/stripe-plugin.ts
14453
- function json2(body, status = 200) {
14454
- return new Response(JSON.stringify(body), {
14455
- status,
14456
- headers: { "Content-Type": "application/json" }
14457
- });
14458
- }
14459
- async function parseBody12(request) {
14460
- try {
14461
- return await request.json();
14462
- } catch {
14463
- return {};
14464
- }
14465
- }
14466
14441
  function stripe(config) {
14467
14442
  return {
14468
14443
  id: "kavach-stripe",
@@ -14478,17 +14453,18 @@ function stripe(config) {
14478
14453
  async handler(request, endpointCtx) {
14479
14454
  const user = await endpointCtx.getUser(request);
14480
14455
  if (!user) {
14481
- return json2({ error: "Authentication required" }, 401);
14456
+ return json({ error: "Authentication required" }, 401);
14482
14457
  }
14483
- const body = await parseBody12(request);
14484
- 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;
14485
14461
  if (!priceId) {
14486
- return json2({ error: "Missing required field: priceId" }, 400);
14462
+ return json({ error: "Missing required field: priceId" }, 400);
14487
14463
  }
14488
- const successUrl = typeof body.successUrl === "string" ? body.successUrl : void 0;
14489
- const cancelUrl = typeof body.cancelUrl === "string" ? body.cancelUrl : void 0;
14490
- const trialDays = typeof body.trialDays === "number" ? body.trialDays : void 0;
14491
- 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;
14492
14468
  try {
14493
14469
  const result = await module.createCheckoutSession(user.id, priceId, {
14494
14470
  successUrl,
@@ -14496,9 +14472,9 @@ function stripe(config) {
14496
14472
  trialDays,
14497
14473
  metadata
14498
14474
  });
14499
- return json2(result);
14475
+ return json(result);
14500
14476
  } catch (err2) {
14501
- return json2(
14477
+ return json(
14502
14478
  {
14503
14479
  error: err2 instanceof Error ? err2.message : "Failed to create checkout session"
14504
14480
  },
@@ -14517,18 +14493,19 @@ function stripe(config) {
14517
14493
  async handler(request, endpointCtx) {
14518
14494
  const user = await endpointCtx.getUser(request);
14519
14495
  if (!user) {
14520
- return json2({ error: "Authentication required" }, 401);
14496
+ return json({ error: "Authentication required" }, 401);
14521
14497
  }
14522
- const body = await parseBody12(request);
14523
- 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;
14524
14501
  if (!returnUrl) {
14525
- return json2({ error: "Missing required field: returnUrl" }, 400);
14502
+ return json({ error: "Missing required field: returnUrl" }, 400);
14526
14503
  }
14527
14504
  try {
14528
14505
  const result = await module.createPortalSession(user.id, returnUrl);
14529
- return json2(result);
14506
+ return json(result);
14530
14507
  } catch (err2) {
14531
- return json2(
14508
+ return json(
14532
14509
  {
14533
14510
  error: err2 instanceof Error ? err2.message : "Failed to create portal session"
14534
14511
  },
@@ -14547,10 +14524,10 @@ function stripe(config) {
14547
14524
  async handler(request, endpointCtx) {
14548
14525
  const user = await endpointCtx.getUser(request);
14549
14526
  if (!user) {
14550
- return json2({ error: "Authentication required" }, 401);
14527
+ return json({ error: "Authentication required" }, 401);
14551
14528
  }
14552
14529
  const subscription = await module.getSubscription(user.id);
14553
- return json2({ subscription });
14530
+ return json({ subscription });
14554
14531
  }
14555
14532
  });
14556
14533
  ctx.addEndpoint({
@@ -14652,13 +14629,13 @@ async function generateBackupCodes(count) {
14652
14629
  }
14653
14630
  return { plain, hashed };
14654
14631
  }
14655
- function jsonResponse19(body, status = 200) {
14632
+ function jsonResponse14(body, status = 200) {
14656
14633
  return new Response(JSON.stringify(body), {
14657
14634
  status,
14658
14635
  headers: { "Content-Type": "application/json" }
14659
14636
  });
14660
14637
  }
14661
- async function parseBody13(request) {
14638
+ async function parseBody7(request) {
14662
14639
  try {
14663
14640
  return await request.json();
14664
14641
  } catch {
@@ -14756,50 +14733,50 @@ function createTotpModule(config, db) {
14756
14733
  const method = request.method.toUpperCase();
14757
14734
  if (method !== "POST") return null;
14758
14735
  if (path === "/auth/2fa/setup") {
14759
- const body = await parseBody13(request);
14736
+ const body = await parseBody7(request);
14760
14737
  const userId = typeof body.userId === "string" ? body.userId : null;
14761
- if (!userId) return jsonResponse19({ error: "userId required" }, 400);
14738
+ if (!userId) return jsonResponse14({ error: "userId required" }, 400);
14762
14739
  try {
14763
14740
  const result = await setup(userId);
14764
- return jsonResponse19(result);
14741
+ return jsonResponse14(result);
14765
14742
  } catch (err2) {
14766
- return jsonResponse19({ error: err2 instanceof Error ? err2.message : "Setup failed" }, 500);
14743
+ return jsonResponse14({ error: err2 instanceof Error ? err2.message : "Setup failed" }, 500);
14767
14744
  }
14768
14745
  }
14769
14746
  if (path === "/auth/2fa/enable") {
14770
- const body = await parseBody13(request);
14747
+ const body = await parseBody7(request);
14771
14748
  const userId = typeof body.userId === "string" ? body.userId : null;
14772
14749
  const code2 = typeof body.code === "string" ? body.code : null;
14773
- if (!userId || !code2) return jsonResponse19({ error: "userId and code required" }, 400);
14750
+ if (!userId || !code2) return jsonResponse14({ error: "userId and code required" }, 400);
14774
14751
  const result = await enable(userId, code2);
14775
- return jsonResponse19(result);
14752
+ return jsonResponse14(result);
14776
14753
  }
14777
14754
  if (path === "/auth/2fa/verify") {
14778
- const body = await parseBody13(request);
14755
+ const body = await parseBody7(request);
14779
14756
  const userId = typeof body.userId === "string" ? body.userId : null;
14780
14757
  const code2 = typeof body.code === "string" ? body.code : null;
14781
- if (!userId || !code2) return jsonResponse19({ error: "userId and code required" }, 400);
14758
+ if (!userId || !code2) return jsonResponse14({ error: "userId and code required" }, 400);
14782
14759
  const result = await verify(userId, code2);
14783
- return jsonResponse19(result);
14760
+ return jsonResponse14(result);
14784
14761
  }
14785
14762
  if (path === "/auth/2fa/disable") {
14786
- const body = await parseBody13(request);
14763
+ const body = await parseBody7(request);
14787
14764
  const userId = typeof body.userId === "string" ? body.userId : null;
14788
14765
  const code2 = typeof body.code === "string" ? body.code : null;
14789
- if (!userId || !code2) return jsonResponse19({ error: "userId and code required" }, 400);
14766
+ if (!userId || !code2) return jsonResponse14({ error: "userId and code required" }, 400);
14790
14767
  const result = await disable(userId, code2);
14791
- return jsonResponse19(result);
14768
+ return jsonResponse14(result);
14792
14769
  }
14793
14770
  if (path === "/auth/2fa/backup-codes") {
14794
- const body = await parseBody13(request);
14771
+ const body = await parseBody7(request);
14795
14772
  const userId = typeof body.userId === "string" ? body.userId : null;
14796
14773
  const code2 = typeof body.code === "string" ? body.code : null;
14797
- if (!userId || !code2) return jsonResponse19({ error: "userId and code required" }, 400);
14774
+ if (!userId || !code2) return jsonResponse14({ error: "userId and code required" }, 400);
14798
14775
  try {
14799
14776
  const result = await regenerateBackupCodes(userId, code2);
14800
- return jsonResponse19(result);
14777
+ return jsonResponse14(result);
14801
14778
  } catch (err2) {
14802
- return jsonResponse19(
14779
+ return jsonResponse14(
14803
14780
  { error: err2 instanceof Error ? err2.message : "Failed to regenerate codes" },
14804
14781
  400
14805
14782
  );
@@ -14819,13 +14796,13 @@ function createTotpModule(config, db) {
14819
14796
  }
14820
14797
 
14821
14798
  // src/auth/totp-plugin.ts
14822
- function jsonResponse20(body, status = 200) {
14799
+ function jsonResponse15(body, status = 200) {
14823
14800
  return new Response(JSON.stringify(body), {
14824
14801
  status,
14825
14802
  headers: { "Content-Type": "application/json" }
14826
14803
  });
14827
14804
  }
14828
- async function parseBody14(request) {
14805
+ async function parseBody8(request) {
14829
14806
  try {
14830
14807
  return await request.json();
14831
14808
  } catch {
@@ -14847,13 +14824,13 @@ function twoFactor(config) {
14847
14824
  async handler(request, endpointCtx) {
14848
14825
  const user = await endpointCtx.getUser(request);
14849
14826
  if (!user) {
14850
- return jsonResponse20({ error: "Authentication required" }, 401);
14827
+ return jsonResponse15({ error: "Authentication required" }, 401);
14851
14828
  }
14852
14829
  try {
14853
14830
  const setup = await module.setup(user.id);
14854
- return jsonResponse20(setup);
14831
+ return jsonResponse15(setup);
14855
14832
  } catch (err2) {
14856
- return jsonResponse20(
14833
+ return jsonResponse15(
14857
14834
  { error: err2 instanceof Error ? err2.message : "Enrollment failed" },
14858
14835
  500
14859
14836
  );
@@ -14870,23 +14847,23 @@ function twoFactor(config) {
14870
14847
  async handler(request, endpointCtx) {
14871
14848
  const user = await endpointCtx.getUser(request);
14872
14849
  if (!user) {
14873
- return jsonResponse20({ error: "Authentication required" }, 401);
14850
+ return jsonResponse15({ error: "Authentication required" }, 401);
14874
14851
  }
14875
- const body = await parseBody14(request);
14852
+ const body = await parseBody8(request);
14876
14853
  const code2 = typeof body.code === "string" ? body.code : null;
14877
14854
  if (!code2) {
14878
- return jsonResponse20({ error: "Missing required field: code" }, 400);
14855
+ return jsonResponse15({ error: "Missing required field: code" }, 400);
14879
14856
  }
14880
14857
  const enabled = await module.isEnabled(user.id);
14881
14858
  if (!enabled) {
14882
14859
  const result2 = await module.enable(user.id, code2);
14883
14860
  if (!result2.enabled) {
14884
- return jsonResponse20({ error: "Invalid TOTP code" }, 400);
14861
+ return jsonResponse15({ error: "Invalid TOTP code" }, 400);
14885
14862
  }
14886
- return jsonResponse20({ valid: true, activated: true });
14863
+ return jsonResponse15({ valid: true, activated: true });
14887
14864
  }
14888
14865
  const result = await module.verify(user.id, code2);
14889
- return jsonResponse20(result);
14866
+ return jsonResponse15(result);
14890
14867
  }
14891
14868
  });
14892
14869
  ctx.addEndpoint({
@@ -14899,18 +14876,18 @@ function twoFactor(config) {
14899
14876
  async handler(request, endpointCtx) {
14900
14877
  const user = await endpointCtx.getUser(request);
14901
14878
  if (!user) {
14902
- return jsonResponse20({ error: "Authentication required" }, 401);
14879
+ return jsonResponse15({ error: "Authentication required" }, 401);
14903
14880
  }
14904
- const body = await parseBody14(request);
14881
+ const body = await parseBody8(request);
14905
14882
  const code2 = typeof body.code === "string" ? body.code : null;
14906
14883
  if (!code2) {
14907
- return jsonResponse20({ error: "Missing required field: code" }, 400);
14884
+ return jsonResponse15({ error: "Missing required field: code" }, 400);
14908
14885
  }
14909
14886
  const result = await module.disable(user.id, code2);
14910
14887
  if (!result.disabled) {
14911
- return jsonResponse20({ error: "Invalid TOTP code" }, 400);
14888
+ return jsonResponse15({ error: "Invalid TOTP code" }, 400);
14912
14889
  }
14913
- return jsonResponse20(result);
14890
+ return jsonResponse15(result);
14914
14891
  }
14915
14892
  });
14916
14893
  ctx.addEndpoint({
@@ -14923,10 +14900,10 @@ function twoFactor(config) {
14923
14900
  async handler(request, endpointCtx) {
14924
14901
  const user = await endpointCtx.getUser(request);
14925
14902
  if (!user) {
14926
- return jsonResponse20({ error: "Authentication required" }, 401);
14903
+ return jsonResponse15({ error: "Authentication required" }, 401);
14927
14904
  }
14928
14905
  const enabled = await module.isEnabled(user.id);
14929
- return jsonResponse20({ enabled });
14906
+ return jsonResponse15({ enabled });
14930
14907
  }
14931
14908
  });
14932
14909
  ctx.addEndpoint({
@@ -14939,18 +14916,18 @@ function twoFactor(config) {
14939
14916
  async handler(request, endpointCtx) {
14940
14917
  const user = await endpointCtx.getUser(request);
14941
14918
  if (!user) {
14942
- return jsonResponse20({ error: "Authentication required" }, 401);
14919
+ return jsonResponse15({ error: "Authentication required" }, 401);
14943
14920
  }
14944
- const body = await parseBody14(request);
14921
+ const body = await parseBody8(request);
14945
14922
  const code2 = typeof body.code === "string" ? body.code : null;
14946
14923
  if (!code2) {
14947
- return jsonResponse20({ error: "Missing required field: code" }, 400);
14924
+ return jsonResponse15({ error: "Missing required field: code" }, 400);
14948
14925
  }
14949
14926
  try {
14950
14927
  const result = await module.regenerateBackupCodes(user.id, code2);
14951
- return jsonResponse20(result);
14928
+ return jsonResponse15(result);
14952
14929
  } catch (err2) {
14953
- return jsonResponse20(
14930
+ return jsonResponse15(
14954
14931
  { error: err2 instanceof Error ? err2.message : "Failed to regenerate backup codes" },
14955
14932
  400
14956
14933
  );
@@ -15069,7 +15046,7 @@ async function hashPassword(password) {
15069
15046
  async function verifyPassword(stored, candidate) {
15070
15047
  return pbkdf2Verify(candidate, stored);
15071
15048
  }
15072
- function jsonResponse21(body, status = 200) {
15049
+ function jsonResponse16(body, status = 200) {
15073
15050
  return new Response(JSON.stringify(body), {
15074
15051
  status,
15075
15052
  headers: { "Content-Type": "application/json" }
@@ -15193,12 +15170,12 @@ function createUsernameAuthModule(config, db, sessionManager) {
15193
15170
  try {
15194
15171
  body = await request.json();
15195
15172
  } catch {
15196
- return jsonResponse21({ error: "Invalid JSON body" }, 400);
15173
+ return jsonResponse16({ error: "Invalid JSON body" }, 400);
15197
15174
  }
15198
15175
  const b = body;
15199
15176
  if (pathname === "/auth/username/sign-up") {
15200
15177
  if (typeof b.username !== "string" || typeof b.password !== "string") {
15201
- return jsonResponse21({ error: "Missing required fields: username, password" }, 400);
15178
+ return jsonResponse16({ error: "Missing required fields: username, password" }, 400);
15202
15179
  }
15203
15180
  try {
15204
15181
  const result = await signUp({
@@ -15206,21 +15183,21 @@ function createUsernameAuthModule(config, db, sessionManager) {
15206
15183
  password: b.password,
15207
15184
  name: typeof b.name === "string" ? b.name : void 0
15208
15185
  });
15209
- return jsonResponse21(result, 201);
15186
+ return jsonResponse16(result, 201);
15210
15187
  } catch (err2) {
15211
- 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);
15212
15189
  }
15213
15190
  }
15214
15191
  if (pathname === "/auth/username/sign-in") {
15215
15192
  if (typeof b.username !== "string" || typeof b.password !== "string") {
15216
- return jsonResponse21({ error: "Missing required fields: username, password" }, 400);
15193
+ return jsonResponse16({ error: "Missing required fields: username, password" }, 400);
15217
15194
  }
15218
15195
  try {
15219
15196
  const result = await signIn({ username: b.username, password: b.password });
15220
- return jsonResponse21(result);
15197
+ return jsonResponse16(result);
15221
15198
  } catch (err2) {
15222
15199
  if (err2 instanceof Error && err2.message === "Password reset required") {
15223
- return jsonResponse21(
15200
+ return jsonResponse16(
15224
15201
  {
15225
15202
  error: {
15226
15203
  code: "PASSWORD_RESET_REQUIRED",
@@ -15230,21 +15207,21 @@ function createUsernameAuthModule(config, db, sessionManager) {
15230
15207
  403
15231
15208
  );
15232
15209
  }
15233
- return jsonResponse21({ error: "Invalid username or password" }, 401);
15210
+ return jsonResponse16({ error: "Invalid username or password" }, 401);
15234
15211
  }
15235
15212
  }
15236
15213
  if (pathname === "/auth/username/change-password") {
15237
15214
  if (typeof b.userId !== "string" || typeof b.current !== "string" || typeof b.newPassword !== "string") {
15238
- return jsonResponse21(
15215
+ return jsonResponse16(
15239
15216
  { error: "Missing required fields: userId, current, newPassword" },
15240
15217
  400
15241
15218
  );
15242
15219
  }
15243
15220
  try {
15244
15221
  const result = await changePassword(b.userId, b.current, b.newPassword);
15245
- return jsonResponse21(result);
15222
+ return jsonResponse16(result);
15246
15223
  } catch (err2) {
15247
- return jsonResponse21(
15224
+ return jsonResponse16(
15248
15225
  { error: err2 instanceof Error ? err2.message : "Change password failed" },
15249
15226
  400
15250
15227
  );
@@ -15252,13 +15229,13 @@ function createUsernameAuthModule(config, db, sessionManager) {
15252
15229
  }
15253
15230
  if (pathname === "/auth/username/change-username") {
15254
15231
  if (typeof b.userId !== "string" || typeof b.newUsername !== "string") {
15255
- return jsonResponse21({ error: "Missing required fields: userId, newUsername" }, 400);
15232
+ return jsonResponse16({ error: "Missing required fields: userId, newUsername" }, 400);
15256
15233
  }
15257
15234
  try {
15258
15235
  const result = await changeUsername(b.userId, b.newUsername);
15259
- return jsonResponse21(result);
15236
+ return jsonResponse16(result);
15260
15237
  } catch (err2) {
15261
- return jsonResponse21(
15238
+ return jsonResponse16(
15262
15239
  { error: err2 instanceof Error ? err2.message : "Change username failed" },
15263
15240
  400
15264
15241
  );
@@ -15440,7 +15417,7 @@ function buildStatements(provider) {
15440
15417
  const isMysql = provider === "mysql";
15441
15418
  const ts = isPostgres ? "TIMESTAMPTZ" : isMysql ? "DATETIME(3)" : "INTEGER";
15442
15419
  const tsNull = ts;
15443
- const json3 = isPostgres ? "JSONB" : isMysql ? "JSON" : "TEXT";
15420
+ const json2 = isPostgres ? "JSONB" : isMysql ? "JSON" : "TEXT";
15444
15421
  const bool = isPostgres ? "BOOLEAN" : isMysql ? "TINYINT(1)" : "INTEGER";
15445
15422
  const ifne = "IF NOT EXISTS";
15446
15423
  return [
@@ -15454,7 +15431,7 @@ function buildStatements(provider) {
15454
15431
  name TEXT,
15455
15432
  external_id TEXT,
15456
15433
  external_provider TEXT,
15457
- metadata ${json3},
15434
+ metadata ${json2},
15458
15435
  banned ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
15459
15436
  ban_reason TEXT,
15460
15437
  ban_expires_at ${tsNull},
@@ -15482,7 +15459,7 @@ function buildStatements(provider) {
15482
15459
  id TEXT NOT NULL PRIMARY KEY,
15483
15460
  name TEXT NOT NULL,
15484
15461
  slug TEXT NOT NULL UNIQUE,
15485
- settings ${json3},
15462
+ settings ${json2},
15486
15463
  status TEXT NOT NULL DEFAULT 'active',
15487
15464
  created_at ${ts} NOT NULL,
15488
15465
  updated_at ${ts} NOT NULL
@@ -15501,7 +15478,7 @@ function buildStatements(provider) {
15501
15478
  token_prefix TEXT NOT NULL,
15502
15479
  expires_at ${tsNull},
15503
15480
  last_active_at ${tsNull},
15504
- metadata ${json3},
15481
+ metadata ${json2},
15505
15482
  created_at ${ts} NOT NULL,
15506
15483
  updated_at ${ts} NOT NULL
15507
15484
  )`,
@@ -15512,8 +15489,8 @@ function buildStatements(provider) {
15512
15489
  id TEXT NOT NULL PRIMARY KEY,
15513
15490
  agent_id TEXT NOT NULL REFERENCES kavach_agents(id) ON DELETE CASCADE,
15514
15491
  resource TEXT NOT NULL,
15515
- actions ${json3} NOT NULL,
15516
- constraints ${json3},
15492
+ actions ${json2} NOT NULL,
15493
+ constraints ${json2},
15517
15494
  created_at ${ts} NOT NULL
15518
15495
  )`,
15519
15496
  // ------------------------------------------------------------------
@@ -15523,7 +15500,7 @@ function buildStatements(provider) {
15523
15500
  id TEXT NOT NULL PRIMARY KEY,
15524
15501
  from_agent_id TEXT NOT NULL REFERENCES kavach_agents(id),
15525
15502
  to_agent_id TEXT NOT NULL REFERENCES kavach_agents(id),
15526
- permissions ${json3} NOT NULL,
15503
+ permissions ${json2} NOT NULL,
15527
15504
  depth INTEGER NOT NULL DEFAULT 1,
15528
15505
  max_depth INTEGER NOT NULL DEFAULT 3,
15529
15506
  status TEXT NOT NULL DEFAULT 'active',
@@ -15539,7 +15516,7 @@ function buildStatements(provider) {
15539
15516
  user_id TEXT NOT NULL REFERENCES kavach_users(id),
15540
15517
  action TEXT NOT NULL,
15541
15518
  resource TEXT NOT NULL,
15542
- parameters ${json3},
15519
+ parameters ${json2},
15543
15520
  result TEXT NOT NULL,
15544
15521
  reason TEXT,
15545
15522
  duration_ms INTEGER NOT NULL,
@@ -15565,7 +15542,7 @@ function buildStatements(provider) {
15565
15542
  id TEXT NOT NULL PRIMARY KEY,
15566
15543
  name TEXT NOT NULL,
15567
15544
  endpoint TEXT NOT NULL UNIQUE,
15568
- tools ${json3} NOT NULL,
15545
+ tools ${json2} NOT NULL,
15569
15546
  auth_required ${bool} NOT NULL DEFAULT ${isPostgres ? "TRUE" : "1"},
15570
15547
  rate_limit_rpm INTEGER,
15571
15548
  status TEXT NOT NULL DEFAULT 'active',
@@ -15579,7 +15556,7 @@ function buildStatements(provider) {
15579
15556
  id TEXT NOT NULL PRIMARY KEY,
15580
15557
  user_id TEXT NOT NULL REFERENCES kavach_users(id),
15581
15558
  expires_at ${ts} NOT NULL,
15582
- metadata ${json3},
15559
+ metadata ${json2},
15583
15560
  created_at ${ts} NOT NULL
15584
15561
  )`,
15585
15562
  // ------------------------------------------------------------------
@@ -15591,13 +15568,13 @@ function buildStatements(provider) {
15591
15568
  client_secret TEXT,
15592
15569
  client_name TEXT,
15593
15570
  client_uri TEXT,
15594
- redirect_uris ${json3} NOT NULL,
15595
- grant_types ${json3} NOT NULL,
15596
- response_types ${json3} NOT NULL,
15571
+ redirect_uris ${json2} NOT NULL,
15572
+ grant_types ${json2} NOT NULL,
15573
+ response_types ${json2} NOT NULL,
15597
15574
  token_endpoint_auth_method TEXT NOT NULL DEFAULT 'client_secret_basic',
15598
15575
  type TEXT NOT NULL DEFAULT 'confidential',
15599
15576
  disabled ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
15600
- metadata ${json3},
15577
+ metadata ${json2},
15601
15578
  created_at ${ts} NOT NULL,
15602
15579
  updated_at ${ts} NOT NULL
15603
15580
  )`,
@@ -15665,8 +15642,8 @@ function buildStatements(provider) {
15665
15642
  agent_id TEXT REFERENCES kavach_agents(id) ON DELETE CASCADE,
15666
15643
  user_id TEXT REFERENCES kavach_users(id),
15667
15644
  tenant_id TEXT REFERENCES kavach_tenants(id),
15668
- limits ${json3} NOT NULL,
15669
- current_usage ${json3} NOT NULL,
15645
+ limits ${json2} NOT NULL,
15646
+ current_usage ${json2} NOT NULL,
15670
15647
  action TEXT NOT NULL DEFAULT 'warn',
15671
15648
  status TEXT NOT NULL DEFAULT 'active',
15672
15649
  created_at ${ts} NOT NULL
@@ -15680,11 +15657,11 @@ function buildStatements(provider) {
15680
15657
  name TEXT NOT NULL,
15681
15658
  description TEXT,
15682
15659
  version TEXT NOT NULL,
15683
- protocols ${json3} NOT NULL,
15684
- capabilities ${json3} NOT NULL,
15685
- auth_requirements ${json3} NOT NULL,
15660
+ protocols ${json2} NOT NULL,
15661
+ capabilities ${json2} NOT NULL,
15662
+ auth_requirements ${json2} NOT NULL,
15686
15663
  endpoint TEXT,
15687
- metadata ${json3},
15664
+ metadata ${json2},
15688
15665
  created_at ${ts} NOT NULL,
15689
15666
  updated_at ${ts} NOT NULL
15690
15667
  )`,
@@ -15697,7 +15674,7 @@ function buildStatements(provider) {
15697
15674
  user_id TEXT NOT NULL REFERENCES kavach_users(id),
15698
15675
  action TEXT NOT NULL,
15699
15676
  resource TEXT NOT NULL,
15700
- arguments ${json3},
15677
+ arguments ${json2},
15701
15678
  status TEXT NOT NULL DEFAULT 'pending',
15702
15679
  expires_at ${ts} NOT NULL,
15703
15680
  responded_at ${tsNull},
@@ -15711,7 +15688,7 @@ function buildStatements(provider) {
15711
15688
  agent_id TEXT NOT NULL PRIMARY KEY REFERENCES kavach_agents(id) ON DELETE CASCADE,
15712
15689
  score INTEGER NOT NULL,
15713
15690
  level TEXT NOT NULL,
15714
- factors ${json3} NOT NULL,
15691
+ factors ${json2} NOT NULL,
15715
15692
  computed_at ${ts} NOT NULL
15716
15693
  )`,
15717
15694
  // ------------------------------------------------------------------
@@ -15722,7 +15699,7 @@ function buildStatements(provider) {
15722
15699
  name TEXT NOT NULL,
15723
15700
  slug TEXT NOT NULL UNIQUE,
15724
15701
  owner_id TEXT NOT NULL REFERENCES kavach_users(id),
15725
- metadata ${json3},
15702
+ metadata ${json2},
15726
15703
  created_at ${ts} NOT NULL,
15727
15704
  updated_at ${ts} NOT NULL
15728
15705
  )`,
@@ -15757,7 +15734,7 @@ function buildStatements(provider) {
15757
15734
  id TEXT NOT NULL PRIMARY KEY,
15758
15735
  org_id TEXT NOT NULL REFERENCES kavach_organizations(id) ON DELETE CASCADE,
15759
15736
  name TEXT NOT NULL,
15760
- permissions ${json3} NOT NULL,
15737
+ permissions ${json2} NOT NULL,
15761
15738
  UNIQUE(org_id, name)
15762
15739
  )`,
15763
15740
  // ------------------------------------------------------------------
@@ -15793,7 +15770,7 @@ function buildStatements(provider) {
15793
15770
  token_hash TEXT NOT NULL UNIQUE,
15794
15771
  purpose TEXT NOT NULL,
15795
15772
  identifier TEXT NOT NULL,
15796
- metadata ${json3},
15773
+ metadata ${json2},
15797
15774
  used ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
15798
15775
  expires_at ${ts} NOT NULL,
15799
15776
  created_at ${ts} NOT NULL
@@ -15838,7 +15815,7 @@ function buildStatements(provider) {
15838
15815
  user_id TEXT NOT NULL PRIMARY KEY REFERENCES kavach_users(id),
15839
15816
  secret TEXT NOT NULL,
15840
15817
  enabled ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
15841
- backup_codes ${json3} NOT NULL,
15818
+ backup_codes ${json2} NOT NULL,
15842
15819
  created_at ${ts} NOT NULL,
15843
15820
  updated_at ${ts} NOT NULL
15844
15821
  )`,
@@ -15863,7 +15840,7 @@ function buildStatements(provider) {
15863
15840
  name TEXT NOT NULL,
15864
15841
  key_hash TEXT NOT NULL,
15865
15842
  key_prefix TEXT NOT NULL,
15866
- permissions ${json3} NOT NULL,
15843
+ permissions ${json2} NOT NULL,
15867
15844
  expires_at ${tsNull},
15868
15845
  last_used_at ${tsNull},
15869
15846
  created_at ${ts} NOT NULL
@@ -15922,10 +15899,10 @@ function buildStatements(provider) {
15922
15899
  client_id TEXT NOT NULL UNIQUE,
15923
15900
  client_secret_hash TEXT NOT NULL,
15924
15901
  client_name TEXT NOT NULL,
15925
- redirect_uris ${json3} NOT NULL,
15926
- grant_types ${json3} NOT NULL,
15927
- response_types ${json3} NOT NULL,
15928
- 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,
15929
15906
  token_endpoint_auth_method TEXT NOT NULL DEFAULT 'client_secret_post',
15930
15907
  created_at ${ts} NOT NULL,
15931
15908
  updated_at ${ts} NOT NULL
@@ -15971,7 +15948,7 @@ function buildStatements(provider) {
15971
15948
  output_tokens INTEGER,
15972
15949
  cost_micros INTEGER NOT NULL,
15973
15950
  currency TEXT NOT NULL DEFAULT 'USD',
15974
- metadata ${json3},
15951
+ metadata ${json2},
15975
15952
  delegation_chain_id TEXT,
15976
15953
  recorded_at ${ts} NOT NULL
15977
15954
  )`,
@@ -16019,7 +15996,7 @@ function buildStatements(provider) {
16019
15996
  id TEXT NOT NULL PRIMARY KEY,
16020
15997
  type TEXT NOT NULL,
16021
15998
  timestamp ${ts} NOT NULL,
16022
- data ${json3} NOT NULL,
15999
+ data ${json2} NOT NULL,
16023
16000
  agent_id TEXT,
16024
16001
  user_id TEXT
16025
16002
  )`,
@@ -16080,7 +16057,7 @@ function buildStatements(provider) {
16080
16057
  source_instance_id TEXT NOT NULL,
16081
16058
  target_instance_id TEXT,
16082
16059
  direction TEXT NOT NULL,
16083
- permissions ${json3} NOT NULL,
16060
+ permissions ${json2} NOT NULL,
16084
16061
  trust_score INTEGER,
16085
16062
  expires_at ${ts} NOT NULL,
16086
16063
  created_at ${ts} NOT NULL
@@ -17398,6 +17375,18 @@ function matchPath(pattern, pathname) {
17398
17375
  return params;
17399
17376
  }
17400
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
+ }
17401
17390
  return {
17402
17391
  async handle(request, basePath, endpointCtx) {
17403
17392
  const url = new URL(request.url);
@@ -17417,6 +17406,20 @@ function createPluginRouter(endpoints) {
17417
17406
  if (endpoint.method !== method) continue;
17418
17407
  const params = matchPath(endpoint.path, pathname);
17419
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
+ }
17420
17423
  const enrichedUrl = new URL(request.url);
17421
17424
  for (const [key, value] of Object.entries(params)) {
17422
17425
  enrichedUrl.searchParams.set(`_param_${key}`, value);
@@ -17474,7 +17477,7 @@ async function runMigrations(db, provider, statements) {
17474
17477
  }
17475
17478
  throw new Error(`runMigrations: unsupported provider "${provider}"`);
17476
17479
  }
17477
- async function initializePlugins(plugins, db, config) {
17480
+ async function initializePlugins(plugins, db, config, sessionManager) {
17478
17481
  const registry = {
17479
17482
  endpoints: [],
17480
17483
  migrations: [],
@@ -17491,6 +17494,7 @@ async function initializePlugins(plugins, db, config) {
17491
17494
  const ctx = {
17492
17495
  db,
17493
17496
  config,
17497
+ sessionManager,
17494
17498
  addEndpoint(endpoint) {
17495
17499
  registry.endpoints.push(endpoint);
17496
17500
  },
@@ -17731,8 +17735,8 @@ var DEFAULT_EXCLUDE_PATHS = [
17731
17735
  var encoder = new TextEncoder();
17732
17736
  var decoder = new TextDecoder();
17733
17737
  function encodeState2(state) {
17734
- const json3 = JSON.stringify(state);
17735
- const bytes = encoder.encode(json3);
17738
+ const json2 = JSON.stringify(state);
17739
+ const bytes = encoder.encode(json2);
17736
17740
  let binary = "";
17737
17741
  for (let i = 0; i < bytes.length; i++) {
17738
17742
  binary += String.fromCharCode(bytes[i]);
@@ -17750,8 +17754,8 @@ function decodeState(encoded) {
17750
17754
  for (let i = 0; i < binary.length; i++) {
17751
17755
  bytes[i] = binary.charCodeAt(i);
17752
17756
  }
17753
- const json3 = decoder.decode(bytes);
17754
- const parsed = JSON.parse(json3);
17757
+ const json2 = decoder.decode(bytes);
17758
+ const parsed = JSON.parse(json2);
17755
17759
  if (!isValidChainState(parsed)) return null;
17756
17760
  return parsed;
17757
17761
  } catch {
@@ -17823,7 +17827,7 @@ function createRedirectChain(config) {
17823
17827
  if (cookieOpts.domain) parts.push(`Domain=${cookieOpts.domain}`);
17824
17828
  return parts.join("; ");
17825
17829
  }
17826
- function buildClearCookie() {
17830
+ function buildClearCookie2() {
17827
17831
  return buildCookieHeader("", 0);
17828
17832
  }
17829
17833
  function serializeAndSetCookie(state) {
@@ -17933,7 +17937,7 @@ function createRedirectChain(config) {
17933
17937
  pop(request) {
17934
17938
  const state = parseFromRequest(request);
17935
17939
  if (!state) {
17936
- return { url: defaultPath, done: true, clearCookie: buildClearCookie() };
17940
+ return { url: defaultPath, done: true, clearCookie: buildClearCookie2() };
17937
17941
  }
17938
17942
  if (state.steps.length > 0) {
17939
17943
  const next = state.steps.shift();
@@ -17957,7 +17961,7 @@ function createRedirectChain(config) {
17957
17961
  return {
17958
17962
  url,
17959
17963
  done: true,
17960
- clearCookie: buildClearCookie()
17964
+ clearCookie: buildClearCookie2()
17961
17965
  };
17962
17966
  },
17963
17967
  peek(request) {
@@ -17983,7 +17987,7 @@ function createRedirectChain(config) {
17983
17987
  },
17984
17988
  clear() {
17985
17989
  currentState = null;
17986
- return buildClearCookie();
17990
+ return buildClearCookie2();
17987
17991
  },
17988
17992
  parse(request) {
17989
17993
  return parseFromRequest(request);
@@ -18316,12 +18320,33 @@ async function createKavach(config) {
18316
18320
  const captchaModule = config.captcha ? createCaptchaModule(config.captcha) : null;
18317
18321
  const redirectChain = createRedirectChain(config.redirects);
18318
18322
  const webhookModule = config.webhooks && config.webhooks.length > 0 ? createWebhookModule(config.webhooks) : null;
18319
- const pluginRegistry = await initializePlugins(config.plugins ?? [], db, config);
18323
+ const pluginRegistry = await initializePlugins(config.plugins ?? [], db, config, sessionManager);
18320
18324
  const endpointCtx = {
18321
18325
  db,
18322
18326
  async getUser(request) {
18323
- if (!authAdapter) return null;
18324
- 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;
18325
18350
  },
18326
18351
  async getSession(token) {
18327
18352
  if (!sessionManager) return null;
@@ -18329,6 +18354,46 @@ async function createKavach(config) {
18329
18354
  }
18330
18355
  };
18331
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
+ }
18332
18397
  async function authorize(agentId, request, context) {
18333
18398
  if (hooks.beforeAuthorize) {
18334
18399
  const verdict = await hooks.beforeAuthorize({
@@ -19400,7 +19465,7 @@ function parseCookies2(header) {
19400
19465
  }
19401
19466
  return result;
19402
19467
  }
19403
- function getCookie(header, name) {
19468
+ function getCookie2(header, name) {
19404
19469
  return parseCookies2(header)[name];
19405
19470
  }
19406
19471
  function parseCookiesFromRequest(request) {
@@ -19521,7 +19586,7 @@ function createCookieSessionManager(config, db) {
19521
19586
  ...config.cookieOptions,
19522
19587
  maxAge: maxAgeSecs
19523
19588
  };
19524
- function buildSetCookie(token) {
19589
+ function buildSetCookie2(token) {
19525
19590
  return serializeCookie(sessionName, token, baseCookieOpts);
19526
19591
  }
19527
19592
  function buildDeleteCookie() {
@@ -19530,10 +19595,10 @@ function createCookieSessionManager(config, db) {
19530
19595
  }
19531
19596
  async function createSession(userId, metadata) {
19532
19597
  const { session, token } = await raw.create(userId, metadata);
19533
- return { session, setCookieHeader: buildSetCookie(token) };
19598
+ return { session, setCookieHeader: buildSetCookie2(token) };
19534
19599
  }
19535
19600
  async function validateSession(cookieHeader) {
19536
- const token = getCookie(cookieHeader, sessionName);
19601
+ const token = getCookie2(cookieHeader, sessionName);
19537
19602
  if (!token) {
19538
19603
  return { session: null, refreshCookieHeader: null };
19539
19604
  }
@@ -19559,7 +19624,7 @@ function createCookieSessionManager(config, db) {
19559
19624
  row.userId,
19560
19625
  row.metadata ?? void 0
19561
19626
  );
19562
- return { session: newSession, setCookieHeader: buildSetCookie(newToken) };
19627
+ return { session: newSession, setCookieHeader: buildSetCookie2(newToken) };
19563
19628
  }
19564
19629
  async function revokeSession(sessionId) {
19565
19630
  await raw.revoke(sessionId);
@@ -19903,7 +19968,7 @@ function createSessionRefresher(config) {
19903
19968
  }
19904
19969
  async function handleRequest(request) {
19905
19970
  const cookieHeader = request.headers.get("cookie") ?? "";
19906
- let rawToken = getCookie(cookieHeader, refreshCookieName);
19971
+ let rawToken = getCookie2(cookieHeader, refreshCookieName);
19907
19972
  if (!rawToken) {
19908
19973
  try {
19909
19974
  const body = await request.clone().json();
@@ -20634,6 +20699,6 @@ async function verifyWebhookSignature3(secret, rawBody, signature) {
20634
20699
  return diff === 0;
20635
20700
  }
20636
20701
 
20637
- 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 };
20638
20703
  //# sourceMappingURL=index.js.map
20639
20704
  //# sourceMappingURL=index.js.map