# A-3 Pre-Fix Test Suite **Date:** 2026-03-28 **Branch:** culurien **Purpose:** Document auth middleware coverage bugs BEFORE fixes are applied. **Reference:** A-3 Auth Middleware Audit (recon findings F-A3-1 through F-A3-14) These tests prove that the bugs exist today and will prove the fixes work when applied. Do NOT modify these tests before the fix is ready — they are the regression baseline. --- ## Test Files Created | File | Package | Bugs Documented | |------|---------|-----------------| | `aggregator-server/internal/api/middleware/auth_secret_leak_test.go` | `middleware_test` | F-A3-11 (agent-side baseline) | | `aggregator-server/internal/api/handlers/auth_middleware_leak_test.go` | `handlers_test` | F-A3-11 (web middleware leak) | | `aggregator-server/internal/api/handlers/downloads_auth_test.go` | `handlers_test` | F-A3-7, F-A3-6 | | `aggregator-server/internal/api/middleware/scheduler_auth_test.go` | `middleware_test` | F-A3-10 | | `aggregator-server/internal/api/middleware/token_confusion_test.go` | `middleware_test` | F-A3-12 | | `aggregator-server/internal/api/handlers/auth_verify_test.go` | `handlers_test` | F-A3-2 | | `aggregator-server/internal/api/middleware/require_admin_test.go` | `middleware_test` | F-A3-13 | | `aggregator-server/internal/api/middleware/require_admin_behavior_test.go` | `middleware_test` | F-A3-13 (build-tagged, cannot compile yet) | | `aggregator-server/internal/api/handlers/agent_unregister_test.go` | `handlers_test` | F-A3-9 | --- ## How to Run ```bash # Middleware tests (scheduler, token confusion, RequireAdmin, agent auth) cd aggregator-server && go test ./internal/api/middleware/... -v # Handler tests (JWT leak, downloads auth, verify, unregister) cd aggregator-server && go test ./internal/api/handlers/... -v # Run specific test groups cd aggregator-server && go test ./internal/api/middleware/... -v -run TestScheduler cd aggregator-server && go test ./internal/api/middleware/... -v -run TestToken cd aggregator-server && go test ./internal/api/middleware/... -v -run TestRequireAdmin cd aggregator-server && go test ./internal/api/handlers/... -v -run TestWebAuth cd aggregator-server && go test ./internal/api/handlers/... -v -run TestConfigDownload cd aggregator-server && go test ./internal/api/handlers/... -v -run TestAuthVerify ``` --- ## Test Inventory ### File 1: `middleware/auth_secret_leak_test.go` — Agent Middleware Baseline #### `TestAgentAuthMiddlewareDoesNotLogSecret` - **Bug:** F-A3-11 (baseline contrast — agent middleware is clean) - **Asserts:** Agent AuthMiddleware does NOT print JWT secret to stdout - **Current state:** PASS (agent middleware is not affected) - **Purpose:** Establishes that the leak is specific to WebAuthMiddleware #### `TestAgentAuthMiddlewareLogHasNoEmoji` - **Bug:** F-A3-11 (baseline contrast) - **Asserts:** Agent AuthMiddleware stdout has no emoji characters - **Current state:** PASS ### File 2: `handlers/auth_middleware_leak_test.go` — WebAuth Secret Leak #### `TestWebAuthMiddlewareDoesNotLogSecret` - **Bug:** F-A3-11 CRITICAL - **Asserts:** WebAuthMiddleware stdout does NOT contain the JWT secret string - **Current state:** FAIL — auth.go:128 prints `h.jwtSecret` directly - **After fix:** PASS — remove secret from log output #### `TestWebAuthMiddlewareLogFormatHasNoEmoji` - **Bug:** F-A3-11 CRITICAL - **Asserts:** WebAuthMiddleware stdout has no emoji (specifically U+1F513), word "secret" absent - **Current state:** FAIL — output contains lock emoji and word "secret" - **After fix:** PASS — use `[WARNING] [server] [auth]` format #### `TestWebAuthMiddlewareLogFormatCompliant` - **Bug:** F-A3-11 CRITICAL - **Asserts:** If stdout output exists, lines start with `[TAG]` pattern, no secret in output - **Current state:** FAIL — output is emoji-prefixed, contains secret - **After fix:** PASS — ETHOS-compliant format or no stdout output ### File 3: `handlers/downloads_auth_test.go` — Unauthenticated Downloads #### `TestConfigDownloadRequiresAuth` - **Bug:** F-A3-7 CRITICAL - **Asserts:** GET /downloads/config/:agent_id returns 401/403 without auth - **Current state:** FAIL — returns 200 (no auth middleware on route) - **After fix:** PASS — add AuthMiddleware or WebAuthMiddleware #### `TestConfigDownloadCurrentlyUnauthenticated` - **Bug:** F-A3-7 CRITICAL - **Asserts:** Config download succeeds without auth (documents bug) - **Current state:** PASS — no auth middleware, request reaches handler - **After fix:** FAIL — update to assert 401 #### `TestUpdatePackageDownloadRequiresAuth` - **Bug:** F-A3-6 HIGH - **Asserts:** GET /downloads/updates/:package_id returns 401/403 without auth - **Current state:** FAIL — returns 200 (no auth middleware) - **After fix:** PASS — add AuthMiddleware #### `TestUpdatePackageDownloadCurrentlyUnauthenticated` - **Bug:** F-A3-6 HIGH - **Asserts:** Update package download succeeds without auth (documents bug) - **Current state:** PASS - **After fix:** FAIL — update to assert 401 ### File 4: `middleware/scheduler_auth_test.go` — Scheduler Wrong Auth #### `TestSchedulerStatsRequiresAdminAuth` - **Bug:** F-A3-10 HIGH - **Asserts:** Agent JWT is rejected on /scheduler/stats (should require admin) - **Current state:** FAIL — agent JWT accepted (200) - **After fix:** PASS — change to WebAuthMiddleware #### `TestSchedulerStatsCurrentlyAcceptsAgentJWT` - **Bug:** F-A3-10 HIGH - **Asserts:** Agent JWT is accepted on /scheduler/stats (documents bug) - **Current state:** PASS — AuthMiddleware accepts agent JWT - **After fix:** FAIL — update to assert rejection ### File 5: `middleware/token_confusion_test.go` — Cross-Type Token Confusion #### `TestWebTokenRejectedByAgentAuthMiddleware` - **Bug:** F-A3-12 MEDIUM - **Asserts:** Web/admin JWT is rejected by agent AuthMiddleware - **Current state:** FAIL — web JWT passes agent auth (shared secret, no audience check) - **After fix:** PASS — add issuer/audience claims or separate secrets #### `TestAgentTokenRejectedByWebAuthMiddleware` - **Bug:** F-A3-12 MEDIUM - **Asserts:** Agent JWT is rejected by WebAuthMiddleware - **Current state:** FAIL — agent JWT passes web auth (shared secret, claims parse succeeds) - **After fix:** PASS — add issuer/audience claims or separate secrets ### File 6: `handlers/auth_verify_test.go` — Dead Verify Endpoint #### `TestAuthVerifyAlwaysReturns401WithoutMiddleware` - **Bug:** F-A3-2 MEDIUM - **Asserts:** /auth/verify returns 401 even with valid JWT (no middleware sets context) - **Current state:** PASS — documents the dead endpoint - **After fix:** N/A (test documents pre-fix state) #### `TestAuthVerifyWorksWithMiddleware` - **Bug:** F-A3-2 MEDIUM - **Asserts:** /auth/verify returns 200 when WebAuthMiddleware is applied - **Current state:** PASS — demonstrates the fix is just adding middleware to the route - **Note:** This test already passes because it applies WebAuthMiddleware directly. The bug is in the route registration (main.go:388), not in the handler code. ### File 7: `middleware/require_admin_test.go` — Missing RequireAdmin #### `TestRequireAdminMiddlewareExists` - **Bug:** F-A3-13 LOW - **Asserts:** RequireAdmin function exists in middleware package (AST scan) - **Current state:** FAIL — function not found - **After fix:** PASS — implement RequireAdmin() ### File 8: `middleware/require_admin_behavior_test.go` — RequireAdmin Behavior - **Build tag:** `//go:build ignore` — cannot compile until RequireAdmin exists - **Bug:** F-A3-13 LOW - **Contains:** `TestRequireAdminBlocksNonAdminUsers` — tests admin vs non-admin role check - **Current state:** Cannot compile (skipped) - **After fix:** Remove build tag, test should PASS ### File 9: `handlers/agent_unregister_test.go` — Missing Rate Limit #### `TestAgentSelfUnregisterHasNoRateLimit` - **Bug:** F-A3-9 MEDIUM - **Asserts:** Documents that DELETE /:id route has no rate limiter - **Current state:** PASS — documents the bug #### `TestAgentSelfUnregisterShouldHaveRateLimit` - **Bug:** F-A3-9 MEDIUM - **Asserts:** DELETE /:id SHOULD have rate limiter in middleware chain - **Current state:** FAIL — no rate limiter on route - **After fix:** PASS — add rate limiter --- ## State-Change Summary | Test | Current | After Fix | |------|---------|-----------| | TestAgentAuthMiddlewareDoesNotLogSecret | PASS | PASS (unchanged) | | TestAgentAuthMiddlewareLogHasNoEmoji | PASS | PASS (unchanged) | | TestWebAuthMiddlewareDoesNotLogSecret | **FAIL** | PASS | | TestWebAuthMiddlewareLogFormatHasNoEmoji | **FAIL** | PASS | | TestWebAuthMiddlewareLogFormatCompliant | **FAIL** | PASS | | TestConfigDownloadRequiresAuth | **FAIL** | PASS | | TestConfigDownloadCurrentlyUnauthenticated | PASS | FAIL (update) | | TestUpdatePackageDownloadRequiresAuth | **FAIL** | PASS | | TestUpdatePackageDownloadCurrentlyUnauthenticated | PASS | FAIL (update) | | TestSchedulerStatsRequiresAdminAuth | **FAIL** | PASS | | TestSchedulerStatsCurrentlyAcceptsAgentJWT | PASS | FAIL (update) | | TestWebTokenRejectedByAgentAuthMiddleware | **FAIL** | PASS | | TestAgentTokenRejectedByWebAuthMiddleware | **FAIL** | PASS | | TestAuthVerifyAlwaysReturns401WithoutMiddleware | PASS | PASS (unchanged) | | TestAuthVerifyWorksWithMiddleware | PASS | PASS (unchanged) | | TestRequireAdminMiddlewareExists | **FAIL** | PASS | | TestRequireAdminBlocksNonAdminUsers | SKIP (build tag) | PASS | | TestAgentSelfUnregisterHasNoRateLimit | PASS | PASS (unchanged) | | TestAgentSelfUnregisterShouldHaveRateLimit | **FAIL** | PASS | **Bold FAIL** = tests that assert correct post-fix behavior (will flip to PASS after fix). Regular PASS = tests that document current buggy state (some will flip to FAIL after fix). --- ## Notes 1. **TestAuthVerifyWorksWithMiddleware** passes even in pre-fix state because it directly applies WebAuthMiddleware to the test router. The bug is not in the handler but in the route registration (main.go:388 missing middleware). This test validates that the fix is a one-line change. 2. **TestAgentTokenRejectedByWebAuthMiddleware** reveals that JWT cross-type confusion works in BOTH directions: agent tokens pass web auth AND web tokens pass agent auth. The `jwt.ParseWithClaims` call succeeds because both claim types share the same signing key and the JSON unmarshaling is permissive. 3. **require_admin_behavior_test.go** uses `//go:build ignore` because it references `middleware.RequireAdmin` which does not exist. Enable this test when F-A3-13 is fixed by removing the build tag. 4. All A-2 tests continue to pass (no regressions from A-3 test additions).