From 39847fc8765cc277a56929b2ea16a7015762daf1 Mon Sep 17 00:00:00 2001 From: Hephaestus Date: Sat, 23 May 2026 08:17:02 +0200 Subject: [PATCH 1/2] =?UTF-8?q?docs:=20fix=20PATCH=20/v1/sessions/:id=20RB?= =?UTF-8?q?AC=20role=20table=20=E2=80=94=20route=20uses=20ownership=20scop?= =?UTF-8?q?ing,=20not=20requireRole?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PATCH endpoint for pinned sessions uses withOwnership (key-based session ownership) rather than requireRole. The docs incorrectly stated 'admin, operator' role requirement. Updated to accurately reflect that any authenticated key owning the session can call this endpoint. --- docs/api-reference.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/api-reference.md b/docs/api-reference.md index b3ffaf5d..590acf18 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -883,9 +883,7 @@ PATCH /v1/sessions/:id Updates mutable session metadata fields. Currently supports pinning sessions to protect them from automatic reaping. -| Role | Required | -|------|----------| -| admin, operator | Yes | +> **Ownership:** Requires a valid API key that owns the session (enforced by `withOwnership`). ```bash # Pin a session (reapers will never kill it) From c2aada896bc8f7e7da19040dbf49d40ababa6d13 Mon Sep 17 00:00:00 2001 From: Hephaestus Date: Sat, 23 May 2026 08:17:31 +0200 Subject: [PATCH 2/2] fix(test): otel-hostname-config test imports real loadTracingConfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous test defined a local loadConfig() that duplicated loadTracingConfig() from src/tracing.ts — test passed even if the real code broke (false confidence). Rewrite to import the real function with vi.resetModules() + dynamic import() for proper module isolation. --- .gitignore | 1 + src/__tests__/otel-hostname-config.test.ts | 89 +++++++++++++--------- 2 files changed, 55 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index 204d44fd..9977caa2 100644 --- a/.gitignore +++ b/.gitignore @@ -83,3 +83,4 @@ test-results/ wt/ coverage/ wt-last-updated +wt-i18n-sessionboard diff --git a/src/__tests__/otel-hostname-config.test.ts b/src/__tests__/otel-hostname-config.test.ts index 738b7218..b8268a33 100644 --- a/src/__tests__/otel-hostname-config.test.ts +++ b/src/__tests__/otel-hostname-config.test.ts @@ -1,70 +1,89 @@ -import { describe, it, expect, beforeEach, afterEach } from 'vitest'; - -// We test loadTracingConfig directly since it's a pure function -// that reads environment variables. +/** + * Tests for loadTracingConfig — hostname/PID env var handling. + * + * Issue: Argus audit found the previous test defined a local loadConfig() + * that duplicated loadTracingConfig() from src/tracing.ts. It never imported + * the real function — test passed even if the real code broke. + * + * Fix: Import the real loadTracingConfig with module isolation so env changes + * are picked up correctly. + */ +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; describe('loadTracingConfig — hostname/PID options', () => { - const originalEnv = { ...process.env }; + const savedEnv: Record = {}; + + const otelKeys = [ + 'AEGIS_OTEL_ENABLED', + 'AEGIS_OTEL_SERVICE_NAME', + 'AEGIS_OTEL_OTLP_ENDPOINT', + 'AEGIS_OTEL_SAMPLE_RATE', + 'AEGIS_OTEL_INCLUDE_HOSTNAME', + 'AEGIS_OTEL_INCLUDE_PID', + ]; + + beforeEach(() => { + for (const key of otelKeys) { + savedEnv[key] = process.env[key]; + delete process.env[key]; + } + }); afterEach(() => { - // Restore original env - process.env = { ...originalEnv }; + for (const key of otelKeys) { + if (savedEnv[key] === undefined) { + delete process.env[key]; + } else { + process.env[key] = savedEnv[key]; + } + } + vi.resetModules(); }); - function loadConfig() { - // Re-import to pick up env changes - // Using dynamic import with cache busting - const config = { - enabled: process.env.AEGIS_OTEL_ENABLED === 'true', - serviceName: process.env.AEGIS_OTEL_SERVICE_NAME || 'aegis', - otlpEndpoint: process.env.AEGIS_OTEL_OTLP_ENDPOINT || 'http://localhost:4318', - sampleRate: parseFloat(process.env.AEGIS_OTEL_SAMPLE_RATE || '1.0'), - includeHostname: process.env.AEGIS_OTEL_INCLUDE_HOSTNAME !== 'false', - includePid: process.env.AEGIS_OTEL_INCLUDE_PID !== 'false', - }; - return config; + /** Import the real loadTracingConfig with fresh module cache. */ + async function loadRealConfig() { + const { loadTracingConfig } = await import('../tracing.js'); + return loadTracingConfig(); } - it('defaults includeHostname to true', () => { - delete process.env.AEGIS_OTEL_INCLUDE_HOSTNAME; - const config = loadConfig(); + it('defaults includeHostname to true', async () => { + const config = await loadRealConfig(); expect(config.includeHostname).toBe(true); }); - it('defaults includePid to true', () => { - delete process.env.AEGIS_OTEL_INCLUDE_PID; - const config = loadConfig(); + it('defaults includePid to true', async () => { + const config = await loadRealConfig(); expect(config.includePid).toBe(true); }); - it('sets includeHostname to false when AEGIS_OTEL_INCLUDE_HOSTNAME=false', () => { + it('sets includeHostname to false when AEGIS_OTEL_INCLUDE_HOSTNAME=false', async () => { process.env.AEGIS_OTEL_INCLUDE_HOSTNAME = 'false'; - const config = loadConfig(); + const config = await loadRealConfig(); expect(config.includeHostname).toBe(false); }); - it('sets includePid to false when AEGIS_OTEL_INCLUDE_PID=false', () => { + it('sets includePid to false when AEGIS_OTEL_INCLUDE_PID=false', async () => { process.env.AEGIS_OTEL_INCLUDE_PID = 'false'; - const config = loadConfig(); + const config = await loadRealConfig(); expect(config.includePid).toBe(false); }); - it('keeps includeHostname true for non-"false" values', () => { + it('keeps includeHostname true for non-"false" values', async () => { process.env.AEGIS_OTEL_INCLUDE_HOSTNAME = 'yes'; - const config = loadConfig(); + const config = await loadRealConfig(); expect(config.includeHostname).toBe(true); }); - it('keeps includePid true for non-"false" values', () => { + it('keeps includePid true for non-"false" values', async () => { process.env.AEGIS_OTEL_INCLUDE_PID = '0'; - const config = loadConfig(); + const config = await loadRealConfig(); expect(config.includePid).toBe(true); }); - it('both can be disabled simultaneously', () => { + it('both can be disabled simultaneously', async () => { process.env.AEGIS_OTEL_INCLUDE_HOSTNAME = 'false'; process.env.AEGIS_OTEL_INCLUDE_PID = 'false'; - const config = loadConfig(); + const config = await loadRealConfig(); expect(config.includeHostname).toBe(false); expect(config.includePid).toBe(false); });