@chaos-overlords/kernel 0.9.0 → 0.9.1

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.
@@ -20,25 +20,53 @@ export class NonCanonicalValueError extends Error {
20
20
  this.name = 'NonCanonicalValueError';
21
21
  }
22
22
  }
23
- function canonicalize(value, path = '') {
23
+ function canonicalize(value, path = []) {
24
24
  if (value === null || typeof value === 'boolean' || typeof value === 'string')
25
25
  return value;
26
26
  if (typeof value === 'number') {
27
27
  if (!Number.isSafeInteger(value) || Object.is(value, -0)) {
28
- throw new NonCanonicalValueError(path, `${value} is not a safe non-negative-zero integer`);
28
+ throw new NonCanonicalValueError(describe(path), `${value} is not a safe non-negative-zero integer`);
29
29
  }
30
30
  return value;
31
31
  }
32
32
  if (Array.isArray(value))
33
- return value.map((item, index) => canonicalize(item, `${path}[${index}]`));
33
+ return value.map((item, index) => descend(path, index, item));
34
34
  if (typeof value === 'object') {
35
35
  const source = value;
36
36
  const sorted = {};
37
37
  for (const key of Object.keys(source).sort()) {
38
- sorted[key] = canonicalize(source[key], path ? `${path}.${key}` : key);
38
+ sorted[key] = descend(path, key, source[key]);
39
39
  }
40
40
  return sorted;
41
41
  }
42
- throw new NonCanonicalValueError(path, `unsupported type ${typeof value}`);
42
+ throw new NonCanonicalValueError(describe(path), `unsupported type ${typeof value}`);
43
+ }
44
+ function descend(path, segment, value) {
45
+ path.push(segment);
46
+ try {
47
+ return canonicalize(value, path);
48
+ }
49
+ finally {
50
+ path.pop();
51
+ }
52
+ }
53
+ /**
54
+ * Renders the accumulated segments the way the C# mirror's `path` parameter spells them
55
+ * (`CanonicalJson.WriteObject`/`WriteArray`): an index is always `[n]`, and a key is dotted unless
56
+ * nothing has been rendered yet. The emptiness of what came before decides the dot, not the
57
+ * segment's position -- an empty-string key renders as nothing, so `{ '': { y: 1.5 } }` reports
58
+ * `y` rather than `.y`, matching both the mirror and the string-building version this replaced.
59
+ *
60
+ * Only a throw reaches here, so the allocation is off the hot path.
61
+ */
62
+ function describe(path) {
63
+ let rendered = '';
64
+ for (const segment of path) {
65
+ if (typeof segment === 'number')
66
+ rendered += `[${segment}]`;
67
+ else
68
+ rendered += rendered.length === 0 ? segment : `.${segment}`;
69
+ }
70
+ return rendered;
43
71
  }
44
72
  //# sourceMappingURL=canonical-json.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"canonical-json.js","sourceRoot":"","sources":["../../src/logic/canonical-json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAA;AAC5C,CAAC;AAED,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAEpC,IAAI;IADf,YACW,IAAY,EACrB,MAAc;QAEd,KAAK,CAAC,uBAAuB,IAAI,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC,CAAA;oBAHjD,IAAI;QAIb,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAA;IACtC,CAAC;CACF;AAED,SAAS,YAAY,CAAC,KAAc,EAAE,IAAI,GAAG,EAAE;IAC7C,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC3F,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,MAAM,IAAI,sBAAsB,CAAC,IAAI,EAAE,GAAG,KAAK,0CAA0C,CAAC,CAAA;QAC5F,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACtB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,CAAA;IAC5E,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,KAAgC,CAAA;QAC/C,MAAM,MAAM,GAA4B,EAAE,CAAA;QAC1C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YAC7C,MAAM,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QACxE,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IACD,MAAM,IAAI,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,OAAO,KAAK,EAAE,CAAC,CAAA;AAC5E,CAAC"}
1
+ {"version":3,"file":"canonical-json.js","sourceRoot":"","sources":["../../src/logic/canonical-json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAA;AAC5C,CAAC;AAED,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAEpC,IAAI;IADf,YACW,IAAY,EACrB,MAAc;QAEd,KAAK,CAAC,uBAAuB,IAAI,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC,CAAA;oBAHjD,IAAI;QAIb,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAA;IACtC,CAAC;CACF;AAID,SAAS,YAAY,CAAC,KAAc,EAAE,IAAI,GAAkB,EAAE;IAC5D,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC3F,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,MAAM,IAAI,sBAAsB,CAC9B,QAAQ,CAAC,IAAI,CAAC,EACd,GAAG,KAAK,0CAA0C,CACnD,CAAA;QACH,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAA;IACvF,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,KAAgC,CAAA;QAC/C,MAAM,MAAM,GAA4B,EAAE,CAAA;QAC1C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YAC7C,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;QAC/C,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IACD,MAAM,IAAI,sBAAsB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,oBAAoB,OAAO,KAAK,EAAE,CAAC,CAAA;AACtF,CAAC;AAED,SAAS,OAAO,CAAC,IAAmB,EAAE,OAAoB,EAAE,KAAc;IACxE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAClB,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IAClC,CAAC;YAAS,CAAC;QACT,IAAI,CAAC,GAAG,EAAE,CAAA;IACZ,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,QAAQ,CAAC,IAA4B;IAC5C,IAAI,QAAQ,GAAG,EAAE,CAAA;IACjB,KAAK,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC;QAC3B,IAAI,OAAO,OAAO,KAAK,QAAQ;YAAE,QAAQ,IAAI,IAAI,OAAO,GAAG,CAAA;;YACtD,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAA;IAClE,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC"}
@@ -1,4 +1,10 @@
1
1
  import type { Clock } from '../ports/runtime';
2
+ export interface RateLimiterOptions {
3
+ limit: number;
4
+ windowMs: number;
5
+ /** Residency bound; defaults to {@link DEFAULT_MAX_KEYS}. */
6
+ maxKeys?: number;
7
+ }
2
8
  /**
3
9
  * Fixed-window counter per key, in memory. It protects the unauthenticated doors (create, join)
4
10
  * from brute force on one process; a horizontally scaled deployment puts a shared limiter (a WAF
@@ -8,19 +14,35 @@ export declare class RateLimiter {
8
14
  private readonly clock;
9
15
  private readonly options;
10
16
  private readonly windows;
17
+ private readonly maxKeys;
11
18
  private lastPrune;
12
- constructor(clock: Clock, options: {
13
- limit: number;
14
- windowMs: number;
15
- });
19
+ private lastWall;
20
+ private elapsed;
21
+ constructor(clock: Clock, options: RateLimiterOptions);
16
22
  /** Returns the retry delay in seconds when over the limit, or null when the call is allowed. */
17
23
  take(key: string): number | null;
18
24
  /** What `take` would answer right now, spending nothing. */
19
25
  peek(key: string): number | null;
20
26
  /** How much of `key`'s budget the current window has already spent; 0 once it has rolled. */
21
27
  spent(key: string): number;
22
- /** The window `key` is spending from, or undefined once it has rolled or was never opened. */
28
+ /**
29
+ * Milliseconds on a clock that only moves forward, accumulated from the wall clock's forward steps.
30
+ *
31
+ * Production passes the wall clock, which NTP can step backwards. Measured directly, a step back
32
+ * would give new windows an earlier start than older ones already at the head, breaking the
33
+ * eviction order, and make elapsed time negative, keeping spent windows alive past `windowMs`.
34
+ * A backward step here just pauses the limiter's time until the wall clock moves forward again.
35
+ */
36
+ private tick;
37
+ /**
38
+ * The window `key` is spending from, or undefined once it has rolled or was never opened.
39
+ *
40
+ * A rolled window is removed here rather than overwritten later: Map#set keeps an existing key's
41
+ * insertion position, so overwriting would leave a fresh, possibly spent window at the head, first
42
+ * in line for eviction.
43
+ */
23
44
  private live;
45
+ private expired;
24
46
  /** Whole seconds until `entry`'s window rolls, rounded up. */
25
47
  private retryAfter;
26
48
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"RateLimiter.d.ts","sourceRoot":"","sources":["../../src/services/RateLimiter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAmB7C;;;;GAIG;AACH,qBAAa,WAAW;IAKpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAL1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,OAAO,CAAC,SAAS,CAA2B;IAE5C,YACmB,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAC3D;IAEJ,gGAAgG;IAChG,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAY/B;IAED,4DAA4D;IAC5D,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK/B;IAED,6FAA6F;IAC7F,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEzB;IAED,8FAA8F;IAC9F,OAAO,CAAC,IAAI;IAMZ,8DAA8D;IAC9D,OAAO,CAAC,UAAU;IAIlB;;;;;;;OAOG;IACH,OAAO,CAAC,KAAK;IAQb,0FAA0F;IAC1F,OAAO,CAAC,WAAW;CAOpB"}
1
+ {"version":3,"file":"RateLimiter.d.ts","sourceRoot":"","sources":["../../src/services/RateLimiter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAe7C,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAOD;;;;GAIG;AACH,qBAAa,WAAW;IAQpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAR1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,OAAO,CAAI;IAEnB,YACmB,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,kBAAkB,EAG7C;IAED,gGAAgG;IAChG,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAa/B;IAED,4DAA4D;IAC5D,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK/B;IAED,6FAA6F;IAC7F,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEzB;IAED;;;;;;;OAOG;IACH,OAAO,CAAC,IAAI;IAOZ;;;;;;OAMG;IACH,OAAO,CAAC,IAAI;IAOZ,OAAO,CAAC,OAAO;IAIf,8DAA8D;IAC9D,OAAO,CAAC,UAAU;IAIlB;;;;;;;OAOG;IACH,OAAO,CAAC,KAAK;IAQb,0FAA0F;IAC1F,OAAO,CAAC,WAAW;CAOpB"}
@@ -1,14 +1,15 @@
1
1
  /**
2
- * How many distinct keys one limiter holds before the oldest are dropped.
2
+ * How many distinct keys one limiter holds by default before the oldest are dropped.
3
3
  *
4
4
  * `prune` only collects windows that have EXPIRED, at most once per window period, which is right
5
5
  * for a minute-long window and wrong for a day-long one: the bug-report budget's window is
6
6
  * twenty-four hours, so every address that ever posted stayed resident for a day or two on an
7
- * unauthenticated route. A Map iterates in insertion order, so the head is the oldest key and
8
- * evicting from there is one shift. Dropping a live window forgives that key's remaining budget,
9
- * which is the safe direction to fail on a memory bound.
7
+ * unauthenticated route. The Map iterates in window-start order — windows open on a clock that
8
+ * never runs backwards, and a rolled window is removed before it reopens at the tail — so the head
9
+ * is the oldest window and evicting from there is one shift. Dropping a live window forgives that
10
+ * key's remaining budget, which is the safe direction to fail on a memory bound.
10
11
  */
11
- const MAX_KEYS = 50_000;
12
+ const DEFAULT_MAX_KEYS = 50_000;
12
13
  /**
13
14
  * Fixed-window counter per key, in memory. It protects the unauthenticated doors (create, join)
14
15
  * from brute force on one process; a horizontally scaled deployment puts a shared limiter (a WAF
@@ -18,16 +19,21 @@ export class RateLimiter {
18
19
  clock;
19
20
  options;
20
21
  windows = new Map();
22
+ maxKeys;
21
23
  lastPrune = Number.NEGATIVE_INFINITY;
24
+ lastWall = Number.NaN;
25
+ elapsed = 0;
22
26
  constructor(clock, options) {
23
27
  this.clock = clock;
24
28
  this.options = options;
29
+ this.maxKeys = options.maxKeys ?? DEFAULT_MAX_KEYS;
25
30
  }
26
31
  /** Returns the retry delay in seconds when over the limit, or null when the call is allowed. */
27
32
  take(key) {
28
- const now = this.clock.now().getTime();
33
+ const now = this.tick();
29
34
  const entry = this.live(key, now);
30
35
  if (!entry) {
36
+ // `live` removed any rolled window, so this appends at the tail and keeps the Map ordered.
31
37
  this.windows.set(key, { windowStart: now, count: 1 });
32
38
  this.prune(now);
33
39
  this.evictOldest();
@@ -40,7 +46,7 @@ export class RateLimiter {
40
46
  }
41
47
  /** What `take` would answer right now, spending nothing. */
42
48
  peek(key) {
43
- const now = this.clock.now().getTime();
49
+ const now = this.tick();
44
50
  const entry = this.live(key, now);
45
51
  if (!entry || entry.count < this.options.limit)
46
52
  return null;
@@ -48,14 +54,39 @@ export class RateLimiter {
48
54
  }
49
55
  /** How much of `key`'s budget the current window has already spent; 0 once it has rolled. */
50
56
  spent(key) {
51
- return this.live(key, this.clock.now().getTime())?.count ?? 0;
57
+ return this.live(key, this.tick())?.count ?? 0;
52
58
  }
53
- /** The window `key` is spending from, or undefined once it has rolled or was never opened. */
59
+ /**
60
+ * Milliseconds on a clock that only moves forward, accumulated from the wall clock's forward steps.
61
+ *
62
+ * Production passes the wall clock, which NTP can step backwards. Measured directly, a step back
63
+ * would give new windows an earlier start than older ones already at the head, breaking the
64
+ * eviction order, and make elapsed time negative, keeping spent windows alive past `windowMs`.
65
+ * A backward step here just pauses the limiter's time until the wall clock moves forward again.
66
+ */
67
+ tick() {
68
+ const wall = this.clock.now().getTime();
69
+ if (wall > this.lastWall)
70
+ this.elapsed += wall - this.lastWall;
71
+ this.lastWall = wall;
72
+ return this.elapsed;
73
+ }
74
+ /**
75
+ * The window `key` is spending from, or undefined once it has rolled or was never opened.
76
+ *
77
+ * A rolled window is removed here rather than overwritten later: Map#set keeps an existing key's
78
+ * insertion position, so overwriting would leave a fresh, possibly spent window at the head, first
79
+ * in line for eviction.
80
+ */
54
81
  live(key, now) {
55
82
  const entry = this.windows.get(key);
56
- if (!entry || now - entry.windowStart >= this.options.windowMs)
57
- return undefined;
58
- return entry;
83
+ if (!entry || !this.expired(entry, now))
84
+ return entry;
85
+ this.windows.delete(key);
86
+ return undefined;
87
+ }
88
+ expired(entry, now) {
89
+ return now - entry.windowStart >= this.options.windowMs;
59
90
  }
60
91
  /** Whole seconds until `entry`'s window rolls, rounded up. */
61
92
  retryAfter(entry, now) {
@@ -74,13 +105,13 @@ export class RateLimiter {
74
105
  return;
75
106
  this.lastPrune = now;
76
107
  for (const [key, entry] of this.windows) {
77
- if (now - entry.windowStart >= this.options.windowMs)
108
+ if (this.expired(entry, now))
78
109
  this.windows.delete(key);
79
110
  }
80
111
  }
81
112
  /** Hard bound on residency, for windows too long for `prune` to be the only collector. */
82
113
  evictOldest() {
83
- while (this.windows.size > MAX_KEYS) {
114
+ while (this.windows.size > this.maxKeys) {
84
115
  const oldest = this.windows.keys().next();
85
116
  if (oldest.done)
86
117
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"RateLimiter.js","sourceRoot":"","sources":["../../src/services/RateLimiter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"RateLimiter.js","sourceRoot":"","sources":["../../src/services/RateLimiter.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chaos-overlords/kernel",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "Runtime-neutral domain of the multiplayer server: entities, ports, pure turn logic and the lobby/turn/snapshot services.",
5
5
  "keywords": [
6
6
  "chaos-overlords",
@@ -52,7 +52,7 @@
52
52
  "provenance": true
53
53
  },
54
54
  "dependencies": {
55
- "@chaos-overlords/contracts": "0.9.0"
55
+ "@chaos-overlords/contracts": "0.9.1"
56
56
  },
57
57
  "devDependencies": {
58
58
  "typescript": "^7.0.2",