@syncular/server-hono 0.0.6-125 → 0.0.6-135

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.
@@ -21,6 +21,7 @@ import { cors } from 'hono/cors';
21
21
  import { describeRoute, resolver, validator as zValidator } from 'hono-openapi';
22
22
  import { sql } from 'kysely';
23
23
  import { z } from 'zod';
24
+ import { closeUnauthenticatedSocket, parseBearerToken, parseWebSocketAuthToken, } from './live-auth.js';
24
25
  import { ApiKeyTypeSchema, ConsoleApiKeyBulkRevokeRequestSchema, ConsoleApiKeyBulkRevokeResponseSchema, ConsoleApiKeyCreateRequestSchema, ConsoleApiKeyCreateResponseSchema, ConsoleApiKeyRevokeResponseSchema, ConsoleApiKeySchema, ConsoleBlobDeleteResponseSchema, ConsoleBlobListQuerySchema, ConsoleBlobListResponseSchema, ConsoleClearEventsResultSchema, ConsoleClientSchema, ConsoleCommitDetailSchema, ConsoleCommitListItemSchema, ConsoleCompactResultSchema, ConsoleEvictResultSchema, ConsoleHandlerSchema, ConsoleOperationEventSchema, ConsoleOperationsQuerySchema, ConsolePaginatedResponseSchema, ConsolePaginationQuerySchema, ConsolePartitionedPaginationQuerySchema, ConsolePartitionQuerySchema, ConsolePruneEventsResultSchema, ConsolePrunePreviewSchema, ConsolePruneResultSchema, ConsoleRequestEventSchema, ConsoleRequestPayloadSchema, ConsoleTimelineItemSchema, ConsoleTimelineQuerySchema, LatencyQuerySchema, LatencyStatsResponseSchema, SyncStatsSchema, TimeseriesQuerySchema, TimeseriesStatsResponseSchema, } from './schemas.js';
25
26
  /**
26
27
  * Create a simple console event emitter for broadcasting live events.
@@ -345,14 +346,20 @@ export function createConsoleRoutes(options) {
345
346
  }
346
347
  await next();
347
348
  });
348
- // Auth middleware
349
- const requireAuth = async (c) => {
349
+ // Route auth middleware. Keep /events/live exempt to preserve websocket
350
+ // message-based auth handshake fallback when no Authorization header is sent.
351
+ routes.use('*', async (c, next) => {
352
+ if (c.req.method === 'OPTIONS' || c.req.path.endsWith('/events/live')) {
353
+ await next();
354
+ return;
355
+ }
350
356
  const auth = await options.authenticate(c);
351
357
  if (!auth) {
352
- return null;
358
+ return c.json({ error: 'UNAUTHENTICATED' }, 401);
353
359
  }
354
- return auth;
355
- };
360
+ c.set('consoleAuth', auth);
361
+ await next();
362
+ });
356
363
  const requestEventSelectColumns = [
357
364
  'event_id',
358
365
  'partition_id',
@@ -641,16 +648,13 @@ export function createConsoleRoutes(options) {
641
648
  },
642
649
  },
643
650
  }), zValidator('query', ConsolePartitionQuerySchema), async (c) => {
644
- const auth = await requireAuth(c);
645
- if (!auth)
646
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
647
651
  const { partitionId } = c.req.valid('query');
648
652
  const stats = await readSyncStats(options.db, {
649
653
  partitionId,
650
654
  });
651
655
  logSyncEvent({
652
656
  event: 'console.stats',
653
- consoleUserId: auth.consoleUserId,
657
+ consoleUserId: c.var.consoleAuth.consoleUserId,
654
658
  });
655
659
  return c.json(stats, 200);
656
660
  });
@@ -677,9 +681,6 @@ export function createConsoleRoutes(options) {
677
681
  },
678
682
  },
679
683
  }), zValidator('query', TimeseriesQuerySchema), async (c) => {
680
- const auth = await requireAuth(c);
681
- if (!auth)
682
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
683
684
  const { interval, range, partitionId } = c.req.valid('query');
684
685
  const rangeMs = rangeToMs(range);
685
686
  const startTime = new Date(Date.now() - rangeMs);
@@ -838,9 +839,6 @@ export function createConsoleRoutes(options) {
838
839
  },
839
840
  },
840
841
  }), zValidator('query', LatencyQuerySchema), async (c) => {
841
- const auth = await requireAuth(c);
842
- if (!auth)
843
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
844
842
  const { range, partitionId } = c.req.valid('query');
845
843
  const rangeMs = rangeToMs(range);
846
844
  const startTime = new Date(Date.now() - rangeMs);
@@ -929,9 +927,6 @@ export function createConsoleRoutes(options) {
929
927
  },
930
928
  },
931
929
  }), zValidator('query', ConsoleTimelineQuerySchema), async (c) => {
932
- const auth = await requireAuth(c);
933
- if (!auth)
934
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
935
930
  const { limit, offset, view, partitionId, eventType, actorId, clientId, requestId, traceId, table, outcome, search, from, to, } = c.req.valid('query');
936
931
  const items = [];
937
932
  const normalizedSearchTerm = search?.trim().toLowerCase() || null;
@@ -1106,9 +1101,6 @@ export function createConsoleRoutes(options) {
1106
1101
  },
1107
1102
  },
1108
1103
  }), zValidator('query', ConsolePartitionedPaginationQuerySchema), async (c) => {
1109
- const auth = await requireAuth(c);
1110
- if (!auth)
1111
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
1112
1104
  const { limit, offset, partitionId } = c.req.valid('query');
1113
1105
  let query = db
1114
1106
  .selectFrom('sync_commits')
@@ -1188,9 +1180,6 @@ export function createConsoleRoutes(options) {
1188
1180
  },
1189
1181
  },
1190
1182
  }), zValidator('param', commitSeqParamSchema), zValidator('query', commitDetailQuerySchema), async (c) => {
1191
- const auth = await requireAuth(c);
1192
- if (!auth)
1193
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
1194
1183
  const { seq } = c.req.valid('param');
1195
1184
  const { partitionId } = c.req.valid('query');
1196
1185
  let commitQuery = db
@@ -1289,9 +1278,6 @@ export function createConsoleRoutes(options) {
1289
1278
  },
1290
1279
  },
1291
1280
  }), zValidator('query', ConsolePartitionedPaginationQuerySchema), async (c) => {
1292
- const auth = await requireAuth(c);
1293
- if (!auth)
1294
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
1295
1281
  const { limit, offset, partitionId } = c.req.valid('query');
1296
1282
  let clientsQuery = db
1297
1283
  .selectFrom('sync_client_cursors')
@@ -1417,9 +1403,6 @@ export function createConsoleRoutes(options) {
1417
1403
  },
1418
1404
  },
1419
1405
  }), async (c) => {
1420
- const auth = await requireAuth(c);
1421
- if (!auth)
1422
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
1423
1406
  const items = options.handlers.map((handler) => ({
1424
1407
  table: handler.table,
1425
1408
  dependsOn: handler.dependsOn,
@@ -1450,9 +1433,6 @@ export function createConsoleRoutes(options) {
1450
1433
  },
1451
1434
  },
1452
1435
  }), zValidator('query', ConsoleOperationsQuerySchema), async (c) => {
1453
- const auth = await requireAuth(c);
1454
- if (!auth)
1455
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
1456
1436
  const { limit, offset, operationType, partitionId } = c.req.valid('query');
1457
1437
  let query = db
1458
1438
  .selectFrom('sync_operation_events')
@@ -1508,9 +1488,6 @@ export function createConsoleRoutes(options) {
1508
1488
  },
1509
1489
  },
1510
1490
  }), async (c) => {
1511
- const auth = await requireAuth(c);
1512
- if (!auth)
1513
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
1514
1491
  const watermarkCommitSeq = await computePruneWatermarkCommitSeq(options.db, options.prune);
1515
1492
  // Count commits that would be deleted
1516
1493
  const countRow = await db
@@ -1546,9 +1523,6 @@ export function createConsoleRoutes(options) {
1546
1523
  },
1547
1524
  },
1548
1525
  }), async (c) => {
1549
- const auth = await requireAuth(c);
1550
- if (!auth)
1551
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
1552
1526
  const watermarkCommitSeq = await computePruneWatermarkCommitSeq(options.db, options.prune);
1553
1527
  const deletedCommits = await pruneSync(options.db, {
1554
1528
  watermarkCommitSeq,
@@ -1556,13 +1530,13 @@ export function createConsoleRoutes(options) {
1556
1530
  });
1557
1531
  logSyncEvent({
1558
1532
  event: 'console.prune',
1559
- consoleUserId: auth.consoleUserId,
1533
+ consoleUserId: c.var.consoleAuth.consoleUserId,
1560
1534
  deletedCommits,
1561
1535
  watermarkCommitSeq,
1562
1536
  });
1563
1537
  await recordOperationEvent({
1564
1538
  operationType: 'prune',
1565
- consoleUserId: auth.consoleUserId,
1539
+ consoleUserId: c.var.consoleAuth.consoleUserId,
1566
1540
  requestPayload: {
1567
1541
  watermarkCommitSeq,
1568
1542
  keepNewestCommits: options.prune?.keepNewestCommits ?? null,
@@ -1595,9 +1569,6 @@ export function createConsoleRoutes(options) {
1595
1569
  },
1596
1570
  },
1597
1571
  }), async (c) => {
1598
- const auth = await requireAuth(c);
1599
- if (!auth)
1600
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
1601
1572
  const fullHistoryHours = options.compact?.fullHistoryHours ?? 24 * 7;
1602
1573
  const deletedChanges = await compactChanges(options.db, {
1603
1574
  dialect: options.dialect,
@@ -1605,13 +1576,13 @@ export function createConsoleRoutes(options) {
1605
1576
  });
1606
1577
  logSyncEvent({
1607
1578
  event: 'console.compact',
1608
- consoleUserId: auth.consoleUserId,
1579
+ consoleUserId: c.var.consoleAuth.consoleUserId,
1609
1580
  deletedChanges,
1610
1581
  fullHistoryHours,
1611
1582
  });
1612
1583
  await recordOperationEvent({
1613
1584
  operationType: 'compact',
1614
- consoleUserId: auth.consoleUserId,
1585
+ consoleUserId: c.var.consoleAuth.consoleUserId,
1615
1586
  requestPayload: { fullHistoryHours },
1616
1587
  resultPayload: { deletedChanges },
1617
1588
  });
@@ -1658,9 +1629,6 @@ export function createConsoleRoutes(options) {
1658
1629
  },
1659
1630
  },
1660
1631
  }), zValidator('json', NotifyDataChangeRequestSchema), async (c) => {
1661
- const auth = await requireAuth(c);
1662
- if (!auth)
1663
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
1664
1632
  const body = c.req.valid('json');
1665
1633
  const result = await notifyExternalDataChange({
1666
1634
  db: options.db,
@@ -1670,14 +1638,14 @@ export function createConsoleRoutes(options) {
1670
1638
  });
1671
1639
  logSyncEvent({
1672
1640
  event: 'console.notify_data_change',
1673
- consoleUserId: auth.consoleUserId,
1641
+ consoleUserId: c.var.consoleAuth.consoleUserId,
1674
1642
  tables: body.tables,
1675
1643
  commitSeq: result.commitSeq,
1676
1644
  deletedChunks: result.deletedChunks,
1677
1645
  });
1678
1646
  await recordOperationEvent({
1679
1647
  operationType: 'notify_data_change',
1680
- consoleUserId: auth.consoleUserId,
1648
+ consoleUserId: c.var.consoleAuth.consoleUserId,
1681
1649
  partitionId: body.partitionId ?? null,
1682
1650
  requestPayload: {
1683
1651
  tables: body.tables,
@@ -1718,9 +1686,6 @@ export function createConsoleRoutes(options) {
1718
1686
  },
1719
1687
  },
1720
1688
  }), zValidator('param', clientIdParamSchema), zValidator('query', evictClientQuerySchema), async (c) => {
1721
- const auth = await requireAuth(c);
1722
- if (!auth)
1723
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
1724
1689
  const { id: clientId } = c.req.valid('param');
1725
1690
  const { partitionId } = c.req.valid('query');
1726
1691
  let deleteQuery = db
@@ -1733,13 +1698,13 @@ export function createConsoleRoutes(options) {
1733
1698
  const evicted = Number(res?.numDeletedRows ?? 0) > 0;
1734
1699
  logSyncEvent({
1735
1700
  event: 'console.evict_client',
1736
- consoleUserId: auth.consoleUserId,
1701
+ consoleUserId: c.var.consoleAuth.consoleUserId,
1737
1702
  clientId,
1738
1703
  evicted,
1739
1704
  });
1740
1705
  await recordOperationEvent({
1741
1706
  operationType: 'evict_client',
1742
- consoleUserId: auth.consoleUserId,
1707
+ consoleUserId: c.var.consoleAuth.consoleUserId,
1743
1708
  partitionId: partitionId ?? null,
1744
1709
  targetClientId: clientId,
1745
1710
  requestPayload: { clientId, partitionId: partitionId ?? null },
@@ -1771,9 +1736,6 @@ export function createConsoleRoutes(options) {
1771
1736
  },
1772
1737
  },
1773
1738
  }), zValidator('query', eventsQuerySchema), async (c) => {
1774
- const auth = await requireAuth(c);
1775
- if (!auth)
1776
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
1777
1739
  const { limit, offset, partitionId, eventType, actorId, clientId, requestId, traceId, outcome, } = c.req.valid('query');
1778
1740
  let query = db
1779
1741
  .selectFrom('sync_request_events')
@@ -1839,15 +1801,6 @@ export function createConsoleRoutes(options) {
1839
1801
  const upgradeWebSocket = options.websocket.upgradeWebSocket;
1840
1802
  const heartbeatIntervalMs = options.websocket.heartbeatIntervalMs ?? 30000;
1841
1803
  const wsState = new WeakMap();
1842
- const closeUnauthenticated = (ws) => {
1843
- try {
1844
- ws.send(JSON.stringify({ type: 'error', message: 'UNAUTHENTICATED' }));
1845
- }
1846
- catch {
1847
- // ignore send errors
1848
- }
1849
- ws.close(4001, 'Unauthenticated');
1850
- };
1851
1804
  const cleanup = (ws) => {
1852
1805
  const state = wsState.get(ws);
1853
1806
  if (!state)
@@ -1900,6 +1853,7 @@ export function createConsoleRoutes(options) {
1900
1853
  heartbeatInterval: null,
1901
1854
  authTimeout: null,
1902
1855
  isAuthenticated: false,
1856
+ startAuthenticatedSession: null,
1903
1857
  };
1904
1858
  wsState.set(ws, state);
1905
1859
  const startAuthenticatedSession = () => {
@@ -1958,6 +1912,7 @@ export function createConsoleRoutes(options) {
1958
1912
  }, heartbeatIntervalMs);
1959
1913
  state.heartbeatInterval = heartbeatInterval;
1960
1914
  };
1915
+ state.startAuthenticatedSession = startAuthenticatedSession;
1961
1916
  if (initialAuth) {
1962
1917
  startAuthenticatedSession();
1963
1918
  return;
@@ -1967,7 +1922,7 @@ export function createConsoleRoutes(options) {
1967
1922
  if (!current || current.isAuthenticated) {
1968
1923
  return;
1969
1924
  }
1970
- closeUnauthenticated(ws);
1925
+ closeUnauthenticatedSocket(ws);
1971
1926
  cleanup(ws);
1972
1927
  }, 5_000);
1973
1928
  },
@@ -1977,24 +1932,13 @@ export function createConsoleRoutes(options) {
1977
1932
  return;
1978
1933
  }
1979
1934
  if (typeof event.data !== 'string') {
1980
- closeUnauthenticated(ws);
1935
+ closeUnauthenticatedSocket(ws);
1981
1936
  cleanup(ws);
1982
1937
  return;
1983
1938
  }
1984
- let token = '';
1985
- try {
1986
- const parsed = JSON.parse(event.data);
1987
- if (parsed.type === 'auth' &&
1988
- typeof parsed.token === 'string' &&
1989
- parsed.token.trim().length > 0) {
1990
- token = parsed.token;
1991
- }
1992
- }
1993
- catch {
1994
- // Ignore parse errors and close as unauthenticated below.
1995
- }
1939
+ const token = parseWebSocketAuthToken(event.data);
1996
1940
  if (!token) {
1997
- closeUnauthenticated(ws);
1941
+ closeUnauthenticatedSocket(ws);
1998
1942
  cleanup(ws);
1999
1943
  return;
2000
1944
  }
@@ -2004,62 +1948,11 @@ export function createConsoleRoutes(options) {
2004
1948
  return;
2005
1949
  }
2006
1950
  if (!auth) {
2007
- closeUnauthenticated(ws);
1951
+ closeUnauthenticatedSocket(ws);
2008
1952
  cleanup(ws);
2009
1953
  return;
2010
1954
  }
2011
- currentState.isAuthenticated = true;
2012
- if (currentState.authTimeout) {
2013
- clearTimeout(currentState.authTimeout);
2014
- currentState.authTimeout = null;
2015
- }
2016
- const listener = (liveEvent) => {
2017
- if (partitionId) {
2018
- const eventPartitionId = liveEvent.data.partitionId;
2019
- if (typeof eventPartitionId !== 'string' ||
2020
- eventPartitionId !== partitionId) {
2021
- return;
2022
- }
2023
- }
2024
- try {
2025
- ws.send(JSON.stringify(liveEvent));
2026
- }
2027
- catch {
2028
- // Connection closed
2029
- }
2030
- };
2031
- emitter.addListener(listener);
2032
- currentState.listener = listener;
2033
- ws.send(JSON.stringify({
2034
- type: 'connected',
2035
- timestamp: new Date().toISOString(),
2036
- }));
2037
- const replayEvents = emitter.replay({
2038
- since: replaySince,
2039
- limit: replayLimit,
2040
- partitionId,
2041
- });
2042
- for (const replayEvent of replayEvents) {
2043
- try {
2044
- ws.send(JSON.stringify(replayEvent));
2045
- }
2046
- catch {
2047
- // Connection closed
2048
- break;
2049
- }
2050
- }
2051
- const heartbeatInterval = setInterval(() => {
2052
- try {
2053
- ws.send(JSON.stringify({
2054
- type: 'heartbeat',
2055
- timestamp: new Date().toISOString(),
2056
- }));
2057
- }
2058
- catch {
2059
- clearInterval(heartbeatInterval);
2060
- }
2061
- }, heartbeatIntervalMs);
2062
- currentState.heartbeatInterval = heartbeatInterval;
1955
+ currentState.startAuthenticatedSession?.();
2063
1956
  },
2064
1957
  onClose(_event, ws) {
2065
1958
  cleanup(ws);
@@ -2105,9 +1998,6 @@ export function createConsoleRoutes(options) {
2105
1998
  },
2106
1999
  },
2107
2000
  }), zValidator('param', eventIdParamSchema), zValidator('query', eventDetailQuerySchema), async (c) => {
2108
- const auth = await requireAuth(c);
2109
- if (!auth)
2110
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
2111
2001
  const { id: eventId } = c.req.valid('param');
2112
2002
  const { partitionId } = c.req.valid('query');
2113
2003
  let eventQuery = db
@@ -2158,9 +2048,6 @@ export function createConsoleRoutes(options) {
2158
2048
  },
2159
2049
  },
2160
2050
  }), zValidator('param', eventIdParamSchema), zValidator('query', eventDetailQuerySchema), async (c) => {
2161
- const auth = await requireAuth(c);
2162
- if (!auth)
2163
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
2164
2051
  const { id: eventId } = c.req.valid('param');
2165
2052
  const { partitionId } = c.req.valid('query');
2166
2053
  let eventQuery = db
@@ -2225,15 +2112,12 @@ export function createConsoleRoutes(options) {
2225
2112
  },
2226
2113
  },
2227
2114
  }), async (c) => {
2228
- const auth = await requireAuth(c);
2229
- if (!auth)
2230
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
2231
2115
  const res = await db.deleteFrom('sync_request_events').executeTakeFirst();
2232
2116
  const deletedCount = Number(res?.numDeletedRows ?? 0);
2233
2117
  const payloadDeletedCount = await deleteUnreferencedPayloadSnapshots();
2234
2118
  logSyncEvent({
2235
2119
  event: 'console.clear_events',
2236
- consoleUserId: auth.consoleUserId,
2120
+ consoleUserId: c.var.consoleAuth.consoleUserId,
2237
2121
  deletedCount,
2238
2122
  payloadDeletedCount,
2239
2123
  });
@@ -2263,14 +2147,11 @@ export function createConsoleRoutes(options) {
2263
2147
  },
2264
2148
  },
2265
2149
  }), async (c) => {
2266
- const auth = await requireAuth(c);
2267
- if (!auth)
2268
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
2269
2150
  const pruneResult = await runEventsPrune();
2270
2151
  const deletedCount = pruneResult.totalDeleted;
2271
2152
  logSyncEvent({
2272
2153
  event: 'console.prune_events',
2273
- consoleUserId: auth.consoleUserId,
2154
+ consoleUserId: c.var.consoleAuth.consoleUserId,
2274
2155
  deletedCount,
2275
2156
  requestEventsDeleted: pruneResult.requestEventsDeleted,
2276
2157
  operationEventsDeleted: pruneResult.operationEventsDeleted,
@@ -2302,9 +2183,6 @@ export function createConsoleRoutes(options) {
2302
2183
  },
2303
2184
  },
2304
2185
  }), zValidator('query', apiKeysQuerySchema), async (c) => {
2305
- const auth = await requireAuth(c);
2306
- if (!auth)
2307
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
2308
2186
  const { limit, offset, type: keyType, status, expiresWithinDays, } = c.req.valid('query');
2309
2187
  let query = db
2310
2188
  .selectFrom('sync_api_keys')
@@ -2411,9 +2289,6 @@ export function createConsoleRoutes(options) {
2411
2289
  },
2412
2290
  },
2413
2291
  }), zValidator('json', ConsoleApiKeyCreateRequestSchema), async (c) => {
2414
- const auth = await requireAuth(c);
2415
- if (!auth)
2416
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
2417
2292
  const body = c.req.valid('json');
2418
2293
  // Generate key components
2419
2294
  const keyId = generateKeyId();
@@ -2446,7 +2321,7 @@ export function createConsoleRoutes(options) {
2446
2321
  .execute();
2447
2322
  logSyncEvent({
2448
2323
  event: 'console.create_api_key',
2449
- consoleUserId: auth.consoleUserId,
2324
+ consoleUserId: c.var.consoleAuth.consoleUserId,
2450
2325
  keyId,
2451
2326
  keyType: body.keyType,
2452
2327
  });
@@ -2495,9 +2370,6 @@ export function createConsoleRoutes(options) {
2495
2370
  },
2496
2371
  },
2497
2372
  }), zValidator('param', apiKeyIdParamSchema), async (c) => {
2498
- const auth = await requireAuth(c);
2499
- if (!auth)
2500
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
2501
2373
  const { id: keyId } = c.req.valid('param');
2502
2374
  const row = await db
2503
2375
  .selectFrom('sync_api_keys')
@@ -2555,9 +2427,6 @@ export function createConsoleRoutes(options) {
2555
2427
  },
2556
2428
  },
2557
2429
  }), zValidator('param', apiKeyIdParamSchema), async (c) => {
2558
- const auth = await requireAuth(c);
2559
- if (!auth)
2560
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
2561
2430
  const { id: keyId } = c.req.valid('param');
2562
2431
  const now = new Date().toISOString();
2563
2432
  const res = await db
@@ -2569,7 +2438,7 @@ export function createConsoleRoutes(options) {
2569
2438
  const revoked = Number(res?.numUpdatedRows ?? 0) > 0;
2570
2439
  logSyncEvent({
2571
2440
  event: 'console.revoke_api_key',
2572
- consoleUserId: auth.consoleUserId,
2441
+ consoleUserId: c.var.consoleAuth.consoleUserId,
2573
2442
  keyId,
2574
2443
  revoked,
2575
2444
  });
@@ -2604,9 +2473,6 @@ export function createConsoleRoutes(options) {
2604
2473
  },
2605
2474
  },
2606
2475
  }), zValidator('json', ConsoleApiKeyBulkRevokeRequestSchema), async (c) => {
2607
- const auth = await requireAuth(c);
2608
- if (!auth)
2609
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
2610
2476
  const body = c.req.valid('json');
2611
2477
  const keyIds = [...new Set(body.keyIds.map((keyId) => keyId.trim()))]
2612
2478
  .filter((keyId) => keyId.length > 0)
@@ -2657,7 +2523,7 @@ export function createConsoleRoutes(options) {
2657
2523
  };
2658
2524
  logSyncEvent({
2659
2525
  event: 'console.bulk_revoke_api_keys',
2660
- consoleUserId: auth.consoleUserId,
2526
+ consoleUserId: c.var.consoleAuth.consoleUserId,
2661
2527
  requestedCount: response.requestedCount,
2662
2528
  revokedCount: response.revokedCount,
2663
2529
  alreadyRevokedCount: response.alreadyRevokedCount,
@@ -2694,9 +2560,6 @@ export function createConsoleRoutes(options) {
2694
2560
  },
2695
2561
  },
2696
2562
  }), zValidator('param', apiKeyIdParamSchema), async (c) => {
2697
- const auth = await requireAuth(c);
2698
- if (!auth)
2699
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
2700
2563
  const { id: keyId } = c.req.valid('param');
2701
2564
  const now = new Date().toISOString();
2702
2565
  const existingRow = await db
@@ -2739,7 +2602,7 @@ export function createConsoleRoutes(options) {
2739
2602
  .execute();
2740
2603
  logSyncEvent({
2741
2604
  event: 'console.stage_rotate_api_key',
2742
- consoleUserId: auth.consoleUserId,
2605
+ consoleUserId: c.var.consoleAuth.consoleUserId,
2743
2606
  oldKeyId: keyId,
2744
2607
  newKeyId,
2745
2608
  });
@@ -2790,9 +2653,6 @@ export function createConsoleRoutes(options) {
2790
2653
  },
2791
2654
  },
2792
2655
  }), zValidator('param', apiKeyIdParamSchema), async (c) => {
2793
- const auth = await requireAuth(c);
2794
- if (!auth)
2795
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
2796
2656
  const { id: keyId } = c.req.valid('param');
2797
2657
  const now = new Date().toISOString();
2798
2658
  // Get existing key
@@ -2843,7 +2703,7 @@ export function createConsoleRoutes(options) {
2843
2703
  .execute();
2844
2704
  logSyncEvent({
2845
2705
  event: 'console.rotate_api_key',
2846
- consoleUserId: auth.consoleUserId,
2706
+ consoleUserId: c.var.consoleAuth.consoleUserId,
2847
2707
  oldKeyId: keyId,
2848
2708
  newKeyId,
2849
2709
  });
@@ -2889,9 +2749,6 @@ export function createConsoleRoutes(options) {
2889
2749
  },
2890
2750
  },
2891
2751
  }), zValidator('query', ConsoleBlobListQuerySchema), async (c) => {
2892
- const auth = await requireAuth(c);
2893
- if (!auth)
2894
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
2895
2752
  if (!bucket) {
2896
2753
  return c.json({ error: 'BLOB_STORAGE_NOT_CONFIGURED' }, 501);
2897
2754
  }
@@ -2933,9 +2790,6 @@ export function createConsoleRoutes(options) {
2933
2790
  },
2934
2791
  },
2935
2792
  }), async (c) => {
2936
- const auth = await requireAuth(c);
2937
- if (!auth)
2938
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
2939
2793
  if (!bucket) {
2940
2794
  return c.json({ error: 'BLOB_STORAGE_NOT_CONFIGURED' }, 501);
2941
2795
  }
@@ -2974,9 +2828,6 @@ export function createConsoleRoutes(options) {
2974
2828
  },
2975
2829
  },
2976
2830
  }), async (c) => {
2977
- const auth = await requireAuth(c);
2978
- if (!auth)
2979
- return c.json({ error: 'UNAUTHENTICATED' }, 401);
2980
2831
  if (!bucket) {
2981
2832
  return c.json({ error: 'BLOB_STORAGE_NOT_CONFIGURED' }, 501);
2982
2833
  }
@@ -3016,12 +2867,9 @@ export function createTokenAuthenticator(token) {
3016
2867
  return async (c) => {
3017
2868
  if (!expectedToken)
3018
2869
  return null;
3019
- const authHeader = c.req.header('Authorization')?.trim();
3020
- if (authHeader?.startsWith('Bearer ')) {
3021
- const bearerToken = authHeader.slice(7).trim();
3022
- if (bearerToken === expectedToken) {
3023
- return { consoleUserId: 'token' };
3024
- }
2870
+ const bearerToken = parseBearerToken(c.req.header('Authorization'));
2871
+ if (bearerToken === expectedToken) {
2872
+ return { consoleUserId: 'token' };
3025
2873
  }
3026
2874
  return null;
3027
2875
  };