@essentialai/cogent-server 3.4.0 → 3.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/dist/__tests__/helpers.d.ts +5 -2
  2. package/dist/__tests__/helpers.d.ts.map +1 -1
  3. package/dist/__tests__/helpers.js +11 -4
  4. package/dist/__tests__/helpers.js.map +1 -1
  5. package/dist/__tests__/services/session-store-contract.d.ts +17 -0
  6. package/dist/__tests__/services/session-store-contract.d.ts.map +1 -0
  7. package/dist/__tests__/services/session-store-contract.js +186 -0
  8. package/dist/__tests__/services/session-store-contract.js.map +1 -0
  9. package/dist/app.d.ts +9 -0
  10. package/dist/app.d.ts.map +1 -1
  11. package/dist/app.js +18 -2
  12. package/dist/app.js.map +1 -1
  13. package/dist/config.d.ts +14 -0
  14. package/dist/config.d.ts.map +1 -1
  15. package/dist/config.js +44 -0
  16. package/dist/config.js.map +1 -1
  17. package/dist/contract/control-plane-contract.d.ts +93 -0
  18. package/dist/contract/control-plane-contract.d.ts.map +1 -0
  19. package/dist/contract/control-plane-contract.js +72 -0
  20. package/dist/contract/control-plane-contract.js.map +1 -0
  21. package/dist/db/index.d.ts +5 -0
  22. package/dist/db/index.d.ts.map +1 -0
  23. package/dist/db/index.js +3 -0
  24. package/dist/db/index.js.map +1 -0
  25. package/dist/db/migrate-cli.d.ts +2 -0
  26. package/dist/db/migrate-cli.d.ts.map +1 -0
  27. package/dist/db/migrate-cli.js +54 -0
  28. package/dist/db/migrate-cli.js.map +1 -0
  29. package/dist/db/migrate.d.ts +31 -0
  30. package/dist/db/migrate.d.ts.map +1 -0
  31. package/dist/db/migrate.js +98 -0
  32. package/dist/db/migrate.js.map +1 -0
  33. package/dist/db/migrations/0001_init_sessions.down.sql +4 -0
  34. package/dist/db/migrations/0001_init_sessions.up.sql +46 -0
  35. package/dist/db/migrations/0002_org_quotas.down.sql +2 -0
  36. package/dist/db/migrations/0002_org_quotas.up.sql +13 -0
  37. package/dist/db/pool.d.ts +39 -0
  38. package/dist/db/pool.d.ts.map +1 -0
  39. package/dist/db/pool.js +72 -0
  40. package/dist/db/pool.js.map +1 -0
  41. package/dist/index.js +33 -3
  42. package/dist/index.js.map +1 -1
  43. package/dist/middleware/auth.d.ts.map +1 -1
  44. package/dist/middleware/auth.js +32 -0
  45. package/dist/middleware/auth.js.map +1 -1
  46. package/dist/middleware/control-plane-auth.d.ts +17 -0
  47. package/dist/middleware/control-plane-auth.d.ts.map +1 -0
  48. package/dist/middleware/control-plane-auth.js +35 -0
  49. package/dist/middleware/control-plane-auth.js.map +1 -0
  50. package/dist/routes/control-plane.d.ts +20 -0
  51. package/dist/routes/control-plane.d.ts.map +1 -0
  52. package/dist/routes/control-plane.js +122 -0
  53. package/dist/routes/control-plane.js.map +1 -0
  54. package/dist/routes/messages.d.ts.map +1 -1
  55. package/dist/routes/messages.js +18 -0
  56. package/dist/routes/messages.js.map +1 -1
  57. package/dist/routes/poll.js +2 -2
  58. package/dist/routes/poll.js.map +1 -1
  59. package/dist/routes/sessions.d.ts +22 -1
  60. package/dist/routes/sessions.d.ts.map +1 -1
  61. package/dist/routes/sessions.js +99 -13
  62. package/dist/routes/sessions.js.map +1 -1
  63. package/dist/routes/validation-hook.d.ts +31 -0
  64. package/dist/routes/validation-hook.d.ts.map +1 -1
  65. package/dist/routes/validation-hook.js +3 -0
  66. package/dist/routes/validation-hook.js.map +1 -1
  67. package/dist/services/auth-service.d.ts +5 -45
  68. package/dist/services/auth-service.d.ts.map +1 -1
  69. package/dist/services/auth-service.js +5 -60
  70. package/dist/services/auth-service.js.map +1 -1
  71. package/dist/services/connection-manager.d.ts +15 -0
  72. package/dist/services/connection-manager.d.ts.map +1 -1
  73. package/dist/services/connection-manager.js +29 -0
  74. package/dist/services/connection-manager.js.map +1 -1
  75. package/dist/services/join-rate-limiter.d.ts +50 -0
  76. package/dist/services/join-rate-limiter.d.ts.map +1 -0
  77. package/dist/services/join-rate-limiter.js +89 -0
  78. package/dist/services/join-rate-limiter.js.map +1 -0
  79. package/dist/services/obs-log.d.ts +51 -0
  80. package/dist/services/obs-log.d.ts.map +1 -0
  81. package/dist/services/obs-log.js +93 -0
  82. package/dist/services/obs-log.js.map +1 -0
  83. package/dist/services/session-store-memory.d.ts +60 -0
  84. package/dist/services/session-store-memory.d.ts.map +1 -0
  85. package/dist/services/session-store-memory.js +189 -0
  86. package/dist/services/session-store-memory.js.map +1 -0
  87. package/dist/services/session-store-postgres.d.ts +60 -0
  88. package/dist/services/session-store-postgres.d.ts.map +1 -0
  89. package/dist/services/session-store-postgres.js +393 -0
  90. package/dist/services/session-store-postgres.js.map +1 -0
  91. package/dist/services/session-store.d.ts +73 -5
  92. package/dist/services/session-store.d.ts.map +1 -1
  93. package/dist/services/session-store.js +63 -17
  94. package/dist/services/session-store.js.map +1 -1
  95. package/dist/services/stats-service.d.ts.map +1 -1
  96. package/dist/services/stats-service.js +2 -0
  97. package/dist/services/stats-service.js.map +1 -1
  98. package/dist/types.d.ts +13 -0
  99. package/dist/types.d.ts.map +1 -1
  100. package/dist/ui/pages/FaqPage.d.ts.map +1 -1
  101. package/dist/ui/pages/FaqPage.js +7 -5
  102. package/dist/ui/pages/FaqPage.js.map +1 -1
  103. package/dist/ui/pages/LandingPage.d.ts.map +1 -1
  104. package/dist/ui/pages/LandingPage.js +2 -2
  105. package/dist/ui/pages/LandingPage.js.map +1 -1
  106. package/package.json +11 -6
@@ -1,7 +1,31 @@
1
1
  import { Hono } from "hono";
2
2
  import { zValidator } from "@hono/zod-validator";
3
3
  import { BridgeError, ErrorCode, CreateSessionRequestSchema, JoinSessionRequestSchema, generateSessionId, generateSessionLabel, isValidSessionLabel, } from "@essentialai/cogent";
4
- import { validationHook } from "./validation-hook.js";
4
+ import { JoinRateLimiter } from "../services/join-rate-limiter.js";
5
+ import { validationHook, honoSchema } from "./validation-hook.js";
6
+ import { logOrgEvent } from "../services/obs-log.js";
7
+ /**
8
+ * Best-effort client IP for the rate limiter's per-source tier.
9
+ *
10
+ * Prefer `X-Real-IP` (our edge proxy OVERWRITES it with the real peer) and the
11
+ * RIGHTMOST `X-Forwarded-For` entry (the hop our proxy appends) — never the
12
+ * leftmost XFF value, which is attacker-supplied. This is only the UX tier;
13
+ * the spoof-proof guarantee comes from the limiter's channel tier (keyed on the
14
+ * non-spoofable sessionId), so a forged header at worst evades per-IP
15
+ * granularity, not the lockout itself.
16
+ */
17
+ export function clientIp(c) {
18
+ const realIp = c.req.header("x-real-ip")?.trim();
19
+ if (realIp)
20
+ return realIp;
21
+ const xff = c.req.header("x-forwarded-for");
22
+ if (xff) {
23
+ const parts = xff.split(",").map((s) => s.trim()).filter(Boolean);
24
+ if (parts.length > 0)
25
+ return parts[parts.length - 1];
26
+ }
27
+ return "unknown";
28
+ }
5
29
  /**
6
30
  * Create session routes sub-router.
7
31
  *
@@ -9,8 +33,13 @@ import { validationHook } from "./validation-hook.js";
9
33
  * POST /:sessionId/join -> Join an existing session
10
34
  *
11
35
  * Both endpoints are unauthenticated (they issue tokens, not consume them).
36
+ *
37
+ * @param multiTenant When true, Org_ID (the 3rd join credential) is enforced
38
+ * for channels created with one. When false (free relay),
39
+ * Org_ID is ignored entirely and behavior is unchanged.
40
+ * @param rateLimiter Throttles repeated failed joins (brute-force lockout).
12
41
  */
13
- export function createSessionRoutes(sessionStore, authService) {
42
+ export function createSessionRoutes(sessionStore, authService, multiTenant, rateLimiter) {
14
43
  const sessions = new Hono();
15
44
  /**
16
45
  * POST / - Create a new session.
@@ -18,16 +47,26 @@ export function createSessionRoutes(sessionStore, authService) {
18
47
  * Receives { secret, label? }, bcrypt-hashes the secret, generates a bearer
19
48
  * token, creates the session on disk, and returns { sessionId, token, createdAt }.
20
49
  */
21
- sessions.post("/", zValidator("json", CreateSessionRequestSchema, validationHook), async (c) => {
22
- const { secret, label } = c.req.valid("json");
50
+ sessions.post("/", zValidator("json", honoSchema(CreateSessionRequestSchema), validationHook), async (c) => {
51
+ const { secret, label, orgId } = c.req.valid("json");
23
52
  // Generate unique session ID
24
53
  const sessionId = generateSessionId();
25
- // Auto-generate label if not provided, with collision retry
54
+ // On a multi-tenant relay, an Org_ID makes this an Org_ID-gated business
55
+ // channel: persist the bcrypt hash (auth) and a stable SHA-256 scope
56
+ // (label namespacing), never the plaintext. The free relay ignores Org_ID
57
+ // entirely (org stays undefined -> labels stay globally scoped, NFR6).
58
+ const org = multiTenant && orgId
59
+ ? {
60
+ idHash: await authService.hashSecret(orgId),
61
+ scope: authService.hashToken(orgId),
62
+ }
63
+ : undefined;
64
+ // Auto-generate label if not provided, with collision retry (scoped to the org)
26
65
  let sessionLabel = label;
27
66
  if (!sessionLabel) {
28
67
  for (let i = 0; i < 5; i++) {
29
68
  const candidate = generateSessionLabel();
30
- if (!sessionStore.isLabelTaken(candidate)) {
69
+ if (!sessionStore.isLabelTaken(candidate, org?.scope)) {
31
70
  sessionLabel = candidate;
32
71
  break;
33
72
  }
@@ -49,7 +88,7 @@ export function createSessionRoutes(sessionStore, authService) {
49
88
  c.req.header("x-real-ip") ||
50
89
  undefined;
51
90
  // Persist the session
52
- const session = await sessionStore.createSession(sessionId, sessionLabel, secretHash, tokenEntry, creatorIp);
91
+ const session = await sessionStore.createSession(sessionId, sessionLabel, secretHash, tokenEntry, creatorIp, org);
53
92
  return c.json({
54
93
  sessionId,
55
94
  token,
@@ -58,9 +97,13 @@ export function createSessionRoutes(sessionStore, authService) {
58
97
  }, 201);
59
98
  });
60
99
  /**
61
- * GET /resolve/:label - Resolve a session label to its UUID.
100
+ * GET /resolve/:label - Resolve a PUBLIC (free) session label to its UUID.
62
101
  *
63
102
  * Unauthenticated -- a sessionId alone grants no access (token required).
103
+ * Resolves the public scope ONLY: business (Org_ID-gated) labels are
104
+ * intentionally NOT discoverable here, so a caller cannot enumerate another
105
+ * org's channels by label (per-org isolation, FR6). Business channels are
106
+ * joined by sessionId, provisioned via the control plane / admin (E3).
64
107
  * Returns { sessionId, label } or 400/404.
65
108
  */
66
109
  sessions.get("/resolve/:label", async (c) => {
@@ -68,6 +111,7 @@ export function createSessionRoutes(sessionStore, authService) {
68
111
  if (!isValidSessionLabel(label)) {
69
112
  return c.json({ error: "Invalid label format. Must be 3-32 lowercase alphanumeric characters with internal hyphens." }, 400);
70
113
  }
114
+ // orgScope omitted -> public scope only; business labels resolve to null.
71
115
  const sessionId = sessionStore.getSessionIdByLabel(label);
72
116
  if (!sessionId) {
73
117
  throw new BridgeError(ErrorCode.SESSION_NOT_FOUND, `No session with label "${label}"`, "Check the label or use the full session ID");
@@ -80,19 +124,61 @@ export function createSessionRoutes(sessionStore, authService) {
80
124
  * Receives { secret }, verifies against bcrypt hash, generates a new bearer
81
125
  * token, and returns { sessionId, token, peerCount }.
82
126
  */
83
- sessions.post("/:sessionId/join", zValidator("json", JoinSessionRequestSchema, validationHook), async (c) => {
127
+ sessions.post("/:sessionId/join", zValidator("json", honoSchema(JoinSessionRequestSchema), validationHook), async (c) => {
84
128
  const sessionId = c.req.param("sessionId");
85
- const { secret } = c.req.valid("json");
129
+ const { secret, orgId } = c.req.valid("json");
130
+ // Rate-limit brute-force joins. Tier 1 (source IP + channel) for UX;
131
+ // tier 2 (channel only, non-spoofable) is the security backstop that
132
+ // holds even if X-Forwarded-For / X-Real-IP are forged. The limiter is a
133
+ // Business Edition control: gate it behind multiTenant so the free relay
134
+ // path is unchanged (NFR6 — a free join failure stays 401, never 429).
135
+ const sourceKey = JoinRateLimiter.sourceKey(clientIp(c), sessionId);
136
+ const channelKey = JoinRateLimiter.channelKey(sessionId);
137
+ if (multiTenant)
138
+ rateLimiter.check(sourceKey, channelKey);
86
139
  // Look up the session
87
140
  const session = await sessionStore.getSession(sessionId);
88
141
  if (!session) {
89
142
  throw new BridgeError(ErrorCode.SESSION_NOT_FOUND, `Session ${sessionId} not found`, "Check the session ID or create a new session");
90
143
  }
91
- // Verify the provided secret against the stored bcrypt hash
92
- const isValid = await authService.verifySecret(secret, session.secretHash);
144
+ // A business channel is one that was created WITH an Org_ID (orgIdHash
145
+ // present). Keyed on the stored hash, NOT the live multiTenant flag, so a
146
+ // channel created as business stays Org_ID-gated even if the flag is later
147
+ // toggled off (fail-closed — never silently downgrade to secret-only).
148
+ const isBusiness = session.orgIdHash !== undefined;
149
+ // Enumeration-safe verification: ALWAYS run the same number of bcrypt
150
+ // comparisons regardless of which credential is wrong, so timing leaks
151
+ // nothing. For business channels both the secret AND Org_ID are checked
152
+ // (Org_ID compared even when omitted -> empty string -> false). A wrong
153
+ // Org_ID and a wrong password therefore produce identical work and the
154
+ // identical error below (no oracle).
155
+ const secretOk = await authService.verifySecret(secret, session.secretHash);
156
+ const orgOk = isBusiness
157
+ ? await authService.verifySecret(orgId ?? "", session.orgIdHash)
158
+ : true;
159
+ const isValid = secretOk && orgOk;
93
160
  if (!isValid) {
94
- throw new BridgeError(ErrorCode.AUTH_INVALID_TOKEN, "Invalid session secret", "Verify you are using the correct shared secret for this session");
161
+ if (multiTenant)
162
+ rateLimiter.recordFailure(sourceKey, channelKey);
163
+ // Per-org observability (Story 2.7): org-tagged auth failure. NEVER log
164
+ // the secret or Org_ID — only the org_scope tag + that it was a business
165
+ // channel. (Does not break the enumeration-safe single error below.)
166
+ logOrgEvent({
167
+ event: "auth_failure",
168
+ orgScope: session.orgScope ?? null,
169
+ sessionId,
170
+ outcome: "invalid_credentials",
171
+ detail: { phase: "join", isBusiness },
172
+ });
173
+ // Business: ONE generic message for every failure mode (no enumeration).
174
+ // Free: keep the historical message verbatim (NFR6, unchanged behavior).
175
+ throw isBusiness
176
+ ? new BridgeError(ErrorCode.AUTH_INVALID_TOKEN, "Invalid credentials", "Verify the channel secret and Org_ID")
177
+ : new BridgeError(ErrorCode.AUTH_INVALID_TOKEN, "Invalid session secret", "Verify you are using the correct shared secret for this session");
95
178
  }
179
+ // Successful join clears the per-source counter for this (IP, channel).
180
+ if (multiTenant)
181
+ rateLimiter.recordSuccess(sourceKey);
96
182
  // Generate a new bearer token for this joining client
97
183
  const { token, tokenHash } = authService.generateToken();
98
184
  const tokenEntry = {
@@ -1 +1 @@
1
- {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EACL,WAAW,EACX,SAAS,EACT,0BAA0B,EAC1B,wBAAwB,EACxB,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CACjC,YAA0B,EAC1B,WAAwB;IAExB,MAAM,QAAQ,GAAG,IAAI,IAAI,EAAa,CAAC;IAEvC;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CACX,GAAG,EACH,UAAU,CAAC,MAAM,EAAE,0BAA0B,EAAE,cAAc,CAAC,EAC9D,KAAK,EAAE,CAAC,EAAE,EAAE;QACV,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAE9C,6BAA6B;QAC7B,MAAM,SAAS,GAAG,iBAAiB,EAAE,CAAC;QAEtC,4DAA4D;QAC5D,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,SAAS,GAAG,oBAAoB,EAAE,CAAC;gBACzC,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC1C,YAAY,GAAG,SAAS,CAAC;oBACzB,MAAM;gBACR,CAAC;YACH,CAAC;YACD,IAAI,CAAC,YAAY;gBAAE,YAAY,GAAG,oBAAoB,EAAE,CAAC,CAAC,kCAAkC;QAC9F,CAAC;QAED,6CAA6C;QAC7C,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAExD,2DAA2D;QAC3D,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,WAAW,CAAC,aAAa,EAAE,CAAC;QAEzD,gCAAgC;QAChC,MAAM,UAAU,GAAe;YAC7B,SAAS;YACT,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;QAEF,kEAAkE;QAClE,MAAM,SAAS,GACb,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;YACrD,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC;YACzB,SAAS,CAAC;QAEZ,sBAAsB;QACtB,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,aAAa,CAC9C,SAAS,EACT,YAAY,EACZ,UAAU,EACV,UAAU,EACV,SAAS,CACV,CAAC;QAEF,OAAO,CAAC,CAAC,IAAI,CACX;YACE,SAAS;YACT,KAAK;YACL,KAAK,EAAE,YAAY;YACnB,SAAS,EAAE,OAAO,CAAC,SAAS;SAC7B,EACD,GAAG,CACJ,CAAC;IACJ,CAAC,CACF,CAAC;IAEF;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,CAAC,iBAAiB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC1C,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEnC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,KAAK,EAAE,6FAA6F,EAAE,EACxG,GAAG,CACJ,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,YAAY,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;QAC1D,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,WAAW,CACnB,SAAS,CAAC,iBAAiB,EAC3B,0BAA0B,KAAK,GAAG,EAClC,4CAA4C,CAC7C,CAAC;QACJ,CAAC;QAED,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CACX,kBAAkB,EAClB,UAAU,CAAC,MAAM,EAAE,wBAAwB,EAAE,cAAc,CAAC,EAC5D,KAAK,EAAE,CAAC,EAAE,EAAE;QACV,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAEvC,sBAAsB;QACtB,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACzD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,WAAW,CACnB,SAAS,CAAC,iBAAiB,EAC3B,WAAW,SAAS,YAAY,EAChC,8CAA8C,CAC/C,CAAC;QACJ,CAAC;QAED,4DAA4D;QAC5D,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,YAAY,CAC5C,MAAM,EACN,OAAO,CAAC,UAAU,CACnB,CAAC;QACF,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,WAAW,CACnB,SAAS,CAAC,kBAAkB,EAC5B,wBAAwB,EACxB,iEAAiE,CAClE,CAAC;QACJ,CAAC;QAED,sDAAsD;QACtD,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,WAAW,CAAC,aAAa,EAAE,CAAC;QACzD,MAAM,UAAU,GAAe;YAC7B,SAAS;YACT,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;QAEF,+BAA+B;QAC/B,MAAM,YAAY,CAAC,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QAEnD,OAAO,CAAC,CAAC,IAAI,CAAC;YACZ,SAAS;YACT,KAAK;YACL,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;YAC1B,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM;SAC7C,CAAC,CAAC;IACL,CAAC,CACF,CAAC;IAEF,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,34 @@
1
1
  import type { Context, Env } from "hono";
2
+ import type { zValidator } from "@hono/zod-validator";
3
+ /**
4
+ * Dual-zod-instance type shim for `zValidator`.
5
+ *
6
+ * The server resolves `zod@4.3.6` while `@essentialai/cogent` bundles its OWN
7
+ * nested `zod@4.4.3`. TypeScript compatibility is STRUCTURAL — decided by a
8
+ * type's inferred shape, not its name (vault:
9
+ * typescript-master-vault/concepts/Structural_Type_Compatibility.md). The two
10
+ * copies' `$ZodType`/`$ZodTypeInternals` shapes differ, so a cogent-exported
11
+ * schema is NOT assignable to the `ZodType` shape `@hono/zod-validator` was
12
+ * compiled against — passing it straight in is a `TS2345`/`TS2769` no-overload
13
+ * error, even though both are "zod v4" by name.
14
+ *
15
+ * A type assertion is the sanctioned escape hatch for exactly this case —
16
+ * "integrating with third-party libraries that may not have accurate type
17
+ * definitions" — to be used judiciously, only when necessary (vault:
18
+ * typescript-master-vault/concepts/Type_Assertion.md, Best Practices). So this is
19
+ * ONE narrow, documented boundary cast to the exact type `zValidator` expects
20
+ * (`Parameters<typeof zValidator>[1]`, NOT `any`), not scattered casts. The
21
+ * schemas validate correctly at runtime (covered by the route test suites); only
22
+ * the compile-time type is bridged. Without it `tsc` exits non-zero and
23
+ * `npm run build` (hence the publish gate / image build) fails.
24
+ *
25
+ * Trade-off: the cast collapses the INFERRED output type, so `c.req.valid(...)`
26
+ * at the call sites is `any` rather than the schema's type. Acceptable here — the
27
+ * handlers are small and covered by route tests. Remove once both packages
28
+ * resolve a single zod instance (dedupe the nested copy / align versions).
29
+ */
30
+ type ZValidatorSchema = Parameters<typeof zValidator>[1];
31
+ export declare function honoSchema(schema: unknown): ZValidatorSchema;
2
32
  /**
3
33
  * Shared validation hook for @hono/zod-validator.
4
34
  *
@@ -15,4 +45,5 @@ export declare function validationHook(result: {
15
45
  success: boolean;
16
46
  error?: unknown;
17
47
  }, c: Context<Env>): Response | void;
48
+ export {};
18
49
  //# sourceMappingURL=validation-hook.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation-hook.d.ts","sourceRoot":"","sources":["../../src/routes/validation-hook.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAEzC;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,EAC7C,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,GACd,QAAQ,GAAG,IAAI,CAejB"}
1
+ {"version":3,"file":"validation-hook.d.ts","sourceRoot":"","sources":["../../src/routes/validation-hook.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AACzD,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAE5D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,EAC7C,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,GACd,QAAQ,GAAG,IAAI,CAejB"}
@@ -1,4 +1,7 @@
1
1
  import { BridgeError, ErrorCode } from "@essentialai/cogent";
2
+ export function honoSchema(schema) {
3
+ return schema;
4
+ }
2
5
  /**
3
6
  * Shared validation hook for @hono/zod-validator.
4
7
  *
@@ -1 +1 @@
1
- {"version":3,"file":"validation-hook.js","sourceRoot":"","sources":["../../src/routes/validation-hook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAG7D;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAC5B,MAA6C,EAC7C,CAAe;IAEf,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC;QAC9B,MAAM,OAAO,GACX,QAAQ,YAAY,KAAK;YACvB,CAAC,CAAC,QAAQ,CAAC,OAAO;YAClB,CAAC,CAAC,sBAAsB,CAAC;QAE7B,MAAM,GAAG,GAAG,IAAI,WAAW,CACzB,SAAS,CAAC,aAAa,EACvB,sBAAsB,OAAO,EAAE,EAC/B,gDAAgD,CACjD,CAAC;QACF,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,GAAG,CAAC,CAAC;IACnC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"validation-hook.js","sourceRoot":"","sources":["../../src/routes/validation-hook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAgC7D,MAAM,UAAU,UAAU,CAAC,MAAe;IACxC,OAAO,MAA0B,CAAC;AACpC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAC5B,MAA6C,EAC7C,CAAe;IAEf,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC;QAC9B,MAAM,OAAO,GACX,QAAQ,YAAY,KAAK;YACvB,CAAC,CAAC,QAAQ,CAAC,OAAO;YAClB,CAAC,CAAC,sBAAsB,CAAC;QAE7B,MAAM,GAAG,GAAG,IAAI,WAAW,CACzB,SAAS,CAAC,aAAa,EACvB,sBAAsB,OAAO,EAAE,EAC/B,gDAAgD,CACjD,CAAC;QACF,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,GAAG,CAAC,CAAC;IACnC,CAAC;AACH,CAAC"}
@@ -1,48 +1,8 @@
1
1
  /**
2
- * Authentication service for the Cogent server.
3
- *
4
- * Responsibilities:
5
- * - bcrypt hashing of session secrets (one-time, during create/join)
6
- * - Random bearer token generation with SHA-256 hashing for storage
7
- * - Timing-safe comparison for token verification (every request)
8
- *
9
- * bcrypt is used for secrets (slow, salted -- appropriate for passwords).
10
- * SHA-256 is used for tokens (fast -- tokens are high-entropy random values).
11
- * Timing-safe comparison prevents timing attacks on token verification.
2
+ * Re-export shim. The hashing/token primitives now live in the shared core
3
+ * (`@essentialai/cogent/auth`) so the relay and the Business Edition control
4
+ * plane hash secrets identically. Behavior is byte-for-byte unchanged; every
5
+ * existing `import { AuthService } from ".../auth-service.js"` keeps working.
12
6
  */
13
- export declare class AuthService {
14
- private readonly bcryptRounds;
15
- constructor(bcryptRounds: number);
16
- /**
17
- * Hash a plaintext secret using bcrypt.
18
- * Used during session creation and join operations.
19
- */
20
- hashSecret(plainSecret: string): Promise<string>;
21
- /**
22
- * Verify a plaintext secret against a bcrypt hash.
23
- * Used during session join to validate the provided secret.
24
- */
25
- verifySecret(plainSecret: string, hash: string): Promise<boolean>;
26
- /**
27
- * Generate a cryptographically random bearer token.
28
- * Returns both the plaintext token (to send to client) and its
29
- * SHA-256 hash (to store on disk for lookup).
30
- */
31
- generateToken(): {
32
- token: string;
33
- tokenHash: string;
34
- };
35
- /**
36
- * Compute the SHA-256 hash of a token string.
37
- * Used by auth middleware to look up tokens in the session store index.
38
- */
39
- hashToken(token: string): string;
40
- /**
41
- * Timing-safe string comparison.
42
- * Hashes both strings with SHA-256 to normalize length, then uses
43
- * crypto.timingSafeEqual on the resulting buffers. This prevents
44
- * timing attacks regardless of input string lengths.
45
- */
46
- timingSafeCompare(a: string, b: string): boolean;
47
- }
7
+ export { AuthService } from "@essentialai/cogent/auth";
48
8
  //# sourceMappingURL=auth-service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth-service.d.ts","sourceRoot":"","sources":["../../src/services/auth-service.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,YAAY,EAAE,MAAM;IAIhC;;;OAGG;IACG,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAItD;;;OAGG;IACG,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIvE;;;;OAIG;IACH,aAAa,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAMrD;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAIhC;;;;;OAKG;IACH,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO;CAKjD"}
1
+ {"version":3,"file":"auth-service.d.ts","sourceRoot":"","sources":["../../src/services/auth-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC"}
@@ -1,63 +1,8 @@
1
- import crypto from "node:crypto";
2
- import bcrypt from "bcryptjs";
3
1
  /**
4
- * Authentication service for the Cogent server.
5
- *
6
- * Responsibilities:
7
- * - bcrypt hashing of session secrets (one-time, during create/join)
8
- * - Random bearer token generation with SHA-256 hashing for storage
9
- * - Timing-safe comparison for token verification (every request)
10
- *
11
- * bcrypt is used for secrets (slow, salted -- appropriate for passwords).
12
- * SHA-256 is used for tokens (fast -- tokens are high-entropy random values).
13
- * Timing-safe comparison prevents timing attacks on token verification.
2
+ * Re-export shim. The hashing/token primitives now live in the shared core
3
+ * (`@essentialai/cogent/auth`) so the relay and the Business Edition control
4
+ * plane hash secrets identically. Behavior is byte-for-byte unchanged; every
5
+ * existing `import { AuthService } from ".../auth-service.js"` keeps working.
14
6
  */
15
- export class AuthService {
16
- bcryptRounds;
17
- constructor(bcryptRounds) {
18
- this.bcryptRounds = bcryptRounds;
19
- }
20
- /**
21
- * Hash a plaintext secret using bcrypt.
22
- * Used during session creation and join operations.
23
- */
24
- async hashSecret(plainSecret) {
25
- return bcrypt.hash(plainSecret, this.bcryptRounds);
26
- }
27
- /**
28
- * Verify a plaintext secret against a bcrypt hash.
29
- * Used during session join to validate the provided secret.
30
- */
31
- async verifySecret(plainSecret, hash) {
32
- return bcrypt.compare(plainSecret, hash);
33
- }
34
- /**
35
- * Generate a cryptographically random bearer token.
36
- * Returns both the plaintext token (to send to client) and its
37
- * SHA-256 hash (to store on disk for lookup).
38
- */
39
- generateToken() {
40
- const token = crypto.randomBytes(32).toString("hex");
41
- const tokenHash = this.hashToken(token);
42
- return { token, tokenHash };
43
- }
44
- /**
45
- * Compute the SHA-256 hash of a token string.
46
- * Used by auth middleware to look up tokens in the session store index.
47
- */
48
- hashToken(token) {
49
- return crypto.createHash("sha256").update(token).digest("hex");
50
- }
51
- /**
52
- * Timing-safe string comparison.
53
- * Hashes both strings with SHA-256 to normalize length, then uses
54
- * crypto.timingSafeEqual on the resulting buffers. This prevents
55
- * timing attacks regardless of input string lengths.
56
- */
57
- timingSafeCompare(a, b) {
58
- const hashA = crypto.createHash("sha256").update(a).digest();
59
- const hashB = crypto.createHash("sha256").update(b).digest();
60
- return crypto.timingSafeEqual(hashA, hashB);
61
- }
62
- }
7
+ export { AuthService } from "@essentialai/cogent/auth";
63
8
  //# sourceMappingURL=auth-service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth-service.js","sourceRoot":"","sources":["../../src/services/auth-service.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,MAAM,MAAM,UAAU,CAAC;AAE9B;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,WAAW;IACL,YAAY,CAAS;IAEtC,YAAY,YAAoB;QAC9B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU,CAAC,WAAmB;QAClC,OAAO,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IACrD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY,CAAC,WAAmB,EAAE,IAAY;QAClD,OAAO,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED;;;;OAIG;IACH,aAAa;QACX,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACxC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC9B,CAAC;IAED;;;OAGG;IACH,SAAS,CAAC,KAAa;QACrB,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjE,CAAC;IAED;;;;;OAKG;IACH,iBAAiB,CAAC,CAAS,EAAE,CAAS;QACpC,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC7D,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC7D,OAAO,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC;CACF"}
1
+ {"version":3,"file":"auth-service.js","sourceRoot":"","sources":["../../src/services/auth-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC"}
@@ -68,6 +68,21 @@ export declare class ConnectionManager {
68
68
  * Get all connections in a session (flat array across all peers).
69
69
  */
70
70
  getAllSessionConnections(sessionId: string): PeerConnection[];
71
+ /**
72
+ * Force-close every WebSocket connection in a session (all peers), returning
73
+ * the number closed. Used when the control plane deletes a channel or rotates
74
+ * an Org_ID: connected agents are dropped so they must rejoin with current
75
+ * credentials. Best-effort — already-closed sockets are ignored. Does not
76
+ * mutate the session store; the caller owns that.
77
+ *
78
+ * Map cleanup is deferred: this does NOT call `removeConnection`. The socket's
79
+ * async `onClose` handler (ws/handler.ts) runs the normal teardown — pruning
80
+ * the connection map, starting the grace timer, and firing `onPeerOffline`.
81
+ * Calling `removeConnection` here as well would double-fire that teardown. So
82
+ * for a brief window after this returns, `getAllSessionConnections` may still
83
+ * list the now-closing sockets (mirrors the existing `closeAll` shutdown path).
84
+ */
85
+ closeSessionConnections(sessionId: string, code: number, reason: string): number;
71
86
  /**
72
87
  * Get the list of peer IDs with active connections in a session.
73
88
  */
@@ -1 +1 @@
1
- {"version":3,"file":"connection-manager.d.ts","sourceRoot":"","sources":["../../src/services/connection-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,KAAK,SAAS,MAAM,IAAI,CAAC;AAEhC;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,EAAE,EAAE,SAAS,CAAC;IACd,qEAAqE;IACrE,KAAK,EAAE,SAAS,CAAC;IACjB,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,WAAW,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,iBAAiB,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;CACnD;AAED;;;;;;;GAOG;AACH,qBAAa,iBAAiB;IAC5B;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAGxB;IAEJ;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAGxB;IAEJ,iFAAiF;IACjF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAExC,uEAAuE;IACvE,OAAO,CAAC,aAAa,CAAC,CAA8C;gBAExD,cAAc,GAAE,MAAe;IAI3C;;;OAGG;IACH,gBAAgB,CACd,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,GACpD,IAAI;IAIP;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IA4BzC;;;;OAIG;IACH,gBAAgB,CACd,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,SAAS,GACZ,IAAI;IA4BP;;;OAGG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,cAAc,EAAE;IAMnE;;OAEG;IACH,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,EAAE;IAW7D;;OAEG;IACH,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE;IAMhD;;;;OAIG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAYnE;;;OAGG;IACH,kBAAkB,CAChB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,aAAa,CAAC,EAAE,MAAM,GACrB,IAAI;IAcP;;;;;;;;OAQG;IACH,4BAA4B,CAC1B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,GACpC,IAAI;IAcP;;OAEG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAOvD;;;OAGG;IACH,sBAAsB,IAAI,MAAM;IAQhC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAwB5C;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;CAUzB"}
1
+ {"version":3,"file":"connection-manager.d.ts","sourceRoot":"","sources":["../../src/services/connection-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,KAAK,SAAS,MAAM,IAAI,CAAC;AAEhC;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,EAAE,EAAE,SAAS,CAAC;IACd,qEAAqE;IACrE,KAAK,EAAE,SAAS,CAAC;IACjB,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,WAAW,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,iBAAiB,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;CACnD;AAED;;;;;;;GAOG;AACH,qBAAa,iBAAiB;IAC5B;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAGxB;IAEJ;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAGxB;IAEJ,iFAAiF;IACjF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAExC,uEAAuE;IACvE,OAAO,CAAC,aAAa,CAAC,CAA8C;gBAExD,cAAc,GAAE,MAAe;IAI3C;;;OAGG;IACH,gBAAgB,CACd,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,GACpD,IAAI;IAIP;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IA4BzC;;;;OAIG;IACH,gBAAgB,CACd,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,SAAS,GACZ,IAAI;IA4BP;;;OAGG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,cAAc,EAAE;IAMnE;;OAEG;IACH,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,EAAE;IAW7D;;;;;;;;;;;;;OAaG;IACH,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAehF;;OAEG;IACH,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE;IAMhD;;;;OAIG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAYnE;;;OAGG;IACH,kBAAkB,CAChB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,aAAa,CAAC,EAAE,MAAM,GACrB,IAAI;IAcP;;;;;;;;OAQG;IACH,4BAA4B,CAC1B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,GACpC,IAAI;IAcP;;OAEG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAOvD;;;OAGG;IACH,sBAAsB,IAAI,MAAM;IAQhC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAwB5C;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;CAUzB"}
@@ -111,6 +111,35 @@ export class ConnectionManager {
111
111
  }
112
112
  return result;
113
113
  }
114
+ /**
115
+ * Force-close every WebSocket connection in a session (all peers), returning
116
+ * the number closed. Used when the control plane deletes a channel or rotates
117
+ * an Org_ID: connected agents are dropped so they must rejoin with current
118
+ * credentials. Best-effort — already-closed sockets are ignored. Does not
119
+ * mutate the session store; the caller owns that.
120
+ *
121
+ * Map cleanup is deferred: this does NOT call `removeConnection`. The socket's
122
+ * async `onClose` handler (ws/handler.ts) runs the normal teardown — pruning
123
+ * the connection map, starting the grace timer, and firing `onPeerOffline`.
124
+ * Calling `removeConnection` here as well would double-fire that teardown. So
125
+ * for a brief window after this returns, `getAllSessionConnections` may still
126
+ * list the now-closing sockets (mirrors the existing `closeAll` shutdown path).
127
+ */
128
+ closeSessionConnections(sessionId, code, reason) {
129
+ const conns = this.getAllSessionConnections(sessionId);
130
+ let closed = 0;
131
+ for (const conn of conns) {
132
+ try {
133
+ clearInterval(conn.heartbeatInterval);
134
+ conn.ws.close(code, reason);
135
+ closed++;
136
+ }
137
+ catch {
138
+ // Already closed / closing -- nothing to do.
139
+ }
140
+ }
141
+ return closed;
142
+ }
114
143
  /**
115
144
  * Get the list of peer IDs with active connections in a session.
116
145
  */
@@ -1 +1 @@
1
- {"version":3,"file":"connection-manager.js","sourceRoot":"","sources":["../../src/services/connection-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"connection-manager.js","sourceRoot":"","sources":["../../src/services/connection-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * In-memory, two-tier rate limiter for session-join attempts.
3
+ *
4
+ * Tier 1 (per source+channel, `${ip}::${sessionId}`): a low threshold for good
5
+ * UX — a single brute-forcing client trips it quickly.
6
+ *
7
+ * Tier 2 (per channel, `channel::${sessionId}`): a higher threshold that is the
8
+ * SECURITY backstop. The channel id comes from the URL path and cannot be
9
+ * spoofed, so it holds even when an attacker rotates `X-Forwarded-For` /
10
+ * `X-Real-IP` to evade tier 1. `check()` blocks if EITHER tier is locked.
11
+ *
12
+ * Single-node MVP: state is process-local. Multi-node (vNext) moves this to a
13
+ * shared store (Postgres / Redis), at which point tier 1 can key on the
14
+ * trusted-proxy-validated real client IP. The clock is injectable for tests.
15
+ *
16
+ * Tradeoff (accepted): tier 2 means an attacker who knows a sessionId can lock
17
+ * NEW joins on that channel for `lockoutMs` with `channelMaxFailures` bad
18
+ * attempts. Already-joined agents keep their bearer tokens (join issues, does
19
+ * not gate, existing sessions). The higher tier-2 threshold keeps this from
20
+ * tripping on the rare legitimate failure; per-org quotas (E5) bound it further.
21
+ */
22
+ export declare class JoinRateLimiter {
23
+ private readonly perSourceMax;
24
+ private readonly channelMax;
25
+ private readonly windowMs;
26
+ private readonly lockoutMs;
27
+ private readonly now;
28
+ private readonly attempts;
29
+ constructor(perSourceMax: number, channelMax: number, windowMs: number, lockoutMs: number, now?: () => number);
30
+ /** Tier-1 key: source IP + channel (best-effort; IP may be spoofable). */
31
+ static sourceKey(ip: string, sessionId: string): string;
32
+ /** Tier-2 key: channel only (non-spoofable; the security backstop). */
33
+ static channelKey(sessionId: string): string;
34
+ /**
35
+ * Throw RATE_LIMITED if EITHER the source tier or the channel tier is locked.
36
+ * Call BEFORE verifying credentials.
37
+ */
38
+ check(sourceKey: string, channelKey: string): void;
39
+ /** Record a failed attempt against both tiers. */
40
+ recordFailure(sourceKey: string, channelKey: string): void;
41
+ /**
42
+ * Clear the SOURCE tier after a successful join. The channel tier is left to
43
+ * decay with its window — a single success must not reset a channel-wide
44
+ * brute-force counter.
45
+ */
46
+ recordSuccess(sourceKey: string): void;
47
+ /** Increment a key's failure count within its window; lock past `threshold`. */
48
+ private _fail;
49
+ }
50
+ //# sourceMappingURL=join-rate-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"join-rate-limiter.d.ts","sourceRoot":"","sources":["../../src/services/join-rate-limiter.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoC;gBAG3D,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,MAAM,MAAyB;IAStC,0EAA0E;IAC1E,MAAM,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;IAIvD,uEAAuE;IACvE,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAI5C;;;OAGG;IACH,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAiBlD,kDAAkD;IAClD,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAK1D;;;;OAIG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAItC,gFAAgF;IAChF,OAAO,CAAC,KAAK;CAed"}