From 55a3f1e6b23a9f6d5e0c3cf80741961102e98e3b Mon Sep 17 00:00:00 2001 From: Deep-Axe Date: Mon, 26 Oct 2026 17:16:15 +0530 Subject: [PATCH] Bring metrics up to date with other replicas and list the new tests GET /api/metrics now runs the registry revision check first, like the server list, so servers added or removed through another replica appear at once. The verification guide lists the credential and scaling test files and the current test count. --- docs/verification.md | 4 +++- services/gateway/src/dashboard-api.ts | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/verification.md b/docs/verification.md index 0578b0a..a07e464 100644 --- a/docs/verification.md +++ b/docs/verification.md @@ -2,7 +2,7 @@ ## Automated test suite -`npm test` runs 40 deterministic unit and protocol tests across eleven test files without making paid OpenAI calls: +`npm test` runs 52 deterministic unit and protocol tests across thirteen test files without making paid OpenAI calls: - **`tests/gateway.test.ts`:** API key HMAC digest lookup, revoked-key attribution after restart, `__` tool collision routing (`time__get_status` vs `ops__get_status`), immediate route removal on disable, hung upstream timeout isolation, uncertain mutation auditing without retries, argument schema validation, cross-team route isolation, audit-failure fail-closed behavior, and full MCP SDK Streamable HTTP exchanges. - **`tests/mcp-notifications.test.ts`:** Stateful Streamable HTTP + GET SSE sessions, team-scoped `notifications/tools/list_changed` delivery, suppression of unchanged catalog refreshes, cross-user/cross-key session rejection (`403`), revoked-key notification cutoff, per-user/global session limits (`429`), `DELETE` cleanup, and idle session expiry (`404`). @@ -11,6 +11,8 @@ - **`tests/woocommerce.test.ts`:** OAuth 1.0a HMAC-SHA256 canonical host signing, direct HTTP transport for both HTTP and HTTPS public store URLs, redirect/HTML/auth error rejection without mutation retry, and service token / CORS enforcement. - **`tests/chat.test.ts`, `tests/chat-admission.test.ts` & `tests/dashboard-api.test.ts`:** Scripted OpenAI Responses multi-round tool continuation, mid-turn catalog/authz rechecks, round/call/context bounds, DST-aware store day windows, categorized provider/timeout errors, atomic conversation persistence, and per-user/team/global admission limits that do not charge rejected requests against the hourly quota. - **`tests/metrics.test.ts`:** Per-server outcome counts and latency aggregation from the audit log, team and time-window filters, histogram-based p95 interpolation, and Prometheus exposition (counters, cumulative histogram buckets, upstream gauges, label escaping). +- **`tests/credentials.test.ts`:** AES-256-GCM credential round trips with a fresh IV per write, fail-closed handling of altered IVs, tags and data, entries moved to another server's slot or read with another pepper, one-time sealing of plaintext entries guarded by the Secret's `resourceVersion`, removal of the plaintext copy kept by `kubectl apply`, and sealed development file credentials. +- **`tests/scaling.test.ts`:** Two gateway replicas behind one origin sharing a database and session store: a session started on one replica continuing on the other, `DELETE` ending it on both, session limits across replicas, rebuilding a session after a replica loses its local copy, registry changes applied before routing, catalog notifications for a stream whose handshake finished on the other replica, and the per-key request limit shared by both replicas with `rate_limited` auditing. - **`tests/scripts.test.ts`:** `kubectl` binary resolution order and host-wide `flock` cluster lock contention (`exit 73`) and release. ## Cluster smoke checks diff --git a/services/gateway/src/dashboard-api.ts b/services/gateway/src/dashboard-api.ts index 2054722..4dddb40 100644 --- a/services/gateway/src/dashboard-api.ts +++ b/services/gateway/src/dashboard-api.ts @@ -243,6 +243,8 @@ export function dashboardApi(options: Options) { .default(24) .parse(req.query.hours); const { teamId } = actor(res); + // Include servers added or removed through another replica. + await registry.ensureCurrent(); const stats = await store.callStats({ teamId, since: new Date(Date.now() - hours * 60 * 60 * 1000),