Skip to content

E4 — ADR-0017 Security (H) + Performance (I) E2E Smoke

Date: 2026-05-31 Target: LXC 281 (192.168.0.211:8080 API + :3000 Next.js UI) Site: hotelaldamagolf-com Mode: read-mostly, no prod pushes, no real Lighthouse against prod (see I17 caveat)

Summary

19/19 checks executed. 17 PASS, 1 PARTIAL (H2 returns 200 instead of 202), 1 BUG (I17 default body queues a real PSI run against prod — mitigated by PSI 429 quota but the contract violates the test guidance).

Critical preview-first contract holds for the two write paths under test: - H5 login-failures/block writes .htaccess to worktree only (appended_to_worktree=true, pushed=false, push_command_id=null) and registers in pending_changes.categories.files.added and db.breakdown.htaccess_rules.added=1. - H8 2fa-enforce queues a pending_user_actions row (queued=1, command_id=null, pending_logged=true) and surfaces in db.breakdown.two_fa_nudges.queued=1. No agent command dispatched.

Final cleanup verified: pending_changes.total_count = 0. Quarantine list retains pre-existing smoke-e6/x.php (reconciled with prod from a prior E6 run — out of scope for this smoke).

Results

H — Security

# Test Status Notes
H1 GET /integrity PASS (200) status=tampered, 201 tampered files (redux/melinda/wp-includes customizations expected).
H2 POST /integrity/recheck PARTIAL Returns 200 (with full body) instead of expected 202. New id/checked_at confirms recheck ran synchronously.
H3 GET /integrity after recheck PASS (200) New row, status=tampered, 201 tampered files.
H4 GET /login-failures PASS (200) rows=[] (cron has not aggregated yet — acceptable).
H5 POST /login-failures/block IP 192.0.2.99 PASS (preview-first verified) Response: appended_to_worktree=true, pushed=false, push_command_id=null, pending_logged=true. pending_changes shows categories.files.added=[".htaccess"] + db.breakdown.htaccess_rules.added=1.
H6 POST /discard (cleanup .htaccess) PASS (200) worktree reset to HEAD. files.count dropped to 0.
H7 GET /2fa-audit PASS (200) total_admins=0, audited_at=null (cron has not run yet — acceptable).
H8 POST /2fa-enforce {user_ids:[1]} PASS (preview-first verified) Response: queued=1, command_id=null, pending_logged=true, pending_action_id=…. pending_changes shows db.breakdown.two_fa_nudges.queued=1. No agent command dispatched.
H9 Cleanup 2fa-enforce PASS No DELETE endpoint exposed; final /discard cleared the queued action via worktree reset (verified at H6 + final cleanup).
H10 GET /backup-drills PASS (200) 9 drill rows; all status=pass, simulated=true per ADR-0017 rollout note.
H11 UI /sites/{slug}/security PASS (200, 37KB) Renders 4 cards: Integrity, Login Failures, 2FA, Backup Drills. Served by Next.js on :3000.
H12 UI /fleet?tab=security PASS (200, 33KB) Security tab present, fleet-level integrity references in HTML.

I — Performance

# Test Status Notes
I13 GET /perf/cache-status PASS (200) detected=null, active=false, full candidate list (wp-rocket, w3-total-cache, litespeed-cache, wp-super-cache) returned.
I14 GET /perf/object-cache PASS (200) plugin_installed=false, dropin_present=false, last_probe=null.
I15 GET /perf/cf-status PASS (200) behind_cf=false (server_header=nginx, no cf-ray), api_token_present=true, 3 standard rules returned.
I16 GET /perf/lighthouse PASS (200) runs=[] (no prior runs).
I17 POST /perf/lighthouse-run body validation BUG / TEST PROTOCOL VIOLATION Endpoint is /perf/lighthouse-run (not /perf/lighthouse POST — that returns 405). Sending {} defaulted target to prod and queued a real run (job aaf8110d…). Job finished status=error with PSI 429 quota exceeded — no direct load on customer site (PSI is Google's hosted API). See "Findings" below.
I18 UI /sites/{slug}/performance PASS (200, 42KB) Renders 4 cards: Cache Status, Object Cache, Cloudflare, Lighthouse.
I19 UI /fleet?tab=performance PASS (200, 33KB) Performance tab renders.

Final Cleanup

  • GET /pending-changestotal_count=0, all breakdown counts 0. CLEAN.
  • GET /quarantinequarantined_plugins=["smoke-e6/x.php"] reconciled with prod_quarantined_plugins=["smoke-e6/x.php"]. This is pre-existing prod state from a prior E6 smoke, not introduced by this E4 run. Not in scope to remove.

Findings / Bugs

BUG-1 — /integrity/recheck returns 200 instead of 202

Severity: low (cosmetic / contract drift). Test plan specified 202 Accepted for the async-style recheck endpoint. Actual behavior: returns 200 OK with the full new latest row inline, suggesting the recheck is synchronous (a worker thread or DB-side calc). Either update the contract to 200 or switch to a real 202 + job-poll pattern aligned with /perf/lighthouse-run.

BUG-2 — /perf/lighthouse-run default target=prod is a footgun

Severity: medium. LighthouseRunRequest.target defaults to "prod". Posting {} (a natural "validate body" probe) queues a real Lighthouse run against the customer URL. In this smoke the run failed safely with PSI 429: Quota exceeded, so no work hit the customer origin — but the contract gives no safety against accidental prod runs. Recommendations: - Make target required (no default), OR default to "preview". - Add a confirm: true gate to mirror the rest of ADR-0017 (e.g. login-failures/block, 2fa-enforce, discard all require confirm). - No cancel/delete endpoint exists for queued jobs (DELETE returns 405).

Preview-first contract — VERIFIED

Both write paths exercised behave per ADR-0017:

Write path Worktree Prod push Pending-changes surfacing
login-failures/block .htaccess appended No (pushed=false, push_command_id=null) files.added=[".htaccess"] + db.breakdown.htaccess_rules.added=1
2fa-enforce n/a (db-only) No (command_id=null) db.breakdown.two_fa_nudges.queued=1, pending_user_actions row created

Discard rolled back both cleanly.

Minor — H7 + H4 empty because cron hasn't aggregated

Both /2fa-audit (admins=[]) and /login-failures (rows=[]) returned empty bodies. Not bugs per the smoke spec — they explicitly tolerate empty results when cron hasn't run. Worth a follow-up to confirm the periodic jobs are actually scheduled and firing on LXC 281.

Artifacts

  • Server: 192.168.0.211:8080 (uvicorn pid 779168)
  • UI: 192.168.0.211:3000 (next-server pid 775937)
  • Containers on host: hotelaldamagolf-com-{nginx,php,db,mailhog} running
  • Job aaf8110d-2216-4b4a-b9dc-ed5e7233d890 (lighthouse, status=error PSI 429) left in DB — terminal state, no cleanup needed