companion-loopback-guard-performance.test.mjs
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd
feat(calendar): enforce agent context tiers in retrieval AP…
Human
minor
⚠ breaking
1 day ago
| 1 | /** |
| 2 | * Tier 6 — PERFORMANCE: the guard must add negligible, bounded overhead. |
| 3 | * |
| 4 | * The loopback endpoint will call verifyLoopbackRequest on EVERY request before any model work, |
| 5 | * so its cost must be tiny and must not degrade with request volume (gate §10 performance: |
| 6 | * endpoint overhead bounds; no event-loop starvation). These are generous CI-safe thresholds — |
| 7 | * they catch accidental O(n^2) / blocking regressions, not micro-fluctuations. |
| 8 | * |
| 9 | * Reference: docs/COMPANION-APP-DESIGN-AND-AUTHORIZATION-GATE.md §10 (performance). |
| 10 | */ |
| 11 | import { describe, it } from 'node:test'; |
| 12 | import assert from 'node:assert/strict'; |
| 13 | import { |
| 14 | verifyLoopbackRequest, |
| 15 | createLoopbackRateState, |
| 16 | recordLoopbackRequest, |
| 17 | shouldCountTowardRateLimit, |
| 18 | } from '../lib/companion-loopback-guard.mjs'; |
| 19 | |
| 20 | const PORT = '54000'; |
| 21 | const TOKEN = 'perf-' + 'a'.repeat(40); |
| 22 | const ALLOWED_HOSTS = [`127.0.0.1:${PORT}`, `localhost:${PORT}`]; |
| 23 | |
| 24 | function base(overrides = {}, rateState) { |
| 25 | return { |
| 26 | method: 'POST', |
| 27 | headers: { Host: `127.0.0.1:${PORT}`, Origin: `http://127.0.0.1:${PORT}`, 'Sec-Fetch-Site': 'same-origin' }, |
| 28 | token: TOKEN, |
| 29 | expectedToken: TOKEN, |
| 30 | allowedHosts: ALLOWED_HOSTS, |
| 31 | now: 0, |
| 32 | rateState, |
| 33 | ...overrides, |
| 34 | }; |
| 35 | } |
| 36 | |
| 37 | describe('Performance — per-decision overhead', () => { |
| 38 | it('100k admit decisions complete well under 2 seconds', () => { |
| 39 | const rateState = { windowMs: 60_000, maxRequests: 1_000_000, timestamps: [] }; |
| 40 | const start = performance.now(); |
| 41 | for (let i = 0; i < 100_000; i++) { |
| 42 | verifyLoopbackRequest(base({ now: i }, rateState)); |
| 43 | } |
| 44 | const elapsed = performance.now() - start; |
| 45 | assert.ok(elapsed < 2000, `100k decisions took ${elapsed.toFixed(1)}ms, expected < 2000ms`); |
| 46 | }); |
| 47 | |
| 48 | it('mean per-decision cost is sub-millisecond', () => { |
| 49 | const rateState = { windowMs: 60_000, maxRequests: 1_000_000, timestamps: [] }; |
| 50 | const N = 50_000; |
| 51 | const start = performance.now(); |
| 52 | for (let i = 0; i < N; i++) verifyLoopbackRequest(base({ now: i }, rateState)); |
| 53 | const perCall = (performance.now() - start) / N; |
| 54 | assert.ok(perCall < 0.5, `mean ${perCall.toFixed(4)}ms/call, expected < 0.5ms`); |
| 55 | }); |
| 56 | }); |
| 57 | |
| 58 | describe('Performance — no super-linear blowup with rate window size', () => { |
| 59 | it('decision cost with a steady-state window does not explode', () => { |
| 60 | // Fill a window to its cap, then time decisions against the full window. |
| 61 | let state = createLoopbackRateState({ windowMs: 10_000, maxRequests: 1000 }); |
| 62 | for (let i = 0; i < 1000; i++) { |
| 63 | const v = verifyLoopbackRequest(base({ now: i }, state)); |
| 64 | if (shouldCountTowardRateLimit(v)) state = recordLoopbackRequest(state, i); |
| 65 | } |
| 66 | const start = performance.now(); |
| 67 | for (let i = 0; i < 20_000; i++) verifyLoopbackRequest(base({ now: 1000 + i }, state)); |
| 68 | const elapsed = performance.now() - start; |
| 69 | assert.ok(elapsed < 2000, `20k decisions over a 1000-entry window took ${elapsed.toFixed(1)}ms`); |
| 70 | }); |
| 71 | }); |
| 72 | |
| 73 | describe('Performance — constant-time compare is not pathologically slow', () => { |
| 74 | it('100k token comparisons (hash + timingSafeEqual) stay bounded', () => { |
| 75 | const rateState = { windowMs: 60_000, maxRequests: 1_000_000, timestamps: [] }; |
| 76 | const start = performance.now(); |
| 77 | for (let i = 0; i < 100_000; i++) { |
| 78 | verifyLoopbackRequest(base({ token: `wrong-${i}` }, rateState)); |
| 79 | } |
| 80 | const elapsed = performance.now() - start; |
| 81 | assert.ok(elapsed < 3000, `100k constant-time compares took ${elapsed.toFixed(1)}ms`); |
| 82 | }); |
| 83 | }); |
File History
2 commits
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd
feat(calendar): enforce agent context tiers in retrieval AP…
Human
minor
⚠
1 day ago
sha256:9103f98c89257ed2b01c237cea895dabb3e85ea337dccb1161c175e4422355b6
docs: accept Calendar Events v0 spec with Phase 0 security …
Human
1 day ago