@chaos-overlords/server 0.9.1 → 0.9.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 (53) hide show
  1. package/dist/app.d.ts.map +1 -1
  2. package/dist/app.js +4 -1
  3. package/dist/app.js.map +1 -1
  4. package/dist/configEnv.d.ts +22 -0
  5. package/dist/configEnv.d.ts.map +1 -0
  6. package/dist/configEnv.js +46 -0
  7. package/dist/configEnv.js.map +1 -0
  8. package/dist/container.d.ts +27 -1
  9. package/dist/container.d.ts.map +1 -1
  10. package/dist/container.js +16 -1
  11. package/dist/container.js.map +1 -1
  12. package/dist/http/errorHandler.js +5 -0
  13. package/dist/http/errorHandler.js.map +1 -1
  14. package/dist/http/middleware.d.ts +11 -0
  15. package/dist/http/middleware.d.ts.map +1 -1
  16. package/dist/http/middleware.js +28 -9
  17. package/dist/http/middleware.js.map +1 -1
  18. package/dist/http/types.d.ts +9 -4
  19. package/dist/http/types.d.ts.map +1 -1
  20. package/dist/index.d.ts +4 -1
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +4 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/routes/bugReports.d.ts.map +1 -1
  25. package/dist/routes/bugReports.js +17 -11
  26. package/dist/routes/bugReports.js.map +1 -1
  27. package/dist/routes/events.d.ts.map +1 -1
  28. package/dist/routes/events.js +17 -0
  29. package/dist/routes/events.js.map +1 -1
  30. package/dist/routes/lobby.d.ts.map +1 -1
  31. package/dist/routes/lobby.js +10 -1
  32. package/dist/routes/lobby.js.map +1 -1
  33. package/dist/sse/LocalEventHub.d.ts +23 -5
  34. package/dist/sse/LocalEventHub.d.ts.map +1 -1
  35. package/dist/sse/LocalEventHub.js +68 -15
  36. package/dist/sse/LocalEventHub.js.map +1 -1
  37. package/dist/sse/MatchLog.d.ts +6 -0
  38. package/dist/sse/MatchLog.d.ts.map +1 -1
  39. package/dist/sse/MatchLog.js +10 -0
  40. package/dist/sse/MatchLog.js.map +1 -1
  41. package/dist/sse/closeLog.d.ts +12 -0
  42. package/dist/sse/closeLog.d.ts.map +1 -0
  43. package/dist/sse/closeLog.js +21 -0
  44. package/dist/sse/closeLog.js.map +1 -0
  45. package/dist/sse/createSseResponse.d.ts +40 -1
  46. package/dist/sse/createSseResponse.d.ts.map +1 -1
  47. package/dist/sse/createSseResponse.js +79 -8
  48. package/dist/sse/createSseResponse.js.map +1 -1
  49. package/dist/sse/membership.d.ts +11 -0
  50. package/dist/sse/membership.d.ts.map +1 -0
  51. package/dist/sse/membership.js +13 -0
  52. package/dist/sse/membership.js.map +1 -0
  53. package/package.json +5 -5
package/dist/app.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAG3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAUlD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAQ1C,eAAO,MAAM,UAAU,YAAY,CAAA;AAInC,2FAA2F;AAC3F,wBAAgB,SAAS,CAAC,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,CAuBlE"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAG3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAWlD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAQ1C,eAAO,MAAM,UAAU,YAAY,CAAA;AAInC,2FAA2F;AAC3F,wBAAgB,SAAS,CAAC,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,CAuBlE"}
package/dist/app.js CHANGED
@@ -3,7 +3,7 @@ import { Hono } from 'hono';
3
3
  import { bodyLimit } from 'hono/body-limit';
4
4
  import { cors } from 'hono/cors';
5
5
  import { handleError } from './http/errorHandler';
6
- import { bearerAuth, bugReportRateLimited, memberRateLimited, rateLimited, requestId, } from './http/middleware';
6
+ import { bearerAuth, bugReportRateLimited, matchCreationRateLimited, memberRateLimited, rateLimited, requestId, } from './http/middleware';
7
7
  import { validateContractResponse } from './http/responseValidation';
8
8
  import { registerBugReportRoutes } from './routes/bugReports';
9
9
  import { registerEventRoutes } from './routes/events';
@@ -60,6 +60,8 @@ function apiRoutes() {
60
60
  registerProtocolRoutes(api);
61
61
  // The doors a stranger can knock on, throttled per client address.
62
62
  api.use('/matches', rateLimited, bodyLimit({ maxSize: LIMITS.gameSettingsBytes + SMALL_BODY }));
63
+ // Creating is also charged to one budget shared by every caller; browsing the same path is not.
64
+ api.on('POST', '/matches', matchCreationRateLimited);
63
65
  api.use('/matches/join', rateLimited, bodyLimit({ maxSize: SMALL_BODY }));
64
66
  // `use(path, ...)` matches the path verbatim, so neither of the two above covers this one. It is
65
67
  // a password-gated door like `/matches/join` and needs the same throttle and the same cap on a
@@ -79,6 +81,7 @@ function apiRoutes() {
79
81
  // parse a body of any size, a few hundred megabytes at a time, inside the same process that is
80
82
  // sealing every other match's turns.
81
83
  api.use('/matches/:matchId/settings', bodyLimit({ maxSize: LIMITS.gameSettingsBytes + SMALL_BODY }));
84
+ api.use('/matches/:matchId/profile', bodyLimit({ maxSize: SMALL_BODY }));
82
85
  api.use('/matches/:matchId/players/:playerId/takeover-vote', bodyLimit({ maxSize: SMALL_BODY }));
83
86
  api.use('/matches/:matchId/turns/:turn/orders', bodyLimit({ maxSize: LIMITS.ordersBytes }));
84
87
  api.use('/matches/:matchId/turns/:turn/report', bodyLimit({ maxSize: SMALL_BODY }));
package/dist/app.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAA;AACtE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,iBAAiB,EACjB,WAAW,EACX,SAAS,GACV,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAA;AAEpE,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAA;AACrF,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAEnD,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAA;AAEnC,MAAM,UAAU,GAAG,EAAE,GAAG,IAAI,CAAA;AAE5B,2FAA2F;AAC3F,MAAM,UAAU,SAAS,CAAC,SAA0B;IAClD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAU,CAAA;IAC9B,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IACxB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QAC7B,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;QAC7B,MAAM,IAAI,EAAE,CAAA;IACd,CAAC,CAAC,CAAA;IACF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;IACvB,IAAI,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5C,GAAG,CAAC,GAAG,CACL,GAAG,EACH,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC;YACzC,YAAY,EAAE,CAAC,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC;YAChE,aAAa,EAAE,CAAC,cAAc,CAAC;YAC/B,MAAM,EAAE,GAAG;SACZ,CAAC,CACH,CAAA;IACH,CAAC;IAED,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAC/C,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,SAAS,EAAE,CAAC,CAAA;IAClC,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,SAAS;IAChB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAU,CAAA;IAE9B,8FAA8F;IAC9F,+EAA+E;IAC/E,8FAA8F;IAC9F,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,wBAAwB,CAAC,CAAA;IAEtC,iGAAiG;IACjG,4FAA4F;IAC5F,8FAA8F;IAC9F,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,iBAAiB,CAAC,gBAAgB,GAAG,UAAU,EAAE,CAAC,CAAC,CAAA;IAErF,iGAAiG;IACjG,yEAAyE;IACzE,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAA;IACtE,sBAAsB,CAAC,GAAG,CAAC,CAAA;IAE3B,mEAAmE;IACnE,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,iBAAiB,GAAG,UAAU,EAAE,CAAC,CAAC,CAAA;IAC/F,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAA;IACzE,iGAAiG;IACjG,+FAA+F;IAC/F,sDAAsD;IACtD,GAAG,CAAC,GAAG,CAAC,uBAAuB,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAA;IACjF,iGAAiG;IACjG,wFAAwF;IACxF,GAAG,CAAC,GAAG,CACL,cAAc,EACd,oBAAoB,EACpB,SAAS,CAAC,EAAE,OAAO,EAAE,iBAAiB,CAAC,gBAAgB,GAAG,UAAU,EAAE,CAAC,CACxE,CAAA;IAED,yBAAyB,CAAC,GAAG,CAAC,CAAA;IAC9B,uBAAuB,CAAC,GAAG,CAAC,CAAA;IAE5B,+FAA+F;IAC/F,8FAA8F;IAC9F,2CAA2C;IAC3C,GAAG,CAAC,GAAG,CAAC,qBAAqB,EAAE,UAAU,EAAE,iBAAiB,EAAE,CAAC,CAAA;IAC/D,gGAAgG;IAChG,iGAAiG;IACjG,+FAA+F;IAC/F,qCAAqC;IACrC,GAAG,CAAC,GAAG,CACL,4BAA4B,EAC5B,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,iBAAiB,GAAG,UAAU,EAAE,CAAC,CAC9D,CAAA;IACD,GAAG,CAAC,GAAG,CAAC,mDAAmD,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAA;IAChG,GAAG,CAAC,GAAG,CAAC,sCAAsC,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;IAC3F,GAAG,CAAC,GAAG,CAAC,sCAAsC,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAA;IACnF,gGAAgG;IAChG,GAAG,CAAC,GAAG,CACL,6BAA6B,EAC7B,iBAAiB,CAAC,QAAQ,CAAC,EAC3B,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,mBAAmB,GAAG,UAAU,EAAE,CAAC,CAChE,CAAA;IAED,yBAAyB,CAAC,GAAG,CAAC,CAAA;IAC9B,kBAAkB,CAAC,GAAG,CAAC,CAAA;IACvB,sBAAsB,CAAC,GAAG,CAAC,CAAA;IAC3B,mBAAmB,CAAC,GAAG,CAAC,CAAA;IACxB,OAAO,GAAG,CAAA;AACZ,CAAC"}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Shared environment parsing for settings exposed by both server runtimes.
3
+ *
4
+ * Each parser takes the raw value as the runtime hands it over. On Node that is always a string; a
5
+ * Worker's `[vars]` entry written without quotes arrives as a number or a boolean instead, so the
6
+ * value is read through `String` rather than trusted to be one. `name`, when given, is put in front
7
+ * of a refusal so the log says which variable to fix.
8
+ */
9
+ type RawVar = string | number | boolean | undefined;
10
+ /**
11
+ * A whole number of at least `minimum`, or `fallback` when the variable is unset or empty.
12
+ *
13
+ * A rate limit of `0` is not "unlimited" and not "closed" — the limiter admits one call per window
14
+ * and refuses the rest, which nobody means — so every budget passes a floor of one, and the refusal
15
+ * names it rather than letting a misconfiguration run. Only decimal digits are read: `Number` would
16
+ * otherwise take a blank value as `0` and `0x10` or `1e3` as numbers nobody typed.
17
+ */
18
+ export declare function configInteger(raw: RawVar, fallback: number, minimum?: number, name?: string): number;
19
+ export declare function configFlag(raw: RawVar, fallback: boolean, name?: string): boolean;
20
+ export declare function configList(raw: RawVar): string[];
21
+ export {};
22
+ //# sourceMappingURL=configEnv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configEnv.d.ts","sourceRoot":"","sources":["../src/configEnv.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,KAAK,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;AAMnD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAI,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ/F;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAmBjF;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAKhD"}
@@ -0,0 +1,46 @@
1
+ function refuse(name, message) {
2
+ throw new Error(name ? `${name}: ${message}` : message);
3
+ }
4
+ /**
5
+ * A whole number of at least `minimum`, or `fallback` when the variable is unset or empty.
6
+ *
7
+ * A rate limit of `0` is not "unlimited" and not "closed" — the limiter admits one call per window
8
+ * and refuses the rest, which nobody means — so every budget passes a floor of one, and the refusal
9
+ * names it rather than letting a misconfiguration run. Only decimal digits are read: `Number` would
10
+ * otherwise take a blank value as `0` and `0x10` or `1e3` as numbers nobody typed.
11
+ */
12
+ export function configInteger(raw, fallback, minimum = 0, name) {
13
+ if (raw === undefined || raw === '')
14
+ return fallback;
15
+ const text = String(raw).trim();
16
+ const value = /^\d+$/.test(text) ? Number(text) : Number.NaN;
17
+ if (!Number.isSafeInteger(value) || value < minimum) {
18
+ refuse(name, `Expected an integer of at least ${minimum}, got "${String(raw)}"`);
19
+ }
20
+ return value;
21
+ }
22
+ export function configFlag(raw, fallback, name) {
23
+ if (raw === undefined || raw === '')
24
+ return fallback;
25
+ switch (String(raw).trim().toLowerCase()) {
26
+ case 'true':
27
+ case '1':
28
+ case 'yes':
29
+ case 'on':
30
+ return true;
31
+ case 'false':
32
+ case '0':
33
+ case 'no':
34
+ case 'off':
35
+ return false;
36
+ default:
37
+ return refuse(name, `Expected a boolean (true/false, 1/0, yes/no, on/off), got "${String(raw)}"`);
38
+ }
39
+ }
40
+ export function configList(raw) {
41
+ return String(raw ?? '')
42
+ .split(',')
43
+ .map((entry) => entry.trim())
44
+ .filter((entry) => entry.length > 0);
45
+ }
46
+ //# sourceMappingURL=configEnv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configEnv.js","sourceRoot":"","sources":["../src/configEnv.ts"],"names":[],"mappings":"AAUA,SAAS,MAAM,CAAC,IAAwB,EAAE,OAAe;IACvD,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;AACzD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,QAAgB,EAAE,OAAO,GAAG,CAAC,EAAE,IAAa;IACrF,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,QAAQ,CAAA;IACpD,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;IAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAA;IAC5D,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,OAAO,EAAE,CAAC;QACpD,MAAM,CAAC,IAAI,EAAE,mCAAmC,OAAO,UAAU,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAClF,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,QAAiB,EAAE,IAAa;IACtE,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,QAAQ,CAAA;IACpD,QAAQ,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QACzC,KAAK,MAAM,CAAC;QACZ,KAAK,GAAG,CAAC;QACT,KAAK,KAAK,CAAC;QACX,KAAK,IAAI;YACP,OAAO,IAAI,CAAA;QACb,KAAK,OAAO,CAAC;QACb,KAAK,GAAG,CAAC;QACT,KAAK,IAAI,CAAC;QACV,KAAK,KAAK;YACR,OAAO,KAAK,CAAA;QACd;YACE,OAAO,MAAM,CACX,IAAI,EACJ,8DAA8D,MAAM,CAAC,GAAG,CAAC,GAAG,CAC7E,CAAA;IACL,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;SACrB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;AACxC,CAAC"}
@@ -56,6 +56,17 @@ export interface RateLimiters {
56
56
  * part worth keeping.
57
57
  */
58
58
  bugReportState: RateLimiter;
59
+ /**
60
+ * Matches this process creates per window, from every caller together, under one key.
61
+ *
62
+ * The anonymous tier is per address, so it bounds one stranger and nothing about many. Each
63
+ * create is a stored lobby that lives until lobby retention collects it, and a PBKDF2 hash when it
64
+ * carries a password, so a flood from a few thousand addresses at the per-address rate would grow
65
+ * the matches table and hold the CPU without ever meeting a limit. This is the ceiling that
66
+ * distributed case meets. Joining and browsing are not charged here, so an existing lobby stays
67
+ * reachable while it is spent.
68
+ */
69
+ matchCreation: RateLimiter;
59
70
  }
60
71
  export interface ServerContainer {
61
72
  kernel: Kernel;
@@ -73,7 +84,16 @@ export interface ServerContainer {
73
84
  export declare const DEFAULT_SERVER_CONFIG: ServerConfig;
74
85
  /** Per-minute budgets. Generous for play, far below what a retry loop would spend. */
75
86
  export declare const DEFAULT_RATE_LIMITS: {
76
- readonly anonymousPerMinute: 30;
87
+ /**
88
+ * Unauthenticated calls (handshake, browse, create, join) per client address. Two a second.
89
+ *
90
+ * The address is often not one player: a household, a LAN party or a mobile carrier's CGNAT puts
91
+ * many behind it, and every lobby a player opens costs a handshake and a create, so thirty a
92
+ * minute was spent by a few hosts creating and cancelling lobbies. Nothing this tier protects
93
+ * needs it tighter: a join code is one of 2^40, a password has its own per-match budget, and a
94
+ * creation flood meets `matchCreationPerMinute` whatever addresses it comes from.
95
+ */
96
+ readonly anonymousPerMinute: 120;
77
97
  readonly memberPerMinute: 240;
78
98
  readonly uploadPerMinute: 10;
79
99
  /**
@@ -87,5 +107,11 @@ export declare const DEFAULT_RATE_LIMITS: {
87
107
  * of the default global budget, so no single address can crowd everybody else out of it.
88
108
  */
89
109
  readonly bugReportStatePerDay: 5;
110
+ /**
111
+ * Matches created per minute across every caller. Two a second is far beyond what players open by
112
+ * hand on any server this is likely to run, and caps a flood at under three thousand lobbies an
113
+ * hour for lobby retention to collect.
114
+ */
115
+ readonly matchCreationPerMinute: 120;
90
116
  };
91
117
  //# sourceMappingURL=container.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAE1C,MAAM,WAAW,YAAY;IAC3B;;;;;;;;OAQG;IACH,aAAa,EAAE,OAAO,CAAA;IACtB,+CAA+C;IAC/C,cAAc,EAAE,MAAM,CAAA;IACtB;;;;OAIG;IACH,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;CAC/B;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,WAAW,CAAA;IACtB,MAAM,EAAE,WAAW,CAAA;IACnB,MAAM,EAAE,WAAW,CAAA;IACnB;;;;;;;OAOG;IACH,SAAS,EAAE,WAAW,CAAA;IACtB;;;;;;;;;OASG;IACH,cAAc,EAAE,WAAW,CAAA;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAA;IAC7B,WAAW,EAAE,iBAAiB,CAAA;IAC9B,YAAY,EAAE,YAAY,CAAA;IAC1B,MAAM,EAAE,YAAY,CAAA;IACpB,wFAAwF;IACxF,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,MAAM,CAAA;CAC/C;AAED,eAAO,MAAM,qBAAqB,EAAE,YAInC,CAAA;AAED,sFAAsF;AACtF,eAAO,MAAM,mBAAmB;aAC9B,kBAAkB,EAAE,EAAE;aACtB,eAAe,EAAE,GAAG;aACpB,eAAe,EAAE,EAAE;IACnB;;;;OAIG;aACH,kBAAkB,EAAE,CAAC;IACrB;;;OAGG;aACH,oBAAoB,EAAE,CAAC;CACf,CAAA"}
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAE1C,MAAM,WAAW,YAAY;IAC3B;;;;;;;;OAQG;IACH,aAAa,EAAE,OAAO,CAAA;IACtB,+CAA+C;IAC/C,cAAc,EAAE,MAAM,CAAA;IACtB;;;;OAIG;IACH,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;CAC/B;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,WAAW,CAAA;IACtB,MAAM,EAAE,WAAW,CAAA;IACnB,MAAM,EAAE,WAAW,CAAA;IACnB;;;;;;;OAOG;IACH,SAAS,EAAE,WAAW,CAAA;IACtB;;;;;;;;;OASG;IACH,cAAc,EAAE,WAAW,CAAA;IAC3B;;;;;;;;;OASG;IACH,aAAa,EAAE,WAAW,CAAA;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAA;IAC7B,WAAW,EAAE,iBAAiB,CAAA;IAC9B,YAAY,EAAE,YAAY,CAAA;IAC1B,MAAM,EAAE,YAAY,CAAA;IACpB,wFAAwF;IACxF,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,MAAM,CAAA;CAC/C;AAED,eAAO,MAAM,qBAAqB,EAAE,YAInC,CAAA;AAED,sFAAsF;AACtF,eAAO,MAAM,mBAAmB;IAC9B;;;;;;;;OAQG;aACH,kBAAkB,EAAE,GAAG;aACvB,eAAe,EAAE,GAAG;aACpB,eAAe,EAAE,EAAE;IACnB;;;;OAIG;aACH,kBAAkB,EAAE,CAAC;IACrB;;;OAGG;aACH,oBAAoB,EAAE,CAAC;IACvB;;;;OAIG;aACH,sBAAsB,EAAE,GAAG;CACnB,CAAA"}
package/dist/container.js CHANGED
@@ -5,7 +5,16 @@ export const DEFAULT_SERVER_CONFIG = {
5
5
  };
6
6
  /** Per-minute budgets. Generous for play, far below what a retry loop would spend. */
7
7
  export const DEFAULT_RATE_LIMITS = {
8
- anonymousPerMinute: 30,
8
+ /**
9
+ * Unauthenticated calls (handshake, browse, create, join) per client address. Two a second.
10
+ *
11
+ * The address is often not one player: a household, a LAN party or a mobile carrier's CGNAT puts
12
+ * many behind it, and every lobby a player opens costs a handshake and a create, so thirty a
13
+ * minute was spent by a few hosts creating and cancelling lobbies. Nothing this tier protects
14
+ * needs it tighter: a join code is one of 2^40, a password has its own per-match budget, and a
15
+ * creation flood meets `matchCreationPerMinute` whatever addresses it comes from.
16
+ */
17
+ anonymousPerMinute: 120,
9
18
  memberPerMinute: 240,
10
19
  uploadPerMinute: 10,
11
20
  /**
@@ -19,5 +28,11 @@ export const DEFAULT_RATE_LIMITS = {
19
28
  * of the default global budget, so no single address can crowd everybody else out of it.
20
29
  */
21
30
  bugReportStatePerDay: 5,
31
+ /**
32
+ * Matches created per minute across every caller. Two a second is far beyond what players open by
33
+ * hand on any server this is likely to run, and caps a flood at under three thousand lobbies an
34
+ * hour for lobby retention to collect.
35
+ */
36
+ matchCreationPerMinute: 120,
22
37
  };
23
38
  //# sourceMappingURL=container.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"container.js","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"AA4EA,MAAM,CAAC,MAAM,qBAAqB,GAAiB;IACjD,aAAa,EAAE,IAAI;IACnB,cAAc,EAAE,MAAM;IACtB,WAAW,EAAE,EAAE;CAChB,CAAA;AAED,sFAAsF;AACtF,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,kBAAkB,EAAE,EAAE;IACtB,eAAe,EAAE,GAAG;IACpB,eAAe,EAAE,EAAE;IACnB;;;;OAIG;IACH,kBAAkB,EAAE,CAAC;IACrB;;;OAGG;IACH,oBAAoB,EAAE,CAAC;CACf,CAAA"}
1
+ {"version":3,"file":"container.js","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"AAuFA,MAAM,CAAC,MAAM,qBAAqB,GAAiB;IACjD,aAAa,EAAE,IAAI;IACnB,cAAc,EAAE,MAAM;IACtB,WAAW,EAAE,EAAE;CAChB,CAAA;AAED,sFAAsF;AACtF,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC;;;;;;;;OAQG;IACH,kBAAkB,EAAE,GAAG;IACvB,eAAe,EAAE,GAAG;IACpB,eAAe,EAAE,EAAE;IACnB;;;;OAIG;IACH,kBAAkB,EAAE,CAAC;IACrB;;;OAGG;IACH,oBAAoB,EAAE,CAAC;IACvB;;;;OAIG;IACH,sBAAsB,EAAE,GAAG;CACnB,CAAA"}
@@ -94,6 +94,11 @@ function codeForStatus(status) {
94
94
  }
95
95
  function respond(c, { code, message, details, requestId }) {
96
96
  const body = { error: { code, message, details, requestId } };
97
+ // Hono carries every header already set on this context onto the error response that replaces
98
+ // a handler's, so a caching policy the handler chose for its success (the sealed-order set's
99
+ // `immutable`, say) would otherwise be applied to the refusal. It must be overwritten on the
100
+ // context itself: the `c.res` setter copies the previous response's headers over the new one.
101
+ c.header('Cache-Control', 'no-store');
97
102
  return c.json(validateSync(errorEnvelopeSchema, body), STATUS_BY_CODE[code]);
98
103
  }
99
104
  //# sourceMappingURL=errorHandler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../src/http/errorHandler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../src/http/errorHandler.ts"],"names":[],"mappings":"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"}
@@ -25,6 +25,17 @@ export declare const rateLimited: MiddlewareHandler<AppEnv>;
25
25
  * one must not be able to exhaust the other.
26
26
  */
27
27
  export declare const bugReportRateLimited: MiddlewareHandler<AppEnv>;
28
+ /**
29
+ * The process-wide budget on creating a match, checked here and spent by the create handler.
30
+ *
31
+ * Mounted for `POST /matches` alone, because the same path also serves the public listing, which
32
+ * must not spend it. It runs after `rateLimited`, so a single address over its own budget is
33
+ * refused without touching the shared one. It only PEEKS: a spent budget is refused before the
34
+ * body is read, but a request is charged only once its body has passed the contract validator,
35
+ * through `spendMatchCreation`. Charging here would let a handful of addresses sending malformed
36
+ * bodies, which never store a lobby, hold the shared budget at zero for every legitimate host.
37
+ */
38
+ export declare const matchCreationRateLimited: MiddlewareHandler<AppEnv>;
28
39
  /**
29
40
  * Limiter for an authenticated member, keyed by player rather than address so one player on a shared
30
41
  * address cannot spend another's budget. Must run after `bearerAuth`.
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/http/middleware.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,iBAAiB,CAAC,MAAM,CAK/C,CAAA;AAgBD;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,EAAE,iBAAiB,CAAC,MAAM,CAgBhD,CAAA;AAgBD,kFAAkF;AAClF,eAAO,MAAM,WAAW,EAAE,iBAAiB,CAAC,MAAM,CAOjD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,iBAAiB,CAAC,MAAM,CAe1D,CAAA;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,MAAM,YAAuB,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAMhG;AAQD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAoBpD;AAmED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAClC,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAClB,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,MAAM,CAaR"}
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/http/middleware.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,iBAAiB,CAAC,MAAM,CAK/C,CAAA;AAgBD;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,EAAE,iBAAiB,CAAC,MAAM,CAgBhD,CAAA;AAgBD,kFAAkF;AAClF,eAAO,MAAM,WAAW,EAAE,iBAAiB,CAAC,MAAM,CAOjD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,iBAAiB,CAAC,MAAM,CAU1D,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB,EAAE,iBAAiB,CAAC,MAAM,CAM9D,CAAA;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,MAAM,YAAuB,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAMhG;AAQD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAoBpD;AAyED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAClC,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAClB,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,MAAM,CAaR"}
@@ -82,12 +82,27 @@ export const bugReportRateLimited = async (c, next) => {
82
82
  const container = c.get('container');
83
83
  const key = addressOf(c);
84
84
  enforce(container.rateLimiters, 'bugReport', key, c);
85
- // The daily journal budget is NOT spent here. It used to be, before the body had even been read,
86
- // so five text-only reports or five requests the contract validator answered 413 or 422 for spent
87
- // it, and the sixth — the one that actually carried a journal — was quietly filed with
88
- // `stateStored: 'omitted'`. Everyone behind one NAT shares those five. The handler spends it
89
- // instead, once it knows there is a journal to spend it on; see the bug report route.
90
- c.set('bugReportJournalBudget', () => container.rateLimiters.bugReportState.take(`bugReportState:${rateLimitKey(key)}`) === null);
85
+ // The handler reserves one unit only for a validated report carrying a journal, then releases it
86
+ // if the journal fails its digest check or is omitted by the storage budget.
87
+ c.set('bugReportJournalBudget', () => container.rateLimiters.bugReportState.reserve(`bugReportState:${rateLimitKey(key)}`));
88
+ await next();
89
+ };
90
+ /**
91
+ * The process-wide budget on creating a match, checked here and spent by the create handler.
92
+ *
93
+ * Mounted for `POST /matches` alone, because the same path also serves the public listing, which
94
+ * must not spend it. It runs after `rateLimited`, so a single address over its own budget is
95
+ * refused without touching the shared one. It only PEEKS: a spent budget is refused before the
96
+ * body is read, but a request is charged only once its body has passed the contract validator,
97
+ * through `spendMatchCreation`. Charging here would let a handful of addresses sending malformed
98
+ * bodies, which never store a lobby, hold the shared budget at zero for every legitimate host.
99
+ */
100
+ export const matchCreationRateLimited = async (c, next) => {
101
+ const limiters = c.get('container').rateLimiters;
102
+ const retryAfter = limiters.matchCreation.peek(`matchCreation:${MATCH_CREATION_KEY}`);
103
+ if (retryAfter !== null)
104
+ refuse(c, retryAfter);
105
+ c.set('spendMatchCreation', () => enforce(limiters, 'matchCreation', MATCH_CREATION_KEY, c));
91
106
  await next();
92
107
  };
93
108
  /**
@@ -187,11 +202,15 @@ function ipv6Prefix64(address) {
187
202
  * `rateLimitKey` masks IPv6 prefixes and strips ports, which is meaningless work on a player UUID
188
203
  * and runs on every authenticated request.
189
204
  */
190
- const IDENTITY_TIERS = new Set(['member', 'upload']);
205
+ const IDENTITY_TIERS = new Set(['member', 'upload', 'matchCreation']);
206
+ /** The one key the match-creation tier counts under; it is a process-wide budget, not a per-caller one. */
207
+ const MATCH_CREATION_KEY = 'all';
191
208
  function enforce(limiters, tier, key, c) {
192
209
  const retryAfter = limiters[tier].take(`${tier}:${IDENTITY_TIERS.has(tier) ? key : rateLimitKey(key)}`);
193
- if (retryAfter === null)
194
- return;
210
+ if (retryAfter !== null)
211
+ refuse(c, retryAfter);
212
+ }
213
+ function refuse(c, retryAfter) {
195
214
  c.header('Retry-After', String(retryAfter));
196
215
  throw new RateLimitedError('Too many attempts; slow down', {
197
216
  reason: 'rate_limited',
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/http/middleware.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/http/middleware.ts"],"names":[],"mappings":"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"}
@@ -15,11 +15,16 @@ export interface AppEnv {
15
15
  */
16
16
  caller?: string;
17
17
  /**
18
- * Spends one unit of this caller's daily attached-journal budget and says whether there was
19
- * any left. Set by `bugReportRateLimited`, called by the handler and only for a report that
20
- * actually carries a journal; absent everywhere else.
18
+ * Reserves one unit of this caller's daily attached-journal budget. Returns a release function
19
+ * when allowed, or null when spent. The handler releases it unless the journal is stored.
21
20
  */
22
- bugReportJournalBudget?: () => boolean;
21
+ bugReportJournalBudget?: () => (() => void) | null;
22
+ /**
23
+ * Spends one unit of the process-wide match-creation budget, or throws the 429 when it is gone.
24
+ * Set by `matchCreationRateLimited`, called by the create handler once the body has validated;
25
+ * absent everywhere else.
26
+ */
27
+ spendMatchCreation?: () => void;
23
28
  /**
24
29
  * The object a contract handler answered with, recorded by `contractJson` so the response
25
30
  * validator can check it without parsing the body back out. Wrapped so that a handler
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/http/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAEnD,MAAM,WAAW,MAAM;IACrB,SAAS,EAAE;QACT,SAAS,EAAE,eAAe,CAAA;QAC1B,SAAS,EAAE,MAAM,CAAA;QACjB,SAAS,EAAE,SAAS,CAAA;QACpB,wFAAwF;QACxF,WAAW,CAAC,EAAE,WAAW,CAAA;QACzB;;;;WAIG;QACH,MAAM,CAAC,EAAE,MAAM,CAAA;QACf;;;;WAIG;QACH,sBAAsB,CAAC,EAAE,MAAM,OAAO,CAAA;QACtC;;;;WAIG;QACH,YAAY,CAAC,EAAE;YAAE,KAAK,EAAE,OAAO,CAAA;SAAE,CAAA;KAClC,CAAA;CACF"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/http/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAEnD,MAAM,WAAW,MAAM;IACrB,SAAS,EAAE;QACT,SAAS,EAAE,eAAe,CAAA;QAC1B,SAAS,EAAE,MAAM,CAAA;QACjB,SAAS,EAAE,SAAS,CAAA;QACpB,wFAAwF;QACxF,WAAW,CAAC,EAAE,WAAW,CAAA;QACzB;;;;WAIG;QACH,MAAM,CAAC,EAAE,MAAM,CAAA;QACf;;;WAGG;QACH,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;QAClD;;;;WAIG;QACH,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAA;QAC/B;;;;WAIG;QACH,YAAY,CAAC,EAAE;YAAE,KAAK,EAAE,OAAO,CAAA;SAAE,CAAA;KAClC,CAAA;CACF"}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,11 @@
1
1
  export { API_PREFIX, createApp } from './app';
2
+ export { configFlag, configInteger, configList } from './configEnv';
2
3
  export { DEFAULT_RATE_LIMITS, DEFAULT_SERVER_CONFIG, type RateLimiters, type ServerConfig, type ServerContainer, } from './container';
3
4
  export { bugReportRateLimited, defaultClientAddress, rateLimitKey } from './http/middleware';
4
5
  export type { AppEnv } from './http/types';
5
- export { createSseResponse, type EventStreamSource, formatEvent, isReadableEvent, } from './sse/createSseResponse';
6
+ export { createSseResponse, type EventStreamSource, formatEvent, type HubCloseReason, isReadableEvent, isUnexpectedClose, type SseCloseReason, } from './sse/createSseResponse';
7
+ export { logStreamClosed } from './sse/closeLog';
6
8
  export { type EventFrame, MatchLog } from './sse/MatchLog';
9
+ export { isActiveMember } from './sse/membership';
7
10
  export { DEFAULT_EVENT_HUB_LIMITS, type EventHubLimits, type EventHubObserver, LocalEventHub, } from './sse/LocalEventHub';
8
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAC7C,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,eAAe,GACrB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAC5F,YAAY,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EACL,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,WAAW,EACX,eAAe,GAChB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,KAAK,UAAU,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EACL,wBAAwB,EACxB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,aAAa,GACd,MAAM,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACnE,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,eAAe,GACrB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAC5F,YAAY,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EACL,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,WAAW,EACX,KAAK,cAAc,EACnB,eAAe,EACf,iBAAiB,EACjB,KAAK,cAAc,GACpB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EAAE,KAAK,UAAU,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EACL,wBAAwB,EACxB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,aAAa,GACd,MAAM,qBAAqB,CAAA"}
package/dist/index.js CHANGED
@@ -1,7 +1,10 @@
1
1
  export { API_PREFIX, createApp } from './app';
2
+ export { configFlag, configInteger, configList } from './configEnv';
2
3
  export { DEFAULT_RATE_LIMITS, DEFAULT_SERVER_CONFIG, } from './container';
3
4
  export { bugReportRateLimited, defaultClientAddress, rateLimitKey } from './http/middleware';
4
- export { createSseResponse, formatEvent, isReadableEvent, } from './sse/createSseResponse';
5
+ export { createSseResponse, formatEvent, isReadableEvent, isUnexpectedClose, } from './sse/createSseResponse';
6
+ export { logStreamClosed } from './sse/closeLog';
5
7
  export { MatchLog } from './sse/MatchLog';
8
+ export { isActiveMember } from './sse/membership';
6
9
  export { DEFAULT_EVENT_HUB_LIMITS, LocalEventHub, } from './sse/LocalEventHub';
7
10
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAC7C,OAAO,EACL,mBAAmB,EACnB,qBAAqB,GAItB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAE5F,OAAO,EACL,iBAAiB,EAEjB,WAAW,EACX,eAAe,GAChB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAmB,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EACL,wBAAwB,EAGxB,aAAa,GACd,MAAM,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACnE,OAAO,EACL,mBAAmB,EACnB,qBAAqB,GAItB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAE5F,OAAO,EACL,iBAAiB,EAEjB,WAAW,EAEX,eAAe,EACf,iBAAiB,GAElB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EAAmB,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EACL,wBAAwB,EAGxB,aAAa,GACd,MAAM,qBAAqB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"bugReports.d.ts","sourceRoot":"","sources":["../../src/routes/bugReports.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAGhC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAE3C;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAqB/D"}
1
+ {"version":3,"file":"bugReports.d.ts","sourceRoot":"","sources":["../../src/routes/bugReports.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAGhC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAE3C;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAyB/D"}
@@ -19,17 +19,23 @@ export function registerBugReportRoutes(api) {
19
19
  });
20
20
  }
21
21
  const request = c.req.valid('json');
22
- // The daily journal budget is spent HERE: after the contract has validated the body, and only
23
- // when there is a journal to spend it on. Charging it in the middleware meant five text-only
24
- // reports, or five bodies the validator refused, used up the day's allowance for everyone
25
- // behind one address — and the sixth report, the one carrying the journal somebody wanted, was
26
- // filed without it and said so only in the receipt.
27
- //
28
- // An address that really has spent it files the description without the journal, and the
29
- // receipt says `omitted` — the same outcome the global byte budget produces.
30
- const allowed = request.state === undefined || (c.get('bugReportJournalBudget')?.() ?? true);
31
- const submitted = allowed ? request : { ...request, state: undefined };
32
- return c.json(answering(c, await bugReports.submit(submitted)), 201);
22
+ const release = request.state === undefined ? undefined : c.get('bugReportJournalBudget')?.();
23
+ const denied = release === null;
24
+ const submitted = denied ? { ...request, state: undefined } : request;
25
+ let stored = false;
26
+ try {
27
+ const receipt = await bugReports.submit(submitted);
28
+ stored = receipt.stateStored === 'stored';
29
+ // The intake sees no journal when this address is spent, but the client did send one.
30
+ return c.json(answering(c, denied ? { ...receipt, stateStored: 'omitted' } : receipt), 201);
31
+ }
32
+ finally {
33
+ // A digest refusal, global-byte omission, row failure, or any other non-storage outcome
34
+ // cannot spend the caller's allowance. The reservation is per request and safe to release
35
+ // even if another request has since entered the same address window.
36
+ if (!stored)
37
+ release?.();
38
+ }
33
39
  });
34
40
  }
35
41
  //# sourceMappingURL=bugReports.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bugReports.js","sourceRoot":"","sources":["../../src/routes/bugReports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAA;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAEvD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAG/C;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CAAC,GAAiB;IACvD,cAAc,CAAC,GAAG,EAAE,uBAAuB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACvD,MAAM,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACzC,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,aAAa,CAAC,yCAAyC,EAAE;gBACjE,MAAM,EAAE,sBAAsB;aAC/B,CAAC,CAAA;QACJ,CAAC;QACD,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QACnC,8FAA8F;QAC9F,6FAA6F;QAC7F,0FAA0F;QAC1F,+FAA+F;QAC/F,oDAAoD;QACpD,EAAE;QACF,yFAAyF;QACzF,6EAA6E;QAC7E,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,wBAAwB,CAAC,EAAE,EAAE,IAAI,IAAI,CAAC,CAAA;QAC5F,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;QACtE,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IACtE,CAAC,CAAC,CAAA;AACJ,CAAC"}
1
+ {"version":3,"file":"bugReports.js","sourceRoot":"","sources":["../../src/routes/bugReports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAA;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAEvD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAG/C;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CAAC,GAAiB;IACvD,cAAc,CAAC,GAAG,EAAE,uBAAuB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACvD,MAAM,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACzC,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,aAAa,CAAC,yCAAyC,EAAE;gBACjE,MAAM,EAAE,sBAAsB;aAC/B,CAAC,CAAA;QACJ,CAAC;QACD,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QACnC,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,wBAAwB,CAAC,EAAE,EAAE,CAAA;QAC7F,MAAM,MAAM,GAAG,OAAO,KAAK,IAAI,CAAA;QAC/B,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,OAAO,CAAA;QACrE,IAAI,MAAM,GAAG,KAAK,CAAA;QAClB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;YAClD,MAAM,GAAG,OAAO,CAAC,WAAW,KAAK,QAAQ,CAAA;YACzC,sFAAsF;YACtF,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAA;QAC7F,CAAC;gBAAS,CAAC;YACT,wFAAwF;YACxF,0FAA0F;YAC1F,qEAAqE;YACrE,IAAI,CAAC,MAAM;gBAAE,OAAO,EAAE,EAAE,CAAA;QAC1B,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/routes/events.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAIhC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAG3C,4FAA4F;AAC5F,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CA0C3D"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/routes/events.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAIhC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAI3C,4FAA4F;AAC5F,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CA2D3D"}
@@ -1,8 +1,10 @@
1
1
  import { INT32_MAX, listEventsContract, streamEventsContract } from '@chaos-overlords/contracts';
2
+ import { UnauthorizedError } from '@chaos-overlords/kernel';
2
3
  import { answering } from '../http/contractJson';
3
4
  import { requireMember } from '../http/guards';
4
5
  import { buildHonoRoute } from '../http/routes';
5
6
  import { isReadableEvent } from '../sse/createSseResponse';
7
+ import { isActiveMember } from '../sse/membership';
6
8
  /** The event log: a paged REST read (the fallback) and the SSE stream over the same log. */
7
9
  export function registerEventRoutes(api) {
8
10
  buildHonoRoute(api, listEventsContract, async (c) => {
@@ -36,7 +38,22 @@ export function registerEventRoutes(api) {
36
38
  playerId: principal.player.id,
37
39
  afterSeq,
38
40
  signal: c.req.raw.signal,
41
+ lobby: principal.match.status === 'lobby',
39
42
  });
43
+ // The kick may have revoked the token and run hangUp after bearerAuth but before the hub
44
+ // subscribed. That hangUp saw no listener. Re-read the row after open and cancel the new stream
45
+ // before returning any of its buffered frames when the membership is already gone.
46
+ let stillMember = false;
47
+ try {
48
+ stillMember = await isActiveMember(c.get('container').kernel.deps.storage.players, principal.match.id, principal.player.id);
49
+ }
50
+ finally {
51
+ if (!stillMember)
52
+ await stream.body?.cancel();
53
+ }
54
+ if (!stillMember) {
55
+ throw new UnauthorizedError('Invalid or expired player token', { reason: 'invalid_token' });
56
+ }
40
57
  // The stream is a raw `Response`, and Hono does not merge the headers the middleware prepared
41
58
  // into one of those — so the one response an operator most wants to correlate, a stream that
42
59
  // misbehaved for an hour, was the only one without an `X-Request-Id`.
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/routes/events.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/routes/events.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"lobby.d.ts","sourceRoot":"","sources":["../../src/routes/lobby.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAIhC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAE3C;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAgCjE;AAED,4DAA4D;AAC5D,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CA8DjE"}
1
+ {"version":3,"file":"lobby.d.ts","sourceRoot":"","sources":["../../src/routes/lobby.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAIhC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAE3C;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAmCjE;AAED,4DAA4D;AAC5D,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAwEjE"}
@@ -1,4 +1,4 @@
1
- import { createMatchContract, getMatchContract, joinMatchContract, joinRunningMatchContract, kickPlayerContract, leaveMatchContract, listLobbiesContract, rejoinMatchContract, startMatchContract, takeoverVoteContract, updateMatchSettingsContract, } from '@chaos-overlords/contracts';
1
+ import { createMatchContract, getMatchContract, joinMatchContract, joinRunningMatchContract, kickPlayerContract, leaveMatchContract, listLobbiesContract, rejoinMatchContract, startMatchContract, takeoverVoteContract, updateMatchSettingsContract, updatePlayerProfileContract, } from '@chaos-overlords/contracts';
2
2
  import { NotFoundError } from '@chaos-overlords/kernel';
3
3
  import { answering } from '../http/contractJson';
4
4
  import { requireMember } from '../http/guards';
@@ -21,6 +21,9 @@ export function registerPublicLobbyRoutes(api) {
21
21
  return c.json(answering(c, { matches: await kernel.query.listPublicLobbies(50) }), 200);
22
22
  });
23
23
  buildHonoRoute(api, createMatchContract, async (c) => {
24
+ // Charged here, after the contract validator, so a body that was never going to store a lobby
25
+ // does not spend the budget every host shares; `matchCreationRateLimited` only checks it.
26
+ c.get('spendMatchCreation')?.();
24
27
  const membership = await c.get('container').kernel.lobby.createMatch(c.req.valid('json'));
25
28
  return c.json(answering(c, membership), 201);
26
29
  });
@@ -63,6 +66,12 @@ export function registerMemberLobbyRoutes(api) {
63
66
  .kernel.lobby.updateSettings(requireMember(c.get('principal'), c.req.valid('param').matchId), c.req.valid('json'));
64
67
  return c.body(null, 204);
65
68
  });
69
+ buildHonoRoute(api, updatePlayerProfileContract, async (c) => {
70
+ await c
71
+ .get('container')
72
+ .kernel.lobby.updateProfile(requireMember(c.get('principal'), c.req.valid('param').matchId), c.req.valid('json'));
73
+ return c.body(null, 204);
74
+ });
66
75
  buildHonoRoute(api, leaveMatchContract, async (c) => {
67
76
  await c
68
77
  .get('container')