@songsid/agend 2.3.0-beta.3 → 2.3.0-beta.4

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 (112) hide show
  1. package/dist/auth-api.d.ts +30 -1
  2. package/dist/auth-api.js +32 -7
  3. package/dist/auth-api.js.map +1 -1
  4. package/dist/backend/types.d.ts +1 -0
  5. package/dist/backend/types.js +15 -0
  6. package/dist/backend/types.js.map +1 -1
  7. package/dist/backend-availability.d.ts +120 -0
  8. package/dist/backend-availability.js +396 -0
  9. package/dist/backend-availability.js.map +1 -0
  10. package/dist/backend-command.d.ts +21 -3
  11. package/dist/backend-command.js +23 -4
  12. package/dist/backend-command.js.map +1 -1
  13. package/dist/channel/adapters/discord.d.ts +7 -0
  14. package/dist/channel/adapters/discord.js +35 -0
  15. package/dist/channel/adapters/discord.js.map +1 -1
  16. package/dist/channel/mcp-tools.js +4 -4
  17. package/dist/channel/mcp-tools.js.map +1 -1
  18. package/dist/channel/types.d.ts +6 -0
  19. package/dist/config-validator.js +73 -2
  20. package/dist/config-validator.js.map +1 -1
  21. package/dist/fleet-context.d.ts +10 -0
  22. package/dist/fleet-manager.d.ts +174 -6
  23. package/dist/fleet-manager.js +642 -41
  24. package/dist/fleet-manager.js.map +1 -1
  25. package/dist/general-knowledge/skills/web-appearance/SKILL.md +17 -7
  26. package/dist/human-delivery-receipts.js +2 -1
  27. package/dist/human-delivery-receipts.js.map +1 -1
  28. package/dist/locale.js +42 -4
  29. package/dist/locale.js.map +1 -1
  30. package/dist/outbound-schemas.d.ts +4 -0
  31. package/dist/outbound-schemas.js +5 -1
  32. package/dist/outbound-schemas.js.map +1 -1
  33. package/dist/public-web-link.d.ts +9 -0
  34. package/dist/public-web-link.js +8 -0
  35. package/dist/public-web-link.js.map +1 -1
  36. package/dist/quickstart-api.d.ts +10 -1
  37. package/dist/quickstart-api.js +12 -4
  38. package/dist/quickstart-api.js.map +1 -1
  39. package/dist/reply-buttons-controller.d.ts +2 -0
  40. package/dist/reply-buttons-controller.js +1 -1
  41. package/dist/reply-buttons-controller.js.map +1 -1
  42. package/dist/topic-commands.d.ts +5 -0
  43. package/dist/topic-commands.js +16 -0
  44. package/dist/topic-commands.js.map +1 -1
  45. package/dist/types.d.ts +24 -0
  46. package/dist/ui/chat-thread.js +4 -1
  47. package/dist/ui/panel-chat.js +4 -3
  48. package/dist/ui/panel-fleet.js +15 -6
  49. package/dist/ui/panel-settings.js +3 -2
  50. package/dist/ui/settings-catalog.js +89 -0
  51. package/dist/ui/settings-dialogs.js +37 -6
  52. package/dist/ui/settings-strings.js +6 -0
  53. package/dist/ui/shared/app.css +36 -3
  54. package/dist/ui/shared/card-strings.js +4 -0
  55. package/dist/ui/shared/effect-stock-trust.js +23 -2
  56. package/dist/ui/shared/identity-card.js +70 -2
  57. package/dist/ui/shared/panel-view.js +22 -2
  58. package/dist/ui/shared/view-strings.js +6 -0
  59. package/dist/view-api.d.ts +11 -0
  60. package/dist/view-api.js +27 -4
  61. package/dist/view-api.js.map +1 -1
  62. package/dist/web-api.d.ts +16 -0
  63. package/dist/web-api.js +133 -22
  64. package/dist/web-api.js.map +1 -1
  65. package/dist/web-appearance-policy.d.ts +4 -6
  66. package/dist/web-appearance-policy.js +5 -12
  67. package/dist/web-appearance-policy.js.map +1 -1
  68. package/dist/web-appearance-tools.js +5 -1
  69. package/dist/web-appearance-tools.js.map +1 -1
  70. package/dist/web-appearance-view.d.ts +4 -1
  71. package/dist/web-appearance-view.js +21 -2
  72. package/dist/web-appearance-view.js.map +1 -1
  73. package/dist/web-appearance.d.ts +2 -2
  74. package/dist/web-appearance.js +5 -6
  75. package/dist/web-appearance.js.map +1 -1
  76. package/dist/web-card.d.ts +14 -0
  77. package/dist/web-card.js +40 -6
  78. package/dist/web-card.js.map +1 -1
  79. package/dist/web-channel-echo.d.ts +7 -1
  80. package/dist/web-channel-echo.js +6 -2
  81. package/dist/web-channel-echo.js.map +1 -1
  82. package/dist/web-chat-history.d.ts +40 -0
  83. package/dist/web-chat-history.js +66 -3
  84. package/dist/web-chat-history.js.map +1 -1
  85. package/dist/web-commands.d.ts +1 -0
  86. package/dist/web-effect-tools.js +2 -3
  87. package/dist/web-effect-tools.js.map +1 -1
  88. package/dist/web-guest-access.d.ts +65 -7
  89. package/dist/web-guest-access.js +124 -18
  90. package/dist/web-guest-access.js.map +1 -1
  91. package/dist/web-guest-rooms.d.ts +82 -0
  92. package/dist/web-guest-rooms.js +135 -0
  93. package/dist/web-guest-rooms.js.map +1 -0
  94. package/dist/web-login.d.ts +47 -0
  95. package/dist/web-login.js +115 -0
  96. package/dist/web-login.js.map +1 -1
  97. package/dist/web-mod-agent.d.ts +1 -1
  98. package/dist/web-mod-agent.js +2 -4
  99. package/dist/web-mod-agent.js.map +1 -1
  100. package/dist/web-returning-device.d.ts +39 -0
  101. package/dist/web-returning-device.js +46 -5
  102. package/dist/web-returning-device.js.map +1 -1
  103. package/dist/web-session.d.ts +43 -3
  104. package/dist/web-session.js +79 -14
  105. package/dist/web-session.js.map +1 -1
  106. package/dist/web-settings-tools.d.ts +12 -0
  107. package/dist/web-settings-tools.js +10 -0
  108. package/dist/web-settings-tools.js.map +1 -1
  109. package/dist/web-theme.d.ts +2 -0
  110. package/dist/web-theme.js +10 -1
  111. package/dist/web-theme.js.map +1 -1
  112. package/package.json +1 -1
@@ -35,15 +35,17 @@ export const GUEST_ROUTES = [
35
35
  { methods: ["GET"], pattern: /^\/ui\/events$/, instance: null, state: "on", note: "the stream, projected for this guest (guestFrameData)" },
36
36
  { methods: ["GET"], pattern: /^\/ui\/poll$/, instance: null, state: "on", note: "the poll, projected for this guest (guestPollBody)" },
37
37
  { methods: ["GET"], pattern: /^\/ui\/file\/[^/]+$/, instance: null, state: "on", note: "a file, served only when its stored instance is in scope (the handler checks)" },
38
- { methods: ["GET"], pattern: /^\/ui\/effect-posters\/[0-9a-f]{32}\.png$/, instance: null, state: "later", note: "phase 1b: a poster bound to its instance" },
38
+ { methods: ["GET"], pattern: /^\/ui\/effect-posters\/[0-9a-f]{32}\.png$/, instance: { query: "instance" }, state: "on", note: "a placed effect's static poster, bound to its instance by the query" },
39
39
  // Opened by phase 2: what needs the guest's own identity, authority and the history rule.
40
- { methods: ["GET"], pattern: /^\/ui\/history$/, instance: { query: "instance" }, state: "later", note: "phase 2: history rows as the channel showed them (#1920 §5.2)" },
41
- { methods: ["POST"], pattern: /^\/ui\/send$/, instance: null, state: "later", note: "phase 2: guest chat (web.guests.chat), authority none" },
42
- { methods: ["POST"], pattern: /^\/ui\/upload$/, instance: { query: "instance" }, state: "later", note: "phase 2: guest chat's uploads" },
43
- { methods: ["POST"], pattern: /^\/ui\/reply-button$/, instance: null, state: "later", note: "phase 2: reply buttons, as on the platform" },
44
- { methods: ["POST"], pattern: new RegExp(`^/ui/cancel/${NAME}$`), instance: { group: 1 }, state: "later", note: "phase 2: Cancel, as the platform's button" },
45
- { methods: ["GET", "POST"], pattern: /^\/ui\/prefs$/, instance: null, state: "later", note: "phase 2: the guest's own preferences, never the host's" },
46
- { methods: ["GET", "POST"], pattern: /^\/ui\/profile$/, instance: null, state: "later", note: "phase 2: the guest's own web name" },
40
+ { methods: ["GET"], pattern: /^\/ui\/history$/, instance: { query: "instance" }, state: "on", note: "an in-scope instance's history, as its channel showed it (guestHistory, #1920 §5.2)" },
41
+ // Phase 2 (step 2b): chat as on the platform — authority none, never a command (guestChatRefusal, in the handlers).
42
+ { methods: ["POST"], pattern: /^\/ui\/send$/, instance: null, state: "on", note: "a message to an in-scope instance (the handler checks the body's instance and web.guests.chat); never a command" },
43
+ { methods: ["POST"], pattern: /^\/ui\/upload$/, instance: { query: "instance" }, state: "on", note: "a file for an in-scope instance's message (web.guests.chat)" },
44
+ { methods: ["POST"], pattern: /^\/ui\/reply-button$/, instance: null, state: "on", note: "a click on a reply the guest may see (the handler checks; web.guests.chat)" },
45
+ { methods: ["POST"], pattern: new RegExp(`^/ui/cancel/${NAME}$`), instance: { group: 1 }, state: "on", note: "Cancel, as the platform's button lets anyone allowed there (web.guests.chat)" },
46
+ { methods: ["GET"], pattern: /^\/ui\/prefs$/, instance: null, state: "on", note: "the host's look (theme, language, shown settings) and the guest's own — nothing that names an instance (guestPrefs)" },
47
+ { methods: ["POST"], pattern: /^\/ui\/prefs$/, instance: null, state: "later", note: "phase 3: what a guest may keep of its own" },
48
+ { methods: ["GET", "POST"], pattern: /^\/ui\/profile$/, instance: null, state: "on", note: "the guest's own web name (its account's, never anyone else's)" },
47
49
  ];
48
50
  /** An instance name from a path segment, or null when it is not one (the shell's own rule). */
49
51
  function segmentName(path) {
@@ -77,6 +79,33 @@ export function guestRouteDecision(method, url, scope) {
77
79
  export function sameAccount(a, b) {
78
80
  return !!a && !!b && a.adapterId === b.adapterId && a.userId === b.userId;
79
81
  }
82
+ /**
83
+ * #1920 §5.1 (step 2b): why a guest may not write to `instance` now, or null (not a guest, or allowed): out of scope is
84
+ * "not found" (another instance's name is never confirmed); read-only when the host says so.
85
+ */
86
+ export function guestChatRefusal(guest, instance) {
87
+ if (!guest)
88
+ return null;
89
+ if (typeof instance !== "string" || !guest.scope().has(instance))
90
+ return { status: 404, error: "not found" };
91
+ if (guest.chat?.() !== true)
92
+ return { status: 403, error: "guest_read_only" };
93
+ return null;
94
+ }
95
+ /** A guest never sends a command: text that starts (after spaces) with "/" is the platform's admin or command syntax. */
96
+ export const guestCommandText = (text) => /^\s*\//.test(text);
97
+ /**
98
+ * #1920 §4 (step 2b): the preferences a guest reads — the host's look and the guest's own; never one that names an
99
+ * instance (the sidebar's order, favourites, a card's size, the sidebar widget, names, the filter).
100
+ */
101
+ export const GUEST_PREF_KEYS = new Set(["theme", "lang", "fx.show", "card.size", "color.show", "color.off", "fx.sidebar", "fx.header", "fx.page", "fx.box", "fx.cursor"]);
102
+ export function guestPrefs(view) {
103
+ const values = {};
104
+ for (const [k, v] of Object.entries(view.values))
105
+ if (GUEST_PREF_KEYS.has(k))
106
+ values[k] = v;
107
+ return { ...view, values };
108
+ }
80
109
  const guestRequests = new WeakMap();
81
110
  /** Set by the one entry that admits a guest (FleetManager's gate); read by the handlers that answer per recipient. */
82
111
  export function bindGuestRequest(req, guest) { guestRequests.set(req, guest); }
@@ -104,23 +133,100 @@ export function guestStatus(status, scope) {
104
133
  }
105
134
  return { instances };
106
135
  }
136
+ // ── Phase 2: the chat, as the channel showed it (#1920 §5.2) ──
137
+ const accountOf = (o) => `${o.adapterId}:${o.userId}`;
138
+ /**
139
+ * Whether a guest sees one kept message: an in-scope instance's message that reached its channel (what the channel's
140
+ * members already saw), the guest's own, or anything in its own private room. Never someone else's web-only exchange,
141
+ * a cross-instance notice, a fleet status line, or a row kept from before these were recorded (they have no mark).
142
+ */
143
+ export function guestSeesMessage(m, guest, scope) {
144
+ if (!scope.has(m.instance))
145
+ return false;
146
+ return m.channel === true || m.from === accountOf(guest.owner) || guest.ownRoom?.(m.instance) === true;
147
+ }
148
+ /**
149
+ * A message as a guest gets it: without whose account wrote it (`mine` says it was the guest), and without another
150
+ * person's message id and ticks; never an effect Try (effects stay admin-only).
151
+ */
152
+ export function guestMessage(m, guest) {
153
+ const { from, channel: _channel, messageId, delivery, effectTrial: _trial, seenSeq: _seen, ...rest } = m;
154
+ void _channel;
155
+ void _trial;
156
+ void _seen;
157
+ const mine = from === accountOf(guest.owner);
158
+ // #2085 review: a click's `text` is what the agent was given — the button's value too, which the platform never
159
+ // shows. A guest gets the label, as the channel showed it.
160
+ const click = rest.click ? { text: rest.click.label } : {};
161
+ return { ...rest, ...click, ...(mine ? { mine: true } : {}), ...(mine && messageId ? { messageId } : {}), ...(mine && delivery ? { delivery } : {}) };
162
+ }
163
+ const visibleList = (rows, guest, scope) => rows.filter((m) => !m.effectTrial && guestSeesMessage(m, guest, scope)).map((m) => guestMessage(m, guest));
107
164
  /**
108
- * One stream event as a guest gets it, or undefined (not sent). Default deny: only the status (projected) and an
109
- * in-scope instance's activity. Chat messages, live replies, delivery ticks and reply buttons wait for phase 2's rule
110
- * (#1920 §5.2: only what reached the channel); prompts (their nonces answer them), Needs you, the Log's ticks, traffic
111
- * and apply progress are never a guest's.
165
+ * One stream event as a guest gets it, or undefined (not sent). Default deny:
166
+ * - the status (projected) and an in-scope instance's activity;
167
+ * - a chat message it may see (§5.2), a tick on one of its own messages, the buttons of a reply it may see;
168
+ * - never: the live reply receipt (effects), prompts (their nonces answer them), Needs you, the Log's ticks, traffic or
169
+ * apply progress.
170
+ * Without `guest` (no context) only the status and activity pass.
112
171
  */
113
- export function guestFrameData(event, data, scope) {
172
+ export function guestFrameData(event, data, scope, guest) {
114
173
  if (event === "status")
115
174
  return guestStatus(data, scope);
116
- if (event === "activity") {
117
- const d = data && typeof data === "object" ? data : {};
175
+ const d = data && typeof data === "object" ? data : {};
176
+ if (event === "activity")
118
177
  return typeof d.instance === "string" && scope.has(d.instance) ? { instance: d.instance, state: d.state ?? null } : undefined;
178
+ if (!guest)
179
+ return undefined;
180
+ if (event === "message") {
181
+ const m = data;
182
+ return typeof m?.instance === "string" && guestSeesMessage(m, guest, scope) ? guestMessage(m, guest) : undefined;
183
+ }
184
+ const history = guest.history?.();
185
+ if (!history || typeof d.instance !== "string" || !scope.has(d.instance))
186
+ return undefined;
187
+ if (event === "delivery") {
188
+ const own = typeof d.messageId === "string" ? history.findByMessageId(d.instance, d.messageId) : undefined;
189
+ return own && own.from === accountOf(guest.owner) ? { instance: d.instance, messageId: d.messageId, delivery: d.delivery } : undefined;
190
+ }
191
+ if (event === "reply_buttons") {
192
+ const id = d.buttons && typeof d.buttons === "object" ? d.buttons.id : undefined;
193
+ const row = typeof id === "string" ? history.findByButtons(d.instance, id) : undefined;
194
+ return row && guestSeesMessage(row, guest, scope) ? { instance: d.instance, buttons: d.buttons } : undefined;
119
195
  }
120
196
  return undefined;
121
197
  }
122
- /** /ui/poll's answer for a guest: the projected status, and nothing else yet (the same rule as the stream). */
123
- export function guestPollBody(status, scope, now) {
124
- return { status: guestStatus(status, scope), messages: [], deliveries: [], reply_buttons: [], prompts: [], needs: [], cursor: null, now };
198
+ /** The ticks a guest is caught up with: its own messages' only. */
199
+ export function guestDeliveries(history, guest, scope) {
200
+ return history.deliveries().filter((t) => scope.has(t.instance) && history.findByMessageId(t.instance, t.messageId)?.from === accountOf(guest.owner));
201
+ }
202
+ /** The ended (or open-poll) buttons a guest is caught up with: on replies it may see. */
203
+ export function guestButtonStates(history, guest, scope) {
204
+ return history.buttonStates().filter((b) => { const row = history.findByButtons(b.instance, b.buttons.id); return !!row && guestSeesMessage(row, guest, scope); });
205
+ }
206
+ /** A guest's replay (a reconnecting stream, a poll): what it may see of `rows`. */
207
+ export function guestMessages(rows, guest, scope) {
208
+ return visibleList(rows, guest, scope);
209
+ }
210
+ /** /ui/history for a guest: the newest `limit` messages of one instance that it may see. */
211
+ export function guestHistory(history, instance, limit, guest, scope) {
212
+ return visibleList(history.list(instance), guest, scope).slice(-limit);
213
+ }
214
+ /**
215
+ * /ui/poll's answer for a guest: the projected status, and the chat it may see (the same rule as its stream) — with the
216
+ * cursor every poll hands out. Never prompts or Needs you.
217
+ */
218
+ export function guestPollBody(status, scope, now, guest, after, replay) {
219
+ const history = guest?.history?.() ?? null;
220
+ if (!guest || !history || !replay)
221
+ return { status: guestStatus(status, scope), messages: [], deliveries: [], reply_buttons: [], prompts: [], needs: [], cursor: null, now };
222
+ return {
223
+ status: guestStatus(status, scope),
224
+ messages: guestMessages(replay(after ?? null), guest, scope),
225
+ deliveries: guestDeliveries(history, guest, scope),
226
+ reply_buttons: guestButtonStates(history, guest, scope),
227
+ prompts: [], needs: [],
228
+ cursor: history.pollCursor(),
229
+ now,
230
+ };
125
231
  }
126
232
  //# sourceMappingURL=web-guest-access.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"web-guest-access.js","sourceRoot":"","sources":["../src/web-guest-access.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAanD,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,MAAM,CAAU,CAAC;AACvC,MAAM,IAAI,GAAG,SAAS,CAAC;AAEvB,yEAAyE;AACzE,MAAM,CAAC,MAAM,YAAY,GAA0B;IACjD,iFAAiF;IACjF,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,wBAAwB,EAAE;IAClG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,MAAM,CAAC,aAAa,IAAI,GAAG,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,wDAAwD,EAAE;IAClK,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,6BAA6B,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,2BAA2B,EAAE;IAC5H,oHAAoH;IACpH,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,MAAM,CAAC,4BAA4B,IAAI,GAAG,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,mCAAmC,EAAE;IAC5J,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,MAAM,CAAC,cAAc,IAAI,4BAA4B,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,8BAA8B,EAAE;IAClK,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,MAAM,CAAC,2BAA2B,IAAI,GAAG,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,oCAAoC,EAAE;IAC9J,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,MAAM,CAAC,kBAAkB,IAAI,gBAAgB,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,+BAA+B,EAAE;IAC7J,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,wBAAwB,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,iDAAiD,EAAE;IAC9J,oGAAoG;IACpG,iHAAiH;IACjH,sFAAsF;IACtF,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,uDAAuD,EAAE;IAC3I,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,oDAAoD,EAAE;IACtI,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,qBAAqB,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,+EAA+E,EAAE;IACxK,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,2CAA2C,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,0CAA0C,EAAE;IAC5J,0FAA0F;IAC1F,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,+DAA+D,EAAE;IACxK,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,uDAAuD,EAAE;IAC7I,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,+BAA+B,EAAE;IACxI,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,sBAAsB,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,4CAA4C,EAAE;IAC1I,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,MAAM,CAAC,eAAe,IAAI,GAAG,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,2CAA2C,EAAE;IAC7J,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,wDAAwD,EAAE;IACtJ,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,mCAAmC,EAAE;CACpI,CAAC;AAMF,+FAA+F;AAC/F,SAAS,WAAW,CAAC,IAAY;IAC/B,MAAM,CAAC,GAAG,UAAU,CAAC,KAAK,EAAE,YAAY,IAAI,EAAE,CAAC,CAAC;IAChD,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AACvF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,GAAQ,EAAE,KAA0B;IACrF,MAAM,CAAC,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1C,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;QACjC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,SAAS;QACzC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI;YAAE,MAAM;QAChC,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC7D,MAAM,IAAI,GAAG,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAChI,IAAI,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;IAC3D,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;AACjE,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,WAAW,CAAC,CAAsE,EAAE,CAAsE;IACxK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,CAAC;AAC5E,CAAC;AAWD,MAAM,aAAa,GAAG,IAAI,OAAO,EAAwB,CAAC;AAC1D,sHAAsH;AACtH,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,KAAmB,IAAU,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AAC3G,MAAM,UAAU,cAAc,CAAC,GAAW,IAA8B,OAAO,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAExG;;;;GAIG;AACH,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,iBAAiB,CAAU,CAAC;AACnL,MAAM,UAAU,WAAW,CAAC,MAAe,EAAE,KAA0B;IACrE,MAAM,IAAI,GAAG,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAE,MAAkC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAE,MAAmC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IACxK,MAAM,SAAS,GAAmC,EAAE,CAAC;IACrD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,SAAS;QAC9C,MAAM,CAAC,GAAG,GAA8B,CAAC;QACzC,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;YAAE,SAAS;QAC/D,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,CAAC,IAAI,aAAa;YAAE,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS;gBAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnH,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,CAAC;AACvB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,IAAa,EAAE,KAA0B;IACrF,IAAI,KAAK,KAAK,QAAQ;QAAE,OAAO,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACxD,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAA+C,CAAC,CAAC,CAAC,EAAE,CAAC;QAClG,OAAO,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAChI,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,+GAA+G;AAC/G,MAAM,UAAU,aAAa,CAAC,MAAe,EAAE,KAA0B,EAAE,GAAW;IACpF,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;AAC5I,CAAC"}
1
+ {"version":3,"file":"web-guest-access.js","sourceRoot":"","sources":["../src/web-guest-access.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * #1920 §3.2: a guest's ClassicBot group or guild rooms — in scope only while its membership is verified.
3
+ *
4
+ * The answers are read in the background (at sign-in, every ten minutes, and when the guest's stream connects) and
5
+ * kept in memory; a request only reads them, never the platform. A room is shown only on a "member" answer at most
6
+ * 15 minutes old; an unknown, failed or stale answer hides it (fail closed).
7
+ *
8
+ * Revocation needs more than "hidden": a scope that becomes empty ends the session, and an answer not read yet (a
9
+ * restart, a room just created) must not end it. A key with no answer is pending for at most the stale window from
10
+ * when it was first wanted; after that, and after a "not a member" answer, it is settled.
11
+ */
12
+ import type { ClassicChannel } from "./classic-channel-manager.js";
13
+ export interface GuestOwner {
14
+ readonly adapterId: string;
15
+ readonly userId: string;
16
+ }
17
+ /** A ClassicBot room a guest may be a member of: a Telegram group or a Discord channel, on the guest's connection. */
18
+ export interface GuestRoom {
19
+ readonly instance: string;
20
+ readonly adapterId: string;
21
+ readonly channelId: string;
22
+ readonly kind: "telegram" | "discord";
23
+ }
24
+ /** The adapter's read: true a member, false not (a definite answer); a rejection or anything else is no answer. */
25
+ export type RoomMemberRead = (room: GuestRoom, userId: string) => Promise<boolean> | undefined;
26
+ export declare const GUEST_ROOM_RECHECK_MS: number;
27
+ export declare const GUEST_ROOM_STALE_MS: number;
28
+ export declare const GUEST_ROOM_FORCE_FLOOR_MS = 60000;
29
+ /** A read a request started (a pending guest polling or retrying): at most one per key in this long, whatever the volume. */
30
+ export declare const GUEST_ROOM_TRIGGER_FLOOR_MS = 30000;
31
+ /** Failed reads back off — a minute, then 2, 4, 8 … — up to ten minutes (a bot without the permission, or removed). */
32
+ export declare const GUEST_ROOM_RETRY_MS = 60000;
33
+ export declare const GUEST_ROOM_RETRY_MAX_MS: number;
34
+ /** Consecutive failures after which a key's failure is persistent: said once (onPersistentFailure), not every attempt. */
35
+ export declare const GUEST_ROOM_PERSISTENT_FAILURES = 3;
36
+ /** The background tick runs this often and reads only what is due. */
37
+ export declare const GUEST_ROOM_TICK_MS = 60000;
38
+ /**
39
+ * The group rooms on this guest's own connection. A Telegram private room (a positive id) is not here: it is the
40
+ * account's own room or someone else's, never a membership question.
41
+ */
42
+ export declare function guestGroupRooms(rooms: readonly ClassicChannel[], owner: GuestOwner): GuestRoom[];
43
+ /** Who reads: the background pass (what is due), a request of a pending guest (rate-limited), a stream connecting. */
44
+ export type GuestRoomReadMode = "scheduled" | "triggered" | "force";
45
+ export declare class GuestRoomMembership {
46
+ private readonly opts;
47
+ private readonly entries;
48
+ private readonly reads;
49
+ constructor(opts: {
50
+ now: () => number;
51
+ read: RoomMemberRead;
52
+ deadlineMs?: number;
53
+ staleMs?: number;
54
+ recheckMs?: number;
55
+ /** A key's reads keep failing (said once, until an answer); and when it answers again after that. */
56
+ onPersistentFailure?: (room: GuestRoom, failures: number) => void;
57
+ onRecovered?: (room: GuestRoom) => void;
58
+ });
59
+ private key;
60
+ private get staleMs();
61
+ /** Shown: a "member" answer no older than the stale window. */
62
+ verified(room: GuestRoom, userId: string): boolean;
63
+ /**
64
+ * Not settled yet: no definite answer, and first wanted less than the stale window ago (or never — a key nobody
65
+ * asked about yet is pending, and starts its window here). A pending room keeps an emptied scope from ending the
66
+ * session; it never shows the room.
67
+ */
68
+ pending(room: GuestRoom, userId: string): boolean;
69
+ /**
70
+ * Read this guest's rooms, one at a time; never rejects. One read per key at a time.
71
+ * - "scheduled": what is due (never asked; ten minutes after an answer; a failure's backoff).
72
+ * - "triggered" (a pending guest's request): the same, and never within 30 s of the key's last read, so a guest that
73
+ * polls or retries is not platform traffic.
74
+ * - "force" (its stream connected): a minute after the key's last read — but a failing key keeps its backoff.
75
+ */
76
+ refresh(owner: GuestOwner, rooms: readonly GuestRoom[], opts?: {
77
+ mode?: GuestRoomReadMode;
78
+ }): Promise<void>;
79
+ private ask;
80
+ private readBounded;
81
+ private put;
82
+ }
@@ -0,0 +1,135 @@
1
+ import { inferClassicChannelType } from "./classic-channel-manager.js";
2
+ export const GUEST_ROOM_RECHECK_MS = 10 * 60_000;
3
+ export const GUEST_ROOM_STALE_MS = 15 * 60_000;
4
+ export const GUEST_ROOM_FORCE_FLOOR_MS = 60_000;
5
+ /** A read a request started (a pending guest polling or retrying): at most one per key in this long, whatever the volume. */
6
+ export const GUEST_ROOM_TRIGGER_FLOOR_MS = 30_000;
7
+ /** Failed reads back off — a minute, then 2, 4, 8 … — up to ten minutes (a bot without the permission, or removed). */
8
+ export const GUEST_ROOM_RETRY_MS = 60_000;
9
+ export const GUEST_ROOM_RETRY_MAX_MS = 10 * 60_000;
10
+ /** Consecutive failures after which a key's failure is persistent: said once (onPersistentFailure), not every attempt. */
11
+ export const GUEST_ROOM_PERSISTENT_FAILURES = 3;
12
+ /** The background tick runs this often and reads only what is due. */
13
+ export const GUEST_ROOM_TICK_MS = 60_000;
14
+ const READ_DEADLINE_MS = 5_000;
15
+ /** The guest caps (4 per account, 64 in all) bound the owners; this bounds a fleet with very many rooms. */
16
+ const MAX_ENTRIES = 8192;
17
+ /**
18
+ * The group rooms on this guest's own connection. A Telegram private room (a positive id) is not here: it is the
19
+ * account's own room or someone else's, never a membership question.
20
+ */
21
+ export function guestGroupRooms(rooms, owner) {
22
+ const out = [];
23
+ for (const room of rooms) {
24
+ if (room.adapterId !== owner.adapterId)
25
+ continue;
26
+ const kind = inferClassicChannelType(room.channelId);
27
+ if (kind === "telegram" && room.channelId.trim().startsWith("-"))
28
+ out.push({ instance: room.instanceName, adapterId: room.adapterId, channelId: room.channelId, kind });
29
+ else if (kind === "discord")
30
+ out.push({ instance: room.instanceName, adapterId: room.adapterId, channelId: room.channelId, kind });
31
+ }
32
+ return out;
33
+ }
34
+ export class GuestRoomMembership {
35
+ opts;
36
+ entries = new Map();
37
+ reads = new Map();
38
+ constructor(opts) {
39
+ this.opts = opts;
40
+ }
41
+ key(room, userId) { return `${room.adapterId}\u0000${room.channelId}\u0000${userId}`; }
42
+ get staleMs() { return this.opts.staleMs ?? GUEST_ROOM_STALE_MS; }
43
+ /** Shown: a "member" answer no older than the stale window. */
44
+ verified(room, userId) {
45
+ const e = this.entries.get(this.key(room, userId));
46
+ return !!e && e.member === true && this.opts.now() - e.at <= this.staleMs;
47
+ }
48
+ /**
49
+ * Not settled yet: no definite answer, and first wanted less than the stale window ago (or never — a key nobody
50
+ * asked about yet is pending, and starts its window here). A pending room keeps an emptied scope from ending the
51
+ * session; it never shows the room.
52
+ */
53
+ pending(room, userId) {
54
+ const k = this.key(room, userId), now = this.opts.now();
55
+ let e = this.entries.get(k);
56
+ if (!e) {
57
+ e = { member: null, at: now, asked: Number.NEGATIVE_INFINITY, due: Number.NEGATIVE_INFINITY, failures: 0, reported: false };
58
+ this.put(k, e);
59
+ }
60
+ return e.member === null && now - e.at < this.staleMs;
61
+ }
62
+ /**
63
+ * Read this guest's rooms, one at a time; never rejects. One read per key at a time.
64
+ * - "scheduled": what is due (never asked; ten minutes after an answer; a failure's backoff).
65
+ * - "triggered" (a pending guest's request): the same, and never within 30 s of the key's last read, so a guest that
66
+ * polls or retries is not platform traffic.
67
+ * - "force" (its stream connected): a minute after the key's last read — but a failing key keeps its backoff.
68
+ */
69
+ async refresh(owner, rooms, opts = {}) {
70
+ const mode = opts.mode ?? "scheduled";
71
+ for (const room of rooms) {
72
+ const k = this.key(room, owner.userId), now = this.opts.now();
73
+ const e = this.entries.get(k);
74
+ // A read in flight is never repeated: a scheduled refresh waits for it; the others skip it (asked just now).
75
+ if (e) {
76
+ const sinceAsked = now - e.asked;
77
+ if (mode === "force" ? sinceAsked < GUEST_ROOM_FORCE_FLOOR_MS || (e.failures > 0 && now < e.due)
78
+ : now < e.due || (mode === "triggered" && sinceAsked < GUEST_ROOM_TRIGGER_FLOOR_MS))
79
+ continue;
80
+ }
81
+ await (this.reads.get(k) ?? this.ask(k, room, owner.userId));
82
+ }
83
+ }
84
+ ask(k, room, userId) {
85
+ const started = this.opts.now();
86
+ const existing = this.entries.get(k);
87
+ const recheck = this.opts.recheckMs ?? GUEST_ROOM_RECHECK_MS;
88
+ const fresh = { member: null, at: started, asked: started, due: started, failures: 0, reported: false };
89
+ this.put(k, existing ? { ...existing, asked: started } : fresh);
90
+ const read = this.readBounded(room, userId).then((member) => {
91
+ const e = this.entries.get(k) ?? fresh;
92
+ const now = this.opts.now();
93
+ if (member === undefined) {
94
+ // A failure leaves the last answer to age (and hide the room when stale), and backs off: 1, 2, 4 … 10 min.
95
+ const failures = e.failures + 1;
96
+ const reported = failures >= GUEST_ROOM_PERSISTENT_FAILURES; // an answer resets both
97
+ this.put(k, { ...e, failures, reported, due: now + Math.min(GUEST_ROOM_RETRY_MAX_MS, GUEST_ROOM_RETRY_MS * 2 ** (failures - 1)) });
98
+ if (reported && !e.reported)
99
+ this.opts.onPersistentFailure?.(room, failures);
100
+ return;
101
+ }
102
+ this.put(k, { member, at: now, asked: e.asked, due: now + recheck, failures: 0, reported: false });
103
+ if (e.reported)
104
+ this.opts.onRecovered?.(room);
105
+ }).finally(() => this.reads.delete(k));
106
+ this.reads.set(k, read);
107
+ return read;
108
+ }
109
+ readBounded(room, userId) {
110
+ return new Promise((resolve) => {
111
+ const timer = setTimeout(() => resolve(undefined), this.opts.deadlineMs ?? READ_DEADLINE_MS);
112
+ timer.unref?.();
113
+ let asked;
114
+ try {
115
+ asked = this.opts.read(room, userId);
116
+ }
117
+ catch {
118
+ asked = undefined;
119
+ }
120
+ if (!asked) {
121
+ clearTimeout(timer);
122
+ resolve(undefined);
123
+ return;
124
+ }
125
+ asked.then((m) => { clearTimeout(timer); resolve(m === true ? true : m === false ? false : undefined); }, () => { clearTimeout(timer); resolve(undefined); });
126
+ });
127
+ }
128
+ put(k, e) {
129
+ this.entries.delete(k); // re-insert: the map's order is its age, for the bound below
130
+ this.entries.set(k, e);
131
+ while (this.entries.size > MAX_ENTRIES)
132
+ this.entries.delete(this.entries.keys().next().value);
133
+ }
134
+ }
135
+ //# sourceMappingURL=web-guest-rooms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-guest-rooms.js","sourceRoot":"","sources":["../src/web-guest-rooms.ts"],"names":[],"mappings":"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"}
@@ -86,3 +86,50 @@ export declare class WebLoginCodes {
86
86
  private activeCode;
87
87
  private recordFailure;
88
88
  }
89
+ /** #1920 step 4: at most this many guest codes outstanding at once; past it a new one is refused, never someone's evicted. */
90
+ export declare const MAX_GUEST_LOGIN_CODES = 32;
91
+ export declare class GuestLoginCodes {
92
+ private readonly outstanding;
93
+ private failures;
94
+ private pausedUntil;
95
+ private readonly now;
96
+ private readonly generate;
97
+ private readonly onEvent;
98
+ constructor(opts?: WebLoginCodesOptions);
99
+ private key;
100
+ /** A code for this account, replacing its own outstanding one; null when MAX_GUEST_LOGIN_CODES others are outstanding. */
101
+ issue(opts: {
102
+ epoch: string;
103
+ recipient: LoginCodeRecipient;
104
+ audiences?: readonly string[];
105
+ }): IssuedLoginCode | null;
106
+ pausedForMs(): number;
107
+ /** This account's code is outstanding. */
108
+ hasCodeFor(r: {
109
+ adapterId: string;
110
+ userId: string;
111
+ }): boolean;
112
+ get size(): number;
113
+ revokeAll(): void;
114
+ /** A guest's own `/web revoke`: its code only. */
115
+ revokeRecipient(r: {
116
+ adapterId: string;
117
+ userId: string;
118
+ }): void;
119
+ revokeIfCurrent(issuanceId: string): void;
120
+ /** A public link closed: its codes no longer work through it (still on the other listeners they were for). */
121
+ revokeAudience(audience: string): void;
122
+ /**
123
+ * The guest code `input` is, spent — or null (no count: the caller asks the admins' codes next, and reports a code
124
+ * neither knows with recordWrong). Every outstanding code is compared, in constant time each. Paused: nothing matches.
125
+ */
126
+ match(input: string, currentEpoch: string, audience?: string): LoginRedeemResult | null;
127
+ /**
128
+ * A code that was neither a guest's nor an admin's: one wrong try against every outstanding guest code, and the
129
+ * breaker. As WebLoginCodes: nothing typed is not a guess, and with no guest code outstanding there is nothing to
130
+ * guess — it counts against nothing (#2093 review: else wrong codes could open this breaker, which pauses the admins'
131
+ * sign-in too, before any code exists). The breaker's history stays across codes.
132
+ */
133
+ recordWrong(input: string): void;
134
+ private prune;
135
+ }
package/dist/web-login.js CHANGED
@@ -135,4 +135,119 @@ export class WebLoginCodes {
135
135
  }
136
136
  }
137
137
  }
138
+ /** #1920 step 4: at most this many guest codes outstanding at once; past it a new one is refused, never someone's evicted. */
139
+ export const MAX_GUEST_LOGIN_CODES = 32;
140
+ export class GuestLoginCodes {
141
+ outstanding = new Map();
142
+ failures = [];
143
+ pausedUntil = 0;
144
+ now;
145
+ generate;
146
+ onEvent;
147
+ constructor(opts = {}) {
148
+ this.now = opts.now ?? Date.now;
149
+ this.generate = opts.generate ?? generateOneTimeCode;
150
+ this.onEvent = opts.onEvent ?? (() => { });
151
+ }
152
+ key(r) { return `${r.adapterId}\u0000${r.userId}`; }
153
+ /** A code for this account, replacing its own outstanding one; null when MAX_GUEST_LOGIN_CODES others are outstanding. */
154
+ issue(opts) {
155
+ this.prune();
156
+ const k = this.key(opts.recipient);
157
+ if (!this.outstanding.has(k) && this.outstanding.size >= MAX_GUEST_LOGIN_CODES)
158
+ return null;
159
+ const code = this.generate();
160
+ const expiresAt = this.now() + LOGIN_CODE_TTL_MS;
161
+ const issuanceId = randomBytes(16).toString("hex");
162
+ const audiences = opts.audiences?.length ? [...opts.audiences] : ["local"];
163
+ this.outstanding.set(k, { code, expiresAt, tier: "guest", epoch: opts.epoch, failures: 0, issuanceId, audience: audiences[0], audiences, recipient: opts.recipient });
164
+ this.onEvent("issued");
165
+ return { display: formatOneTimeCode(code), expiresAt, tier: "guest", issuanceId };
166
+ }
167
+ pausedForMs() { return Math.max(0, this.pausedUntil - this.now()); }
168
+ /** This account's code is outstanding. */
169
+ hasCodeFor(r) { this.prune(); return this.outstanding.has(this.key(r)); }
170
+ get size() { this.prune(); return this.outstanding.size; }
171
+ revokeAll() { this.outstanding.clear(); }
172
+ /** A guest's own `/web revoke`: its code only. */
173
+ revokeRecipient(r) { this.outstanding.delete(this.key(r)); }
174
+ revokeIfCurrent(issuanceId) {
175
+ for (const [k, o] of this.outstanding)
176
+ if (o.issuanceId === issuanceId)
177
+ this.outstanding.delete(k);
178
+ }
179
+ /** A public link closed: its codes no longer work through it (still on the other listeners they were for). */
180
+ revokeAudience(audience) {
181
+ for (const [k, o] of this.outstanding) {
182
+ if (!o.audiences.includes(audience))
183
+ continue;
184
+ const rest = o.audiences.filter(a => a !== audience);
185
+ if (rest.length)
186
+ this.outstanding.set(k, { ...o, audiences: rest, audience: rest[0] });
187
+ else
188
+ this.outstanding.delete(k);
189
+ }
190
+ }
191
+ /**
192
+ * The guest code `input` is, spent — or null (no count: the caller asks the admins' codes next, and reports a code
193
+ * neither knows with recordWrong). Every outstanding code is compared, in constant time each. Paused: nothing matches.
194
+ */
195
+ match(input, currentEpoch, audience = "local") {
196
+ if (this.now() < this.pausedUntil)
197
+ return null;
198
+ const provided = normalizeOneTimeCode(input);
199
+ if (!provided)
200
+ return null;
201
+ this.prune();
202
+ let hit = null;
203
+ for (const entry of this.outstanding) {
204
+ if (entry[1].epoch !== currentEpoch) {
205
+ this.outstanding.delete(entry[0]);
206
+ continue;
207
+ } // the token was rotated
208
+ if (constantTimeMatches(provided, entry[1].code) && entry[1].audiences.includes(audience))
209
+ hit = entry;
210
+ }
211
+ if (!hit)
212
+ return null;
213
+ this.outstanding.delete(hit[0]);
214
+ this.onEvent("spent");
215
+ return { kind: "ok", tier: "guest", recipient: hit[1].recipient };
216
+ }
217
+ /**
218
+ * A code that was neither a guest's nor an admin's: one wrong try against every outstanding guest code, and the
219
+ * breaker. As WebLoginCodes: nothing typed is not a guess, and with no guest code outstanding there is nothing to
220
+ * guess — it counts against nothing (#2093 review: else wrong codes could open this breaker, which pauses the admins'
221
+ * sign-in too, before any code exists). The breaker's history stays across codes.
222
+ */
223
+ recordWrong(input) {
224
+ if (!normalizeOneTimeCode(input))
225
+ return;
226
+ this.prune();
227
+ if (!this.outstanding.size)
228
+ return;
229
+ const now = this.now();
230
+ for (const [k, o] of this.outstanding) {
231
+ o.failures += 1;
232
+ if (o.failures >= MAX_LOGIN_CODE_ATTEMPTS) {
233
+ this.outstanding.delete(k);
234
+ this.onEvent("burned");
235
+ }
236
+ }
237
+ this.failures.push(now);
238
+ const cutoff = now - LOGIN_BREAKER_WINDOW_MS;
239
+ this.failures = this.failures.filter(t => t > cutoff);
240
+ if (this.failures.length >= LOGIN_BREAKER_THRESHOLD) {
241
+ this.pausedUntil = now + LOGIN_BREAKER_PAUSE_MS;
242
+ this.failures = [];
243
+ this.onEvent("breaker-open");
244
+ }
245
+ }
246
+ prune() {
247
+ const now = this.now();
248
+ for (const [k, o] of this.outstanding)
249
+ if (now >= o.expiresAt)
250
+ this.outstanding.delete(k);
251
+ }
252
+ }
138
253
  //# sourceMappingURL=web-login.js.map