@chaos-overlords/server 0.9.1 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +3 -1
- package/dist/app.js.map +1 -1
- package/dist/configEnv.d.ts +22 -0
- package/dist/configEnv.d.ts.map +1 -0
- package/dist/configEnv.js +46 -0
- package/dist/configEnv.js.map +1 -0
- package/dist/container.d.ts +17 -0
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +6 -0
- package/dist/container.js.map +1 -1
- package/dist/http/errorHandler.js +5 -0
- package/dist/http/errorHandler.js.map +1 -1
- package/dist/http/middleware.d.ts +11 -0
- package/dist/http/middleware.d.ts.map +1 -1
- package/dist/http/middleware.js +28 -9
- package/dist/http/middleware.js.map +1 -1
- package/dist/http/types.d.ts +9 -4
- package/dist/http/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/routes/bugReports.d.ts.map +1 -1
- package/dist/routes/bugReports.js +17 -11
- package/dist/routes/bugReports.js.map +1 -1
- package/dist/routes/events.d.ts.map +1 -1
- package/dist/routes/events.js +17 -0
- package/dist/routes/events.js.map +1 -1
- package/dist/routes/lobby.d.ts.map +1 -1
- package/dist/routes/lobby.js +3 -0
- package/dist/routes/lobby.js.map +1 -1
- package/dist/sse/LocalEventHub.d.ts +15 -5
- package/dist/sse/LocalEventHub.d.ts.map +1 -1
- package/dist/sse/LocalEventHub.js +56 -10
- package/dist/sse/LocalEventHub.js.map +1 -1
- package/dist/sse/MatchLog.d.ts +6 -0
- package/dist/sse/MatchLog.d.ts.map +1 -1
- package/dist/sse/MatchLog.js +10 -0
- package/dist/sse/MatchLog.js.map +1 -1
- package/dist/sse/createSseResponse.d.ts +2 -0
- package/dist/sse/createSseResponse.d.ts.map +1 -1
- package/dist/sse/createSseResponse.js +22 -0
- package/dist/sse/createSseResponse.js.map +1 -1
- package/dist/sse/membership.d.ts +11 -0
- package/dist/sse/membership.d.ts.map +1 -0
- package/dist/sse/membership.js +13 -0
- package/dist/sse/membership.js.map +1 -0
- 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;
|
|
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
|
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"}
|
package/dist/container.d.ts
CHANGED
|
@@ -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;
|
|
@@ -87,5 +98,11 @@ export declare const DEFAULT_RATE_LIMITS: {
|
|
|
87
98
|
* of the default global budget, so no single address can crowd everybody else out of it.
|
|
88
99
|
*/
|
|
89
100
|
readonly bugReportStatePerDay: 5;
|
|
101
|
+
/**
|
|
102
|
+
* Matches created per minute across every caller. Two a second is far beyond what players open by
|
|
103
|
+
* hand on any server this is likely to run, and caps a flood at under three thousand lobbies an
|
|
104
|
+
* hour for lobby retention to collect.
|
|
105
|
+
*/
|
|
106
|
+
readonly matchCreationPerMinute: 120;
|
|
90
107
|
};
|
|
91
108
|
//# sourceMappingURL=container.d.ts.map
|
package/dist/container.d.ts.map
CHANGED
|
@@ -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;
|
|
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;aAC9B,kBAAkB,EAAE,EAAE;aACtB,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
|
@@ -19,5 +19,11 @@ export const DEFAULT_RATE_LIMITS = {
|
|
|
19
19
|
* of the default global budget, so no single address can crowd everybody else out of it.
|
|
20
20
|
*/
|
|
21
21
|
bugReportStatePerDay: 5,
|
|
22
|
+
/**
|
|
23
|
+
* Matches created per minute across every caller. Two a second is far beyond what players open by
|
|
24
|
+
* hand on any server this is likely to run, and caps a flood at under three thousand lobbies an
|
|
25
|
+
* hour for lobby retention to collect.
|
|
26
|
+
*/
|
|
27
|
+
matchCreationPerMinute: 120,
|
|
22
28
|
};
|
|
23
29
|
//# sourceMappingURL=container.js.map
|
package/dist/container.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container.js","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"
|
|
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,kBAAkB,EAAE,EAAE;IACtB,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":"AAAA,OAAO,EAGL,mBAAmB,EACnB,cAAc,EACd,YAAY,GACb,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAE5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAGnD,kGAAkG;AAClG,MAAM,UAAU,WAAW,CAAC,KAAY,EAAE,CAAkB;IAC1D,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACpC,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,OAAO,CAAC,CAAC,EAAE;YAChB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,SAAS;SACV,CAAC,CAAA;IACJ,CAAC;IACD,IAAI,KAAK,YAAY,qBAAqB,EAAE,CAAC;QAC3C,8FAA8F;QAC9F,8FAA8F;QAC9F,iCAAiC;QACjC,OAAO,OAAO,CAAC,CAAC,EAAE;YAChB,IAAI,EAAE,mBAAmB;YACzB,OAAO,EAAE,oCAAoC;YAC7C,OAAO,EAAE,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE;YAC/E,SAAS;SACV,CAAC,CAAA;IACJ,CAAC;IACD,IAAI,KAAK,YAAY,aAAa,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QACxC,OAAO,OAAO,CAAC,CAAC,EAAE;YAChB,IAAI;YACJ,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,IAAI;YAC9B,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,KAAK,CAAC,MAAM,EAAE,EAAE;YAC3C,SAAS;SACV,CAAC,CAAA;IACJ,CAAC;IACD,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE;QACtE,SAAS;QACT,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC;KACpC,CAAC,CAAA;IACF,OAAO,OAAO,CAAC,CAAC,EAAE;QAChB,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,uBAAuB;QAChC,OAAO,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;QAC/B,SAAS;KACV,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAS,aAAa,CAAC,KAA8C;IAInE,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAgB,EAAE,EAAE,CACvD,MAAM,CACJ,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,IAAI,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAC5F,CACF,CAAA;IACD,OAAO,EAAE,OAAO,EAAE,eAAe,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;AAClD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,eAAe,CAAC,KAA8C;IACrE,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC,OAAO,CAAA;IACtD,MAAM,eAAe,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,CAAC,CAAA;IAC3E,OAAO,eAAe,KAAK,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,eAAe,CAAA;AACnE,CAAC;AAED;;;;GAIG;AACH,MAAM,cAAc,GAAwC;IAC1D,GAAG,EAAE,aAAa;IAClB,GAAG,EAAE,cAAc;IACnB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,mBAAmB;IACxB,GAAG,EAAE,mBAAmB;IACxB,GAAG,EAAE,cAAc;CACpB,CAAA;AAED,SAAS,aAAa,CAAC,MAAc;IACnC,OAAO,cAAc,CAAC,MAAM,CAAC,IAAI,UAAU,CAAA;AAC7C,CAAC;AAUD,SAAS,OAAO,CAAC,CAAkB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAa;IACnF,MAAM,IAAI,GAAkB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,CAAA;IAC5E,8FAA8F;IAC9F,6FAA6F;IAC7F,6FAA6F;IAC7F,8FAA8F;IAC9F,CAAC,CAAC,MAAM,CAAC,eAAe,EAAE,UAAU,CAAC,CAAA;IACrC,OAAO,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,mBAAmB,EAAE,IAAI,CAAC,EAAE,cAAc,CAAC,IAAI,CAAQ,CAAC,CAAA;AACrF,CAAC"}
|
|
@@ -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,
|
|
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"}
|
package/dist/http/middleware.js
CHANGED
|
@@ -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
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
|
194
|
-
|
|
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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"}
|
package/dist/http/types.d.ts
CHANGED
|
@@ -15,11 +15,16 @@ export interface AppEnv {
|
|
|
15
15
|
*/
|
|
16
16
|
caller?: string;
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
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?: () =>
|
|
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
|
package/dist/http/types.d.ts.map
CHANGED
|
@@ -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,
|
|
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,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, 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
6
|
export { createSseResponse, type EventStreamSource, formatEvent, isReadableEvent, } from './sse/createSseResponse';
|
|
6
7
|
export { type EventFrame, MatchLog } from './sse/MatchLog';
|
|
8
|
+
export { isActiveMember } from './sse/membership';
|
|
7
9
|
export { DEFAULT_EVENT_HUB_LIMITS, type EventHubLimits, type EventHubObserver, LocalEventHub, } from './sse/LocalEventHub';
|
|
8
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,eAAe,GAChB,MAAM,yBAAyB,CAAA;AAChC,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,9 @@
|
|
|
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
5
|
export { createSseResponse, formatEvent, isReadableEvent, } from './sse/createSseResponse';
|
|
5
6
|
export { MatchLog } from './sse/MatchLog';
|
|
7
|
+
export { isActiveMember } from './sse/membership';
|
|
6
8
|
export { DEFAULT_EVENT_HUB_LIMITS, LocalEventHub, } from './sse/LocalEventHub';
|
|
7
9
|
//# 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,EACX,eAAe,GAChB,MAAM,yBAAyB,CAAA;AAChC,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,
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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,
|
|
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":"
|
|
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"}
|
package/dist/routes/events.js
CHANGED
|
@@ -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":"AAAA,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;
|
|
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,
|
|
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,CAmCjE;AAED,4DAA4D;AAC5D,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CA8DjE"}
|
package/dist/routes/lobby.js
CHANGED
|
@@ -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
|
});
|
package/dist/routes/lobby.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lobby.js","sourceRoot":"","sources":["../../src/routes/lobby.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lobby.js","sourceRoot":"","sources":["../../src/routes/lobby.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,8 @@ import { type EventNotifier, type EventRepository, type EventStreamOpener, type
|
|
|
13
13
|
* predecessor is still being torn down. Reaching it closes that player's oldest stream rather than
|
|
14
14
|
* refusing the new one, because the new one is the live client and the old one is the corpse.
|
|
15
15
|
* `perMatch` and `perProcess` are the ceilings a client cannot talk its way past, and they refuse.
|
|
16
|
+
* Lobby streams may use at most one quarter of the process ceiling, so cheaply minted host tokens
|
|
17
|
+
* cannot fill every stream slot needed by running matches.
|
|
16
18
|
*/
|
|
17
19
|
export interface EventHubLimits {
|
|
18
20
|
perPlayer: number;
|
|
@@ -20,8 +22,10 @@ export interface EventHubLimits {
|
|
|
20
22
|
perProcess: number;
|
|
21
23
|
}
|
|
22
24
|
export declare const DEFAULT_EVENT_HUB_LIMITS: EventHubLimits;
|
|
23
|
-
/**
|
|
25
|
+
/** Runtime hooks for stream diagnostics and membership checks. */
|
|
24
26
|
export interface EventHubObserver {
|
|
27
|
+
/** A false result or failed lookup ends the stream. */
|
|
28
|
+
revalidate?(matchId: string, playerId: string): Promise<boolean>;
|
|
25
29
|
/** A stored event a stream had to skip because this build cannot read it. */
|
|
26
30
|
unreadable?(matchId: string, seq: number): void;
|
|
27
31
|
/**
|
|
@@ -51,6 +55,9 @@ export declare class LocalEventHub implements EventNotifier, EventStreamOpener,
|
|
|
51
55
|
*/
|
|
52
56
|
private readonly logs;
|
|
53
57
|
private open_;
|
|
58
|
+
private lobbyOpen_;
|
|
59
|
+
/** The share of `perProcess` lobby streams may hold; see `makeRoom`. */
|
|
60
|
+
private readonly lobbyCap;
|
|
54
61
|
constructor(events: EventRepository, heartbeatMs: number, limits?: EventHubLimits, observer?: EventHubObserver);
|
|
55
62
|
notify(event: PersistedEvent): Promise<void>;
|
|
56
63
|
/** Wake every stream of a match; used when the notification arrives without the event body. */
|
|
@@ -58,9 +65,9 @@ export declare class LocalEventHub implements EventNotifier, EventStreamOpener,
|
|
|
58
65
|
/**
|
|
59
66
|
* End every stream a membership holds.
|
|
60
67
|
*
|
|
61
|
-
* Revoking a token stops the next request
|
|
62
|
-
*
|
|
63
|
-
* (which names each player's state hash) and every host change
|
|
68
|
+
* Revoking a token stops the next request, and an open stream only re-checks its membership on
|
|
69
|
+
* the catch-up heartbeat; until then a kicked player keeps being handed every sealed set, every
|
|
70
|
+
* desync report (which names each player's state hash) and every host change.
|
|
64
71
|
*/
|
|
65
72
|
close(input: {
|
|
66
73
|
matchId: string;
|
|
@@ -83,11 +90,14 @@ export declare class LocalEventHub implements EventNotifier, EventStreamOpener,
|
|
|
83
90
|
playerId: string;
|
|
84
91
|
afterSeq: number;
|
|
85
92
|
signal: AbortSignal;
|
|
93
|
+
lobby?: boolean;
|
|
86
94
|
}): Promise<Response>;
|
|
87
95
|
private logOf;
|
|
88
96
|
private subscribe;
|
|
97
|
+
/** Stop charging a stream to the lobby share once its match is running. */
|
|
98
|
+
private releaseLobby;
|
|
89
99
|
/**
|
|
90
|
-
* Enforce the
|
|
100
|
+
* Enforce the stream caps before a stream is built.
|
|
91
101
|
*
|
|
92
102
|
* The caller's own stale streams are closed FIRST, before either ceiling is read. Closing them is
|
|
93
103
|
* not a concession to the caller, it is bookkeeping: a reconnect whose predecessor has not
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalEventHub.d.ts","sourceRoot":"","sources":["../../src/sse/LocalEventHub.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAEnB,KAAK,YAAY,EAClB,MAAM,yBAAyB,CAAA;AAIhC
|
|
1
|
+
{"version":3,"file":"LocalEventHub.d.ts","sourceRoot":"","sources":["../../src/sse/LocalEventHub.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAEnB,KAAK,YAAY,EAClB,MAAM,yBAAyB,CAAA;AAIhC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,eAAO,MAAM,wBAAwB,EAAE,cAItC,CAAA;AAED,kEAAkE;AAClE,MAAM,WAAW,gBAAgB;IAC/B,uDAAuD;IACvD,UAAU,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAChE,6EAA6E;IAC7E,UAAU,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/C;;;;;OAKG;IACH,SAAS,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACpD;AASD;;;GAGG;AACH,qBAAa,aAAc,YAAW,aAAa,EAAE,iBAAiB,EAAE,YAAY;IAgBhF,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAlB3B,yFAAyF;IACzF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IACjE;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA8B;IACnD,OAAO,CAAC,KAAK,CAAI;IACjB,OAAO,CAAC,UAAU,CAAI;IACtB,wEAAwE;IACxE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IAEjC,YACmB,MAAM,EAAE,eAAe,EACvB,WAAW,EAAE,MAAM,EACnB,MAAM,GAAE,cAAyC,EACjD,QAAQ,GAAE,gBAAqB,EAGjD;IAEK,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAajD;IAED,+FAA+F;IAC/F,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAI1B;IAED;;;;;;OAMG;IACG,KAAK,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvE;IAED;;;;;;;OAOG;IACH,QAAQ,IAAI,IAAI,CAOf;IAED,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvC;IAED,uDAAuD;IACvD,IAAI,WAAW,IAAI,MAAM,CAExB;IAEK,IAAI,CAAC,KAAK,EAAE;QAChB,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,MAAM,CAAA;QAChB,QAAQ,EAAE,MAAM,CAAA;QAChB,MAAM,EAAE,WAAW,CAAA;QACnB,KAAK,CAAC,EAAE,OAAO,CAAA;KAChB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAqCpB;IAED,OAAO,CAAC,KAAK;IAQb,OAAO,CAAC,SAAS;IAoBjB,2EAA2E;IAC3E,OAAO,CAAC,YAAY;IAMpB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,QAAQ;CA6BjB"}
|
|
@@ -26,13 +26,24 @@ export class LocalEventHub {
|
|
|
26
26
|
*/
|
|
27
27
|
logs = new Map();
|
|
28
28
|
open_ = 0;
|
|
29
|
+
lobbyOpen_ = 0;
|
|
30
|
+
/** The share of `perProcess` lobby streams may hold; see `makeRoom`. */
|
|
31
|
+
lobbyCap;
|
|
29
32
|
constructor(events, heartbeatMs, limits = DEFAULT_EVENT_HUB_LIMITS, observer = {}) {
|
|
30
33
|
this.events = events;
|
|
31
34
|
this.heartbeatMs = heartbeatMs;
|
|
32
35
|
this.limits = limits;
|
|
33
36
|
this.observer = observer;
|
|
37
|
+
this.lobbyCap = Math.max(1, Math.floor(limits.perProcess / 4));
|
|
34
38
|
}
|
|
35
39
|
async notify(event) {
|
|
40
|
+
// A stream opened in the lobby stays connected when play starts. Release its lobby quota now
|
|
41
|
+
// rather than waiting for a reconnect that may never happen.
|
|
42
|
+
if (event.type === 'match.started') {
|
|
43
|
+
for (const subscription of this.listeners.get(event.matchId) ?? []) {
|
|
44
|
+
this.releaseLobby(subscription);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
36
47
|
// The notification carries the durable row, so its frame is formatted once here and every
|
|
37
48
|
// stream one event behind — which is every healthy stream of the match — is served from it
|
|
38
49
|
// without reading anything. See `MatchLog`.
|
|
@@ -49,9 +60,9 @@ export class LocalEventHub {
|
|
|
49
60
|
/**
|
|
50
61
|
* End every stream a membership holds.
|
|
51
62
|
*
|
|
52
|
-
* Revoking a token stops the next request
|
|
53
|
-
*
|
|
54
|
-
* (which names each player's state hash) and every host change
|
|
63
|
+
* Revoking a token stops the next request, and an open stream only re-checks its membership on
|
|
64
|
+
* the catch-up heartbeat; until then a kicked player keeps being handed every sealed set, every
|
|
65
|
+
* desync report (which names each player's state hash) and every host change.
|
|
55
66
|
*/
|
|
56
67
|
async close(input) {
|
|
57
68
|
// Snapshot deliberately: `close()` removes the subscription from the set being walked.
|
|
@@ -93,17 +104,32 @@ export class LocalEventHub {
|
|
|
93
104
|
this.observer.abandoned?.(input.matchId, input.playerId);
|
|
94
105
|
return abandonedSseResponse();
|
|
95
106
|
}
|
|
96
|
-
|
|
107
|
+
const lobby = input.lobby === true;
|
|
108
|
+
this.makeRoom(input.matchId, input.playerId, lobby);
|
|
97
109
|
const log = this.logOf(input.matchId);
|
|
110
|
+
let subscription;
|
|
111
|
+
const revalidate = this.observer.revalidate;
|
|
98
112
|
return createSseResponse({
|
|
99
|
-
page: (afterSeq, force) =>
|
|
113
|
+
page: async (afterSeq, force) => {
|
|
114
|
+
const frames = await log.page(afterSeq, force);
|
|
115
|
+
// `lobby` was read when the request authenticated. A match that started in between
|
|
116
|
+
// announced it before this stream subscribed, so the release in `notify` missed it; the
|
|
117
|
+
// stream's own read of the log is where it learns the match is running.
|
|
118
|
+
if (subscription?.lobby && log.started)
|
|
119
|
+
this.releaseLobby(subscription);
|
|
120
|
+
return frames;
|
|
121
|
+
},
|
|
100
122
|
caughtUp: (lastSeq) => log.caughtUp(lastSeq),
|
|
101
|
-
subscribe: (wake, close) =>
|
|
123
|
+
subscribe: (wake, close) => {
|
|
124
|
+
subscription = { playerId: input.playerId, lobby: lobby && !log.started, wake, close };
|
|
125
|
+
return this.subscribe(input.matchId, subscription);
|
|
126
|
+
},
|
|
102
127
|
}, {
|
|
103
128
|
afterSeq: input.afterSeq,
|
|
104
129
|
heartbeatMs: this.heartbeatMs,
|
|
105
130
|
signal: input.signal,
|
|
106
131
|
onUnreadable: (seq) => this.observer.unreadable?.(input.matchId, seq),
|
|
132
|
+
...(revalidate ? { revalidate: () => revalidate(input.matchId, input.playerId) } : {}),
|
|
107
133
|
});
|
|
108
134
|
}
|
|
109
135
|
logOf(matchId) {
|
|
@@ -114,16 +140,19 @@ export class LocalEventHub {
|
|
|
114
140
|
this.logs.set(matchId, log);
|
|
115
141
|
return log;
|
|
116
142
|
}
|
|
117
|
-
subscribe(matchId,
|
|
143
|
+
subscribe(matchId, subscription) {
|
|
118
144
|
const set = this.listeners.get(matchId) ?? new Set();
|
|
119
|
-
const subscription = { playerId, wake, close };
|
|
120
145
|
set.add(subscription);
|
|
121
146
|
this.listeners.set(matchId, set);
|
|
122
147
|
this.open_ += 1;
|
|
148
|
+
if (subscription.lobby)
|
|
149
|
+
this.lobbyOpen_ += 1;
|
|
123
150
|
return () => {
|
|
124
151
|
if (!set.delete(subscription))
|
|
125
152
|
return;
|
|
126
153
|
this.open_ -= 1;
|
|
154
|
+
// Clears the flag as well, so a page still in flight at close cannot release it twice.
|
|
155
|
+
this.releaseLobby(subscription);
|
|
127
156
|
if (set.size === 0) {
|
|
128
157
|
this.listeners.delete(matchId);
|
|
129
158
|
// Nothing reads this match any more, so its frames are only memory. The next stream of it
|
|
@@ -132,8 +161,15 @@ export class LocalEventHub {
|
|
|
132
161
|
}
|
|
133
162
|
};
|
|
134
163
|
}
|
|
164
|
+
/** Stop charging a stream to the lobby share once its match is running. */
|
|
165
|
+
releaseLobby(subscription) {
|
|
166
|
+
if (!subscription.lobby)
|
|
167
|
+
return;
|
|
168
|
+
subscription.lobby = false;
|
|
169
|
+
this.lobbyOpen_ -= 1;
|
|
170
|
+
}
|
|
135
171
|
/**
|
|
136
|
-
* Enforce the
|
|
172
|
+
* Enforce the stream caps before a stream is built.
|
|
137
173
|
*
|
|
138
174
|
* The caller's own stale streams are closed FIRST, before either ceiling is read. Closing them is
|
|
139
175
|
* not a concession to the caller, it is bookkeeping: a reconnect whose predecessor has not
|
|
@@ -145,7 +181,7 @@ export class LocalEventHub {
|
|
|
145
181
|
* `perMatch` and `perProcess` then refuse whatever is still over, which is the case no client can
|
|
146
182
|
* talk its way past.
|
|
147
183
|
*/
|
|
148
|
-
makeRoom(matchId, playerId) {
|
|
184
|
+
makeRoom(matchId, playerId, lobby) {
|
|
149
185
|
const set = this.listeners.get(matchId);
|
|
150
186
|
if (set) {
|
|
151
187
|
const mine = [...set].filter((subscription) => subscription.playerId === playerId);
|
|
@@ -158,6 +194,16 @@ export class LocalEventHub {
|
|
|
158
194
|
scope: 'process',
|
|
159
195
|
});
|
|
160
196
|
}
|
|
197
|
+
// Creating a lobby is unauthenticated. A caller can mint hundreds of host tokens and hold
|
|
198
|
+
// three streams per token, so lobby streams cannot be allowed to occupy the whole process cap.
|
|
199
|
+
// Running matches retain the other three quarters even when a single source spreads creation
|
|
200
|
+
// across many IPv6 /64s and exhausts the lobby pool.
|
|
201
|
+
if (lobby && this.lobbyOpen_ >= this.lobbyCap) {
|
|
202
|
+
throw new RateLimitedError('This server is holding as many lobby streams as it can', {
|
|
203
|
+
reason: 'too_many_streams',
|
|
204
|
+
scope: 'lobby',
|
|
205
|
+
});
|
|
206
|
+
}
|
|
161
207
|
if ((this.listeners.get(matchId)?.size ?? 0) >= this.limits.perMatch) {
|
|
162
208
|
throw new RateLimitedError('This match is holding as many event streams as it can', {
|
|
163
209
|
reason: 'too_many_streams',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalEventHub.js","sourceRoot":"","sources":["../../src/sse/LocalEventHub.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAA;AACnD,OAAO,EAKL,gBAAgB,GAEjB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAC7E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"LocalEventHub.js","sourceRoot":"","sources":["../../src/sse/LocalEventHub.ts"],"names":[],"mappings":"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"}
|
package/dist/sse/MatchLog.d.ts
CHANGED
|
@@ -44,6 +44,12 @@ export declare class MatchLog {
|
|
|
44
44
|
* every one of its reads goes to the log exactly as before.
|
|
45
45
|
*/
|
|
46
46
|
private notified;
|
|
47
|
+
/**
|
|
48
|
+
* Whether this process has seen the match's `match.started`, by notification or by reading it.
|
|
49
|
+
* A stream authenticated while the match was still a lobby can subscribe after that notification
|
|
50
|
+
* went out; this is how the hub learns the stream is no longer a lobby stream.
|
|
51
|
+
*/
|
|
52
|
+
started: boolean;
|
|
47
53
|
constructor(matchId: string, events: EventRepository);
|
|
48
54
|
/**
|
|
49
55
|
* Remember a published event and its frame.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MatchLog.d.ts","sourceRoot":"","sources":["../../src/sse/MatchLog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAG9E,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,+EAA+E;IAC/E,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAcD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,QAAQ;
|
|
1
|
+
{"version":3,"file":"MatchLog.d.ts","sourceRoot":"","sources":["../../src/sse/MatchLog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAG9E,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,+EAA+E;IAC/E,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAcD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,QAAQ;IAsBjB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAtBzB,mFAAmF;IACnF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2C;IACpE;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAQ,CAAI;IACpB;;;;OAIG;IACH,OAAO,UAAQ;IAEf,YACmB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,eAAe,EACtC;IAEJ;;;;;OAKG;IACH,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAMlC;IAED;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEjC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACG,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,UAAQ,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAejE;IAED,OAAO,CAAC,cAAc;YAUR,IAAI;IAclB,OAAO,CAAC,IAAI;CAOb"}
|
package/dist/sse/MatchLog.js
CHANGED
|
@@ -48,6 +48,12 @@ export class MatchLog {
|
|
|
48
48
|
* every one of its reads goes to the log exactly as before.
|
|
49
49
|
*/
|
|
50
50
|
notified = 0;
|
|
51
|
+
/**
|
|
52
|
+
* Whether this process has seen the match's `match.started`, by notification or by reading it.
|
|
53
|
+
* A stream authenticated while the match was still a lobby can subscribe after that notification
|
|
54
|
+
* went out; this is how the hub learns the stream is no longer a lobby stream.
|
|
55
|
+
*/
|
|
56
|
+
started = false;
|
|
51
57
|
constructor(matchId, events) {
|
|
52
58
|
this.matchId = matchId;
|
|
53
59
|
this.events = events;
|
|
@@ -61,6 +67,8 @@ export class MatchLog {
|
|
|
61
67
|
record(event) {
|
|
62
68
|
if (event.seq > this.notified)
|
|
63
69
|
this.notified = event.seq;
|
|
70
|
+
if (event.type === 'match.started')
|
|
71
|
+
this.started = true;
|
|
64
72
|
if (this.frames.has(event.seq))
|
|
65
73
|
return;
|
|
66
74
|
this.frames.set(event.seq, { seq: event.seq, text: tryFormatEvent(event) });
|
|
@@ -125,6 +133,8 @@ export class MatchLog {
|
|
|
125
133
|
async read(afterSeq) {
|
|
126
134
|
const rows = await this.events.listAfter(this.matchId, afterSeq, PAGE_SIZE);
|
|
127
135
|
const page = rows.map((row) => {
|
|
136
|
+
if (row.type === 'match.started')
|
|
137
|
+
this.started = true;
|
|
128
138
|
const known = this.frames.get(row.seq);
|
|
129
139
|
if (known)
|
|
130
140
|
return known;
|
package/dist/sse/MatchLog.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MatchLog.js","sourceRoot":"","sources":["../../src/sse/MatchLog.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AASpD;;;;;;GAMG;AACH,MAAM,WAAW,GAAG,GAAG,CAAA;AAEvB,8BAA8B;AAC9B,MAAM,SAAS,GAAG,GAAG,CAAA;AAErB;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAO,QAAQ;
|
|
1
|
+
{"version":3,"file":"MatchLog.js","sourceRoot":"","sources":["../../src/sse/MatchLog.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AASpD;;;;;;GAMG;AACH,MAAM,WAAW,GAAG,GAAG,CAAA;AAEvB,8BAA8B;AAC9B,MAAM,SAAS,GAAG,GAAG,CAAA;AAErB;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAO,QAAQ;IAsBA,OAAO;IACP,MAAM;IAtBzB,mFAAmF;IAClE,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAA;IACtC,QAAQ,GAAG,IAAI,GAAG,EAAiC,CAAA;IACpE;;;;;;;;OAQG;IACK,QAAQ,GAAG,CAAC,CAAA;IACpB;;;;OAIG;IACH,OAAO,GAAG,KAAK,CAAA;IAEf,YACmB,OAAe,EACf,MAAuB;uBADvB,OAAO;sBACP,MAAM;IACtB,CAAC;IAEJ;;;;;OAKG;IACH,MAAM,CAAC,KAAqB;QAC1B,IAAI,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,QAAQ;YAAE,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAA;QACxD,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe;YAAE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;QACvD,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;YAAE,OAAM;QACtC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAC3E,IAAI,CAAC,IAAI,EAAE,CAAA;IACb,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CAAC,OAAe;QACtB,OAAO,IAAI,CAAC,QAAQ,GAAG,CAAC,IAAI,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAA;IACtD,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,IAAI,CAAC,QAAgB,EAAE,KAAK,GAAG,KAAK;QACxC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAA;YAC9C,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,QAAQ,CAAA;YACxC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAAE,OAAO,EAAE,CAAA;QACxC,CAAC;QACD,8FAA8F;QAC9F,iCAAiC;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAC1C,IAAI,MAAM;YAAE,OAAO,MAAM,CAAA;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;YAC/C,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAChC,CAAC,CAAC,CAAA;QACF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QACpC,OAAO,OAAO,CAAA;IAChB,CAAC;IAEO,cAAc,CAAC,QAAgB;QACrC,MAAM,IAAI,GAAiB,EAAE,CAAA;QAC7B,KAAK,IAAI,GAAG,GAAG,QAAQ,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,SAAS,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;YAC/D,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YAClC,IAAI,CAAC,KAAK;gBAAE,MAAK;YACjB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAClB,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,QAAgB;QACjC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAA;QAC3E,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YAC5B,IAAI,GAAG,CAAC,IAAI,KAAK,eAAe;gBAAE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;YACrD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACtC,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAA;YACvB,MAAM,KAAK,GAAe,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,CAAA;YACrE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;YAC/B,OAAO,KAAK,CAAA;QACd,CAAC,CAAC,CAAA;QACF,IAAI,CAAC,IAAI,EAAE,CAAA;QACX,OAAO,IAAI,CAAA;IACb,CAAC;IAEO,IAAI;QACV,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,WAAW,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAA;YACxC,IAAI,MAAM,CAAC,IAAI;gBAAE,OAAM;YACvB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAClC,CAAC;IACH,CAAC;CACF"}
|
|
@@ -30,6 +30,8 @@ export interface SseOptions {
|
|
|
30
30
|
signal: AbortSignal;
|
|
31
31
|
/** Told the sequence of a stored event this build cannot validate, so it can be logged. */
|
|
32
32
|
onUnreadable?: (seq: number) => void;
|
|
33
|
+
/** Confirm that the subscription still belongs to an active member. */
|
|
34
|
+
revalidate?: () => Promise<boolean>;
|
|
33
35
|
}
|
|
34
36
|
/**
|
|
35
37
|
* A server-sent event stream over a persisted, sequence-numbered log.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createSseResponse.d.ts","sourceRoot":"","sources":["../../src/sse/createSseResponse.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAE7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;IAC9D;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;IAClC;;;;;;OAMG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,KAAK,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAA;CAC3D;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,WAAW,CAAA;IACnB,2FAA2F;IAC3F,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"createSseResponse.d.ts","sourceRoot":"","sources":["../../src/sse/createSseResponse.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAE7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;IAC9D;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;IAClC;;;;;;OAMG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,KAAK,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAA;CAC3D;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,WAAW,CAAA;IACnB,2FAA2F;IAC3F,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;CACpC;AAkCD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,UAAU,GAAG,QAAQ,CAyL1F;AASD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,IAAI,QAAQ,CAE/C;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAIzD;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAMnE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAO9D"}
|
|
@@ -149,6 +149,7 @@ export function createSseResponse(source, options) {
|
|
|
149
149
|
});
|
|
150
150
|
let beats = 0;
|
|
151
151
|
let stalledBeats = 0;
|
|
152
|
+
let validating = false;
|
|
152
153
|
const heartbeat = setInterval(() => {
|
|
153
154
|
// A consumer that is not reading is not a consumer. The queue is full, so this frame
|
|
154
155
|
// would only buffer; after a few beats of that the connection is gone in every way that
|
|
@@ -167,6 +168,27 @@ export function createSseResponse(source, options) {
|
|
|
167
168
|
// idle server was otherwise issuing one query per stream per heartbeat to find nothing.
|
|
168
169
|
beats += 1;
|
|
169
170
|
const overdue = beats % CATCH_UP_EVERY_HEARTBEATS === 0;
|
|
171
|
+
if (overdue && options.revalidate) {
|
|
172
|
+
// A lookup still pending a whole catch-up cycle later is a failed one. Waiting on it
|
|
173
|
+
// instead left the stream never checked again for as long as that query hung.
|
|
174
|
+
if (validating) {
|
|
175
|
+
shutdown();
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
validating = true;
|
|
179
|
+
void Promise.resolve()
|
|
180
|
+
.then(options.revalidate)
|
|
181
|
+
.then((valid) => {
|
|
182
|
+
validating = false;
|
|
183
|
+
if (!valid)
|
|
184
|
+
shutdown();
|
|
185
|
+
}, () => {
|
|
186
|
+
validating = false;
|
|
187
|
+
shutdown();
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
// The catch-up does not wait on the membership check: notifications keep delivering
|
|
191
|
+
// while it is in flight anyway, so holding this back only delayed the read.
|
|
170
192
|
if (overdue || !source.caughtUp(lastSeq))
|
|
171
193
|
wake(overdue);
|
|
172
194
|
}, options.heartbeatMs);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createSseResponse.js","sourceRoot":"","sources":["../../src/sse/createSseResponse.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"createSseResponse.js","sourceRoot":"","sources":["../../src/sse/createSseResponse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PlayerRepository } from '@chaos-overlords/kernel';
|
|
2
|
+
/**
|
|
3
|
+
* Whether `playerId` still holds a live membership of `matchId`: the row exists, belongs to that
|
|
4
|
+
* match, and its token has not been revoked. A token is issued once per membership and never
|
|
5
|
+
* rotated, so a non-null hash is the token the stream was authenticated with.
|
|
6
|
+
*
|
|
7
|
+
* The stream route runs this right after subscribing and every hub repeats it on its catch-up
|
|
8
|
+
* heartbeat; one definition keeps the two from drifting apart.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isActiveMember(players: PlayerRepository, matchId: string, playerId: string): Promise<boolean>;
|
|
11
|
+
//# sourceMappingURL=membership.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"membership.d.ts","sourceRoot":"","sources":["../../src/sse/membership.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAE/D;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAGlB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether `playerId` still holds a live membership of `matchId`: the row exists, belongs to that
|
|
3
|
+
* match, and its token has not been revoked. A token is issued once per membership and never
|
|
4
|
+
* rotated, so a non-null hash is the token the stream was authenticated with.
|
|
5
|
+
*
|
|
6
|
+
* The stream route runs this right after subscribing and every hub repeats it on its catch-up
|
|
7
|
+
* heartbeat; one definition keeps the two from drifting apart.
|
|
8
|
+
*/
|
|
9
|
+
export async function isActiveMember(players, matchId, playerId) {
|
|
10
|
+
const player = await players.get(playerId);
|
|
11
|
+
return player?.matchId === matchId && player.tokenHash !== null;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=membership.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"membership.js","sourceRoot":"","sources":["../../src/sse/membership.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAyB,EACzB,OAAe,EACf,QAAgB;IAEhB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAC1C,OAAO,MAAM,EAAE,OAAO,KAAK,OAAO,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI,CAAA;AACjE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chaos-overlords/server",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2",
|
|
4
4
|
"description": "The Hono application both runtimes serve: REST intents, the SSE event stream, auth and the error envelope. Takes its ports through a container.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chaos-overlords",
|
|
@@ -48,15 +48,15 @@
|
|
|
48
48
|
"provenance": true
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@chaos-overlords/bug-reports": "0.9.
|
|
52
|
-
"@chaos-overlords/contracts": "0.9.
|
|
53
|
-
"@chaos-overlords/kernel": "0.9.
|
|
51
|
+
"@chaos-overlords/bug-reports": "0.9.2",
|
|
52
|
+
"@chaos-overlords/contracts": "0.9.2",
|
|
53
|
+
"@chaos-overlords/kernel": "0.9.2",
|
|
54
54
|
"@toad-contracts/core": "1.0.0",
|
|
55
55
|
"@toad-contracts/hono": "1.0.0",
|
|
56
56
|
"hono": "^4.13.8"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@chaos-overlords/conformance": "0.9.
|
|
59
|
+
"@chaos-overlords/conformance": "0.9.2",
|
|
60
60
|
"typescript": "^7.0.2",
|
|
61
61
|
"vitest": "^4.1.11"
|
|
62
62
|
},
|