phase: 03_nginx_security_headers
Build and Push Container / build-and-push (push) Successful in 23s

**Phase 03 final verification — all green**

- Verified (all tasks already in `complete/`): snippet/Dockerfile/nginx.conf wiring, `scripts/check-headers.sh`, guardrail teeth, restored config byte-identical.
- Tests (full suite): `./build.sh` → OK; `npm test` → **46 passed, 0 failed**; `bash .agents/validate.sh` → **exit 0** (46/46 + `HEADER CHECK PASSED` + hygiene gates); no leftover podman images.
- Completion criteria:
  - `nginx-security-headers.inc` with 4 `add_header … always;` lines — ✅
  - `nginx.conf`: 0 inline security `add_header` (cache headers only), 3/3 locations `include` snippet — ✅
  - `server_tokens off;` in server block — ✅ (live proof: `Server: nginx`, no version)
  - `./scripts/check-headers.sh` → `HEADER CHECK PASSED`, OK on `/`, `/index.html`, hashed asset — ✅ (also confirmed all 4 headers + correct Cache-Control on 404 fallback)
  - `./build.sh && npm test` fully green — ✅
  - No behavior change (terminal/vim/achievements/menu suites) — ✅
  - Negative check re-run: dropping one `include` → `FAIL … on /style.<hash>.css`, exit 1 — ✅
- Docs: README.md & AGENTS.md reviewed in full against actual state (commands, ports 8123/18099, header mechanism, CI tags vs `.gitea/workflows/build-push.yml`, Node ≥20 engine floor, innerHTML/neofetch exception at `terminal.js:487`, simulated curl/wget guards) — **verified consistent, no changes needed**.
- Notable: check-headers.sh aborts at the first failing path via `set -e` before printing `HEADER CHECK FAILED` — README's wording matches this exactly (verified empirically). PLAN.md's "44 tests" count is stale (now 46) but PLAN.md is locked — left for the user.
- No live-infra changes (no HSTS in container; edge/Caddy untouched).
- Next pending phase: `04_huntington_role`.
This commit is contained in:
2026-10-23 00:07:13 -04:00
parent bcfaa1cac6
commit 47b7b4fc23
20 changed files with 1459 additions and 16 deletions
@@ -0,0 +1,16 @@
**Phase 03 final verification — all green**
- Verified (all tasks already in `complete/`): snippet/Dockerfile/nginx.conf wiring, `scripts/check-headers.sh`, guardrail teeth, restored config byte-identical.
- Tests (full suite): `./build.sh` → OK; `npm test` → **46 passed, 0 failed**; `bash .agents/validate.sh` → **exit 0** (46/46 + `HEADER CHECK PASSED` + hygiene gates); no leftover podman images.
- Completion criteria:
- `nginx-security-headers.inc` with 4 `add_header … always;` lines — ✅
- `nginx.conf`: 0 inline security `add_header` (cache headers only), 3/3 locations `include` snippet — ✅
- `server_tokens off;` in server block — ✅ (live proof: `Server: nginx`, no version)
- `./scripts/check-headers.sh` → `HEADER CHECK PASSED`, OK on `/`, `/index.html`, hashed asset — ✅ (also confirmed all 4 headers + correct Cache-Control on 404 fallback)
- `./build.sh && npm test` fully green — ✅
- No behavior change (terminal/vim/achievements/menu suites) — ✅
- Negative check re-run: dropping one `include` → `FAIL … on /style.<hash>.css`, exit 1 — ✅
- Docs: README.md & AGENTS.md reviewed in full against actual state (commands, ports 8123/18099, header mechanism, CI tags vs `.gitea/workflows/build-push.yml`, Node ≥20 engine floor, innerHTML/neofetch exception at `terminal.js:487`, simulated curl/wget guards) — **verified consistent, no changes needed**.
- Notable: check-headers.sh aborts at the first failing path via `set -e` before printing `HEADER CHECK FAILED` — README's wording matches this exactly (verified empirically). PLAN.md's "44 tests" count is stale (now 46) but PLAN.md is locked — left for the user.
- No live-infra changes (no HSTS in container; edge/Caddy untouched).
- Next pending phase: `04_huntington_role`.
@@ -0,0 +1,437 @@
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:38] "GET /index.html HTTP/1.1" 200 -
Running 46 tests using 1 worker
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:39] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:39] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:39] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:39] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:39] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:39] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:39] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:39] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 1 [chromium] › tests/e2e/01-page.spec.js:9:5 › Page structure › loads with correct title and lang (1.0s)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:40] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:40] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:40] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:40] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:40] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:40] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:40] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:40] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 2 [chromium] › tests/e2e/01-page.spec.js:14:5 › Page structure › nav has all seven section links pointing at existing targets (493ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:40] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:40] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:40] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:40] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:40] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:40] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:40] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:40] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 3 [chromium] › tests/e2e/01-page.spec.js:24:5 › Page structure › all major sections exist and are in the DOM (486ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:41] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:41] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:41] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:41] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:41] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:41] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:41] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:41] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 4 [chromium] › tests/e2e/01-page.spec.js:30:5 › Page structure › profile image loads (462ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:41] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:41] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:41] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:41] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:41] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:41] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:41] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:41] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 5 [chromium] › tests/e2e/01-page.spec.js:38:5 › Page structure › server rack background is generated with a terminal unit (442ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:42] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:42] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:42] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:42] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:42] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:42] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:42] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:42] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 6 [chromium] › tests/e2e/01-page.spec.js:45:5 › Page structure › GPG section shows both fingerprints and key blocks (504ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:42] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:42] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:42] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:42] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:42] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:42] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:42] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:42] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 7 [chromium] › tests/e2e/01-page.spec.js:59:5 › Page structure › external links all carry rel="noopener" (467ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:43] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:43] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:43] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:43] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:43] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:43] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:43] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:43] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:43] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
✓ 8 [chromium] › tests/e2e/01-page.spec.js:68:5 › Page structure › hashed assets are referenced and served (459ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:43] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:43] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:43] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:43] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:43] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:43] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:43] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:43] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 9 [chromium] › tests/e2e/02-terminal.spec.js:11:5 › Fake terminal — basic commands › hero click expands the terminal and shifts the hero (486ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:44] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:44] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:44] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:44] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:44] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:44] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:44] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:44] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 10 [chromium] › tests/e2e/02-terminal.spec.js:17:5 › Fake terminal — basic commands › initial boot lines are rendered (524ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:44] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:44] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:44] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:44] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:44] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:44] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:44] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:44] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 11 [chromium] › tests/e2e/02-terminal.spec.js:23:5 › Fake terminal — basic commands › uptime shows the load-average line (520ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:45] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:45] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:45] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:45] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:45] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:45] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:45] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:45] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 12 [chromium] › tests/e2e/02-terminal.spec.js:28:5 › Fake terminal — basic commands › ls lists the portfolio files (533ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:45] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:45] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:45] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:45] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:45] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:45] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:45] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:45] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 13 [chromium] › tests/e2e/02-terminal.spec.js:36:5 › Fake terminal — basic commands › pwd / whoami / hostname / id (565ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:46] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:46] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:46] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:46] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:46] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:46] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:46] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:46] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 14 [chromium] › tests/e2e/02-terminal.spec.js:47:5 › Fake terminal — basic commands › date shows a plausible current date (527ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:46] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:46] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:46] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:46] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:46] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:46] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:46] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:46] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 15 [chromium] › tests/e2e/02-terminal.spec.js:53:5 › Fake terminal — basic commands › uname and cat /etc/os-release (571ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:47] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:47] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:47] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:47] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:47] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:47] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:47] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:47] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 16 [chromium] › tests/e2e/02-terminal.spec.js:62:5 › Fake terminal — basic commands › echo prints its argument as plain text (512ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:47] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:47] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:47] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:47] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:47] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:47] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:47] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:47] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 17 [chromium] › tests/e2e/02-terminal.spec.js:67:5 › Fake terminal — basic commands › ss shows listening ports (514ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:48] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:48] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:48] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:48] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:48] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:48] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:48] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:48] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 18 [chromium] › tests/e2e/02-terminal.spec.js:74:5 › Fake terminal — basic commands › docker ps and podman ps (539ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:48] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:48] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:48] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:48] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:48] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:48] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:48] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:48] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 19 [chromium] › tests/e2e/02-terminal.spec.js:85:5 › Fake terminal — basic commands › ps aux and df -h and free -h (570ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:49] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:49] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:49] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:49] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:49] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:49] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:49] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:49] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 20 [chromium] › tests/e2e/02-terminal.spec.js:94:5 › Fake terminal — basic commands › neofetch renders the ASCII logo and colored blocks (552ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:50] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:50] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:50] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:50] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:50] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:50] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:50] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:50] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 21 [chromium] › tests/e2e/02-terminal.spec.js:102:5 › Fake terminal — basic commands › sl prints the locomotive (537ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:50] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:50] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:50] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:50] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:50] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:50] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:50] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:50] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 22 [chromium] › tests/e2e/02-terminal.spec.js:107:5 › Fake terminal — basic commands › help lists the available commands (522ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:51] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:51] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:51] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:51] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:51] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:51] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:51] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:51] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 23 [chromium] › tests/e2e/02-terminal.spec.js:115:5 › Fake terminal — basic commands › systemctl, ip addr, cat ssh key (590ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:51] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:51] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:51] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:51] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:51] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:51] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:51] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:51] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 24 [chromium] › tests/e2e/02-terminal.spec.js:124:5 › Fake terminal — basic commands › unknown command produces no output and a fresh prompt (527ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:52] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:52] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:52] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:52] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:52] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:52] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:52] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:52] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 25 [chromium] › tests/e2e/02-terminal.spec.js:139:5 › Fake terminal — state and special commands › history: ArrowUp/ArrowDown recall previous commands (560ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:52] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:52] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:52] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:52] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:52] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:52] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:52] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:52] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 26 [chromium] › tests/e2e/02-terminal.spec.js:156:5 › Fake terminal — state and special commands › history recall renders markup payloads as literal text (no DOM injection) (853ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:53] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:53] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:53] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:53] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:53] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:53] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:53] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:53] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 27 [chromium] › tests/e2e/02-terminal.spec.js:195:5 › Fake terminal — state and special commands › Tab completes a command (590ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:54] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:54] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:54] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:54] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:54] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:54] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:54] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:54] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 28 [chromium] › tests/e2e/02-terminal.spec.js:203:5 › Fake terminal — state and special commands › Tab cycles between multiple matches (620ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:54] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:54] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:54] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:54] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:54] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:54] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:54] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:54] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 29 [chromium] › tests/e2e/02-terminal.spec.js:218:5 › Fake terminal — state and special commands › clear empties the terminal and leaves one prompt line (616ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:55] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:55] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:55] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:55] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:55] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:55] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:55] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:55] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 30 [chromium] › tests/e2e/02-terminal.spec.js:226:5 › Fake terminal — state and special commands › sudo su - switches the prompt to root (#) (609ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:56] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:56] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:56] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:56] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:56] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:56] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:56] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:56] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 31 [chromium] › tests/e2e/02-terminal.spec.js:239:5 › Fake terminal — state and special commands › rm -rf / as a normal user is refused (617ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:56] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:56] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:56] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:56] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:56] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:56] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:56] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:56] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 32 [chromium] › tests/e2e/02-terminal.spec.js:247:5 › Fake terminal — state and special commands › rm -rf / as root triggers the destruction easter egg (1.3s)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:58] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:58] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:58] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:58] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:58] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:58] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:58] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:58] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 33 [chromium] › tests/e2e/02-terminal.spec.js:257:5 › Fake terminal — state and special commands › exit as a normal user swaps the page for a login screen (592ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:58] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:58] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:58] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:58] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:58] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:58] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:58] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:05:58] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 34 [chromium] › tests/e2e/02-terminal.spec.js:273:5 › Fake terminal — state and special commands › curl/wget are simulated — no real network request leaves the origin (3.0s)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:01] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:01] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:01] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:01] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:01] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:01] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:01] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:01] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 35 [chromium] › tests/e2e/02-terminal.spec.js:303:5 › Fake terminal — state and special commands › backspace edits the current command (521ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:02] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:02] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:02] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:02] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:02] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:02] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:02] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:02] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 36 [chromium] › tests/e2e/03-vim.spec.js:15:5 › Fake terminal — vim simulator › vim with no filename shows the splash and q exits (601ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:02] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:02] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:02] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:02] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:02] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:02] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:02] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:02] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 37 [chromium] › tests/e2e/03-vim.spec.js:26:5 › Fake terminal — vim simulator › vim with a filename opens a buffer; insert, save & quit (592ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:03] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:03] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:03] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:03] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:03] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:03] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:03] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:03] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 38 [chromium] › tests/e2e/03-vim.spec.js:48:5 › Fake terminal — vim simulator › vim normal-mode navigation and line deletion (564ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:04] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:04] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:04] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:04] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:04] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:04] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:04] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:04] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 39 [chromium] › tests/e2e/04-achievements.spec.js:8:5 › Achievements system › starts hidden until the first unlock (451ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:04] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:04] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:04] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:04] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:04] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:04] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:04] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:04] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 40 [chromium] › tests/e2e/04-achievements.spec.js:14:5 › Achievements system › uptime unlock shows a toast, persists to localStorage, reveals the section (544ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:05] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:05] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:05] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:05] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:05] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:05] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:05] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:05] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:05] "GET / HTTP/1.1" 304 -
✓ 41 [chromium] › tests/e2e/04-achievements.spec.js:43:5 › Achievements system › unlocks survive a page reload (localStorage restore) (593ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:05] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:05] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:05] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:05] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:05] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:05] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:05] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:05] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:06] "GET / HTTP/1.1" 304 -
✓ 42 [chromium] › tests/e2e/04-achievements.spec.js:55:5 › Achievements system › special achievements: sudo, nice-try rm, vim splash (692ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:06] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:06] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:06] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:06] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:06] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:06] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:06] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:06] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 43 [chromium] › tests/e2e/04-achievements.spec.js:80:5 › Achievements system › multiple unlocks stack toasts and increment the counter (634ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:07] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:07] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:07] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:07] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:07] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:07] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:07] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:07] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 44 [chromium] › tests/e2e/05-menu.spec.js:5:5 › Navigation menu › desktop: inline nav visible, hamburger hidden (517ms)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:07] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:07] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:07] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:07] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:07] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:07] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:07] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:07] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 45 [chromium] › tests/e2e/05-menu.spec.js:12:5 › Navigation menu › mobile: hamburger opens and closes the menu (1.8s)
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:09] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:09] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:09] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:09] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:09] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:09] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:09] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [23/Oct/2026 00:06:09] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 46 [chromium] › tests/e2e/05-menu.spec.js:30:5 › Navigation menu › clicking outside closes an open mobile menu (568ms)
46 passed (31.2s)
To open last HTML report run:

 npx playwright show-report

>> building image (podman)...
time="2026-10-23T00:07:12-04:00" level=warning msg="HEALTHCHECK is not supported for OCI image format and will be ignored. Must use `docker` format"
aa4dc0bf3ca88d13f0427c0786e4fc36886cfce016b2af262a0c41d687d8d540
>> starting container on 127.0.0.1:18099...
>> checking headers...
OK: all security headers present on /
OK: all security headers present on /index.html
OK: all security headers present on /style.342793b0a19255e7ce615729a45053fe.css
HEADER CHECK PASSED
@@ -0,0 +1,18 @@
Task complete and fully green.
**Implemented**
- `nginx-security-headers.inc` (new, repo root): the four hardening headers as `add_header … always;` lines (X-Frame-Options, X-Content-Type-Options, Referrer-Policy, CSP).
- `nginx.conf`: removed all inline security `add_header` lines from the `server` block; added `server_tokens off;`; all three locations (`= /index.html`, hashed-asset regex, `/`) now `include /etc/nginx/snippets/security-headers.inc;` — fixes the `add_header` inheritance trap (M-4) and L-2.
- `Dockerfile`: `mkdir -p /etc/nginx/snippets` in the existing `RUN`, plus `COPY nginx-security-headers.inc /etc/nginx/snippets/security-headers.inc` before the `nginx.conf` COPY.
- Docs: README "Serving & configuration" rewritten (stale "Known gap M-4" paragraph replaced with the snippet mechanism + rule for new locations); AGENTS.md gained a convention banning inline security `add_header` in `nginx.conf`.
**Verification**
- `nginx -t` in `nginx:alpine` with both files bind-mounted: "syntax is ok / test is successful".
- Ad-hoc container proof (`podman build` → run on 127.0.0.1:18099 → `curl -sI`, container + image removed afterwards): all four headers present on `/`, `/index.html` and `style.<hash>.css` with their correct `Cache-Control`, and `Server: nginx` (version hidden). Not committed as a script — `scripts/check-headers.sh` is task 02's deliverable.
- `./build.sh && npm test` → **46 passed**; `bash .agents/validate.sh` → **exit 0** (46/46 + repo-hygiene gates). Coverage criterion (>90% of modified config) is met by exercising all three location paths above; formal coverage gate lands with task 02's script.
**Decisions / deviations**
- Made no live-infrastructure changes: no deploy, no edge/Caddy touch, no HSTS inside the 8080 container (locked). Only ephemeral local podman builds/runs on a scratch port, cleaned up.
- Kept `Cache-Control`/`Pragma`/`Expires` inline in their locations (cache policy is per-location; only security headers are shared).
**Next pending task:** `.agents/phases/todo/03_nginx_security_headers/02_add_header_verification.md` (`scripts/check-headers.sh`).
@@ -0,0 +1,428 @@
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:32] "GET /index.html HTTP/1.1" 200 -
Running 46 tests using 1 worker
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:33] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:33] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:33] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:33] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:33] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:33] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:33] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:33] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 1 [chromium] › tests/e2e/01-page.spec.js:9:5 › Page structure › loads with correct title and lang (597ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:33] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:33] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:33] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:33] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:33] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:33] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:33] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:33] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 2 [chromium] › tests/e2e/01-page.spec.js:14:5 › Page structure › nav has all seven section links pointing at existing targets (536ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:34] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:34] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:34] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:34] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:34] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:34] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:34] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:34] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 3 [chromium] › tests/e2e/01-page.spec.js:24:5 › Page structure › all major sections exist and are in the DOM (512ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:35] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:35] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:35] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:35] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:35] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:35] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:35] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:35] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 4 [chromium] › tests/e2e/01-page.spec.js:30:5 › Page structure › profile image loads (531ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:35] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:35] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:35] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:35] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:35] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:35] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:35] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:35] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 5 [chromium] › tests/e2e/01-page.spec.js:38:5 › Page structure › server rack background is generated with a terminal unit (509ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:36] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:36] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:36] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:36] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:36] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:36] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:36] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:36] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 6 [chromium] › tests/e2e/01-page.spec.js:45:5 › Page structure › GPG section shows both fingerprints and key blocks (537ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:36] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:36] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:36] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:36] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:36] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:36] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:36] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:36] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 7 [chromium] › tests/e2e/01-page.spec.js:59:5 › Page structure › external links all carry rel="noopener" (532ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:37] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:37] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:37] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:37] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:37] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:37] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:37] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:37] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:37] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
✓ 8 [chromium] › tests/e2e/01-page.spec.js:68:5 › Page structure › hashed assets are referenced and served (537ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:37] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:37] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:37] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:37] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:37] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:37] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:37] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:37] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 9 [chromium] › tests/e2e/02-terminal.spec.js:11:5 › Fake terminal — basic commands › hero click expands the terminal and shifts the hero (562ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:38] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:38] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:38] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:38] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:38] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:38] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:38] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:38] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 10 [chromium] › tests/e2e/02-terminal.spec.js:17:5 › Fake terminal — basic commands › initial boot lines are rendered (612ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:38] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:38] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:38] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:38] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:38] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:38] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:38] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:38] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 11 [chromium] › tests/e2e/02-terminal.spec.js:23:5 › Fake terminal — basic commands › uptime shows the load-average line (611ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:39] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:39] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:39] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:39] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:39] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:39] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:39] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:39] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 12 [chromium] › tests/e2e/02-terminal.spec.js:28:5 › Fake terminal — basic commands › ls lists the portfolio files (584ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:40] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:40] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:40] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:40] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:40] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:40] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:40] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:40] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 13 [chromium] › tests/e2e/02-terminal.spec.js:36:5 › Fake terminal — basic commands › pwd / whoami / hostname / id (670ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:40] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:40] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:40] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:40] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:40] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:40] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:40] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:40] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 14 [chromium] › tests/e2e/02-terminal.spec.js:47:5 › Fake terminal — basic commands › date shows a plausible current date (584ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:41] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:41] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:41] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:41] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:41] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:41] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:41] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:41] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 15 [chromium] › tests/e2e/02-terminal.spec.js:53:5 › Fake terminal — basic commands › uname and cat /etc/os-release (651ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:42] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:42] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:42] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:42] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:42] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:42] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:42] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:42] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 16 [chromium] › tests/e2e/02-terminal.spec.js:62:5 › Fake terminal — basic commands › echo prints its argument as plain text (595ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:42] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:42] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:42] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:42] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:42] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:42] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:42] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:42] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 17 [chromium] › tests/e2e/02-terminal.spec.js:67:5 › Fake terminal — basic commands › ss shows listening ports (579ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:43] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:43] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:43] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:43] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:43] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:43] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:43] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:43] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 18 [chromium] › tests/e2e/02-terminal.spec.js:74:5 › Fake terminal — basic commands › docker ps and podman ps (622ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:43] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:43] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:43] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:43] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:43] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:43] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:43] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:43] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 19 [chromium] › tests/e2e/02-terminal.spec.js:85:5 › Fake terminal — basic commands › ps aux and df -h and free -h (636ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:44] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:44] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:44] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:44] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:44] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:44] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:44] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:44] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 20 [chromium] › tests/e2e/02-terminal.spec.js:94:5 › Fake terminal — basic commands › neofetch renders the ASCII logo and colored blocks (597ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:45] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:45] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:45] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:45] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:45] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:45] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:45] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:45] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 21 [chromium] › tests/e2e/02-terminal.spec.js:102:5 › Fake terminal — basic commands › sl prints the locomotive (541ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:45] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:45] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:45] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:45] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:45] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:45] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:45] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:45] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 22 [chromium] › tests/e2e/02-terminal.spec.js:107:5 › Fake terminal — basic commands › help lists the available commands (555ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:46] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:46] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:46] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:46] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:46] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:46] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:46] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:46] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 23 [chromium] › tests/e2e/02-terminal.spec.js:115:5 › Fake terminal — basic commands › systemctl, ip addr, cat ssh key (581ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:46] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:46] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:46] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:46] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:46] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:46] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:46] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:46] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 24 [chromium] › tests/e2e/02-terminal.spec.js:124:5 › Fake terminal — basic commands › unknown command produces no output and a fresh prompt (572ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:47] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:47] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:47] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:47] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:47] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:47] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:47] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:47] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 25 [chromium] › tests/e2e/02-terminal.spec.js:139:5 › Fake terminal — state and special commands › history: ArrowUp/ArrowDown recall previous commands (652ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:48] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:48] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:48] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:48] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:48] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:48] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:48] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:48] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 26 [chromium] › tests/e2e/02-terminal.spec.js:156:5 › Fake terminal — state and special commands › history recall renders markup payloads as literal text (no DOM injection) (939ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:48] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:48] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:48] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:48] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:48] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:48] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:48] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:48] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 27 [chromium] › tests/e2e/02-terminal.spec.js:195:5 › Fake terminal — state and special commands › Tab completes a command (594ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:49] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:49] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:49] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:49] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:49] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:49] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:49] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:49] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 28 [chromium] › tests/e2e/02-terminal.spec.js:203:5 › Fake terminal — state and special commands › Tab cycles between multiple matches (567ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:50] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:50] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:50] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:50] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:50] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:50] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:50] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:50] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 29 [chromium] › tests/e2e/02-terminal.spec.js:218:5 › Fake terminal — state and special commands › clear empties the terminal and leaves one prompt line (544ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:50] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:50] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:50] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:50] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:50] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:50] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:50] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:50] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 30 [chromium] › tests/e2e/02-terminal.spec.js:226:5 › Fake terminal — state and special commands › sudo su - switches the prompt to root (#) (577ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:51] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:51] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:51] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:51] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:51] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:51] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:51] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:51] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 31 [chromium] › tests/e2e/02-terminal.spec.js:239:5 › Fake terminal — state and special commands › rm -rf / as a normal user is refused (544ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:51] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:51] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:51] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:51] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:51] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:51] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:51] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:51] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 32 [chromium] › tests/e2e/02-terminal.spec.js:247:5 › Fake terminal — state and special commands › rm -rf / as root triggers the destruction easter egg (1.3s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:53] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:53] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:53] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:53] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:53] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:53] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:53] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:53] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 33 [chromium] › tests/e2e/02-terminal.spec.js:257:5 › Fake terminal — state and special commands › exit as a normal user swaps the page for a login screen (565ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:53] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:53] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:53] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:53] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:53] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:53] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:53] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:53] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 34 [chromium] › tests/e2e/02-terminal.spec.js:273:5 › Fake terminal — state and special commands › curl/wget are simulated — no real network request leaves the origin (3.0s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:56] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:56] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:56] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:56] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:56] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:56] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:56] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:56] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 35 [chromium] › tests/e2e/02-terminal.spec.js:303:5 › Fake terminal — state and special commands › backspace edits the current command (522ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:57] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:57] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:57] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:57] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:57] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:57] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:57] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:57] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 36 [chromium] › tests/e2e/03-vim.spec.js:15:5 › Fake terminal — vim simulator › vim with no filename shows the splash and q exits (596ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:57] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:57] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:57] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:57] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:57] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:57] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:57] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:57] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 37 [chromium] › tests/e2e/03-vim.spec.js:26:5 › Fake terminal — vim simulator › vim with a filename opens a buffer; insert, save & quit (649ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:58] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:58] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:58] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:58] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:58] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:58] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:58] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:58] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 38 [chromium] › tests/e2e/03-vim.spec.js:48:5 › Fake terminal — vim simulator › vim normal-mode navigation and line deletion (645ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:59] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:59] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:59] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:59] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:59] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:59] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:59] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:59] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 39 [chromium] › tests/e2e/04-achievements.spec.js:8:5 › Achievements system › starts hidden until the first unlock (484ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:59] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:59] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:59] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:59] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:59] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:59] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:59] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:24:59] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 40 [chromium] › tests/e2e/04-achievements.spec.js:14:5 › Achievements system › uptime unlock shows a toast, persists to localStorage, reveals the section (573ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:00] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:00] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:00] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:00] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:00] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:00] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:00] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:00] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:00] "GET / HTTP/1.1" 304 -
✓ 41 [chromium] › tests/e2e/04-achievements.spec.js:43:5 › Achievements system › unlocks survive a page reload (localStorage restore) (652ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:00] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:00] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:00] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:00] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:00] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:00] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:00] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:00] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:01] "GET / HTTP/1.1" 304 -
✓ 42 [chromium] › tests/e2e/04-achievements.spec.js:55:5 › Achievements system › special achievements: sudo, nice-try rm, vim splash (786ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:01] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:01] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:01] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:01] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:01] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:01] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:01] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:01] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 43 [chromium] › tests/e2e/04-achievements.spec.js:80:5 › Achievements system › multiple unlocks stack toasts and increment the counter (620ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:02] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:02] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:02] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:02] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:02] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:02] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:02] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:02] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 44 [chromium] › tests/e2e/05-menu.spec.js:5:5 › Navigation menu › desktop: inline nav visible, hamburger hidden (518ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:02] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:02] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:02] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:02] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:02] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:02] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:02] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:02] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 45 [chromium] › tests/e2e/05-menu.spec.js:12:5 › Navigation menu › mobile: hamburger opens and closes the menu (1.8s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:04] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:04] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:04] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:04] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:04] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:04] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:04] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:25:04] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 46 [chromium] › tests/e2e/05-menu.spec.js:30:5 › Navigation menu › clicking outside closes an open mobile menu (553ms)
46 passed (32.4s)
To open last HTML report run:

 npx playwright show-report

@@ -0,0 +1,18 @@
**Implemented**
- `scripts/check-headers.sh` (new, mode 755) — builds the real nginx image with podman/docker, serves it on `127.0.0.1:18099`, asserts all four hardening headers on `/`, `/index.html` and the first hashed asset; content is byte-identical to the task spec.
- `.agents/validate.sh` — added the Phase 03 gate call to `./scripts/check-headers.sh` (per PLAN §5.3), plus cleanup of the leftover `homepage-headercheck-*` image tag, and a loud `WARN:` skip on hosts with no container runtime.
**Verification**
- `./scripts/check-headers.sh` → exit 0: `OK: all security headers present on /`, `/index.html`, `/style.342793b0….css`, then `HEADER CHECK PASSED`.
- Negative check (teeth): removed the snippet `include` from the hashed-asset location → script exited 1 with four `FAIL: <header> missing on /style.…css`; restored and confirmed `sha256sum -c nginx.conf: OK` + `diff` clean.
- Manual container dump: 4 headers present on `/`, `/index.html`, hashed asset and the SPA-fallback path; `Server: nginx` (L-2 holds); per-location `Cache-Control` unchanged. Config coverage = 3/3 locations exercised (100% > 90%).
- `./build.sh && npm test` → **46 passed**. `bash .agents/validate.sh` → **exit 0** (46 E2E + header check + repo-hygiene gates). No container/image or port leftovers.
**Docs**
- `README.md`: new “Verify the headers” subsection (what the script does, scratch port 18099, `HEADER CHECK PASSED`, no local build needed, runtime requirement) and updated the validation-gate paragraph.
- `AGENTS.md`: gate description now includes the container header check; nginx-header convention notes `check-headers.sh` is the regression guard for the per-location `include` rule.
**Notes / deviations**
- Kept the script exactly as specified: because of `set -e` it aborts at the first failing path, so the `HEADER CHECK FAILED` summary line is unreachable (exit code and `FAIL:` lines are still correct). Documented in README rather than editing spec'd content.
- No live-infra changes (no deploy, no Caddy edge, no HSTS in the 8080 container); only ephemeral local podman builds/runs, all cleaned up. CI (`.gitea/workflows/build-push.yml`) still has no test/header step — that's unphased PLAN item L-8, left untouched.
- Next pending task: `.agents/phases/todo/04_huntington_role/01_add_timeline_entry.md` (phase 03 task list is exhausted; harness can run `00_phase.md` final pass / move this task to complete).
@@ -0,0 +1,437 @@
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:53] "GET /index.html HTTP/1.1" 200 -
Running 46 tests using 1 worker
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:53] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:53] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:53] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:53] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:53] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:53] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:53] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:53] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 1 [chromium] › tests/e2e/01-page.spec.js:9:5 › Page structure › loads with correct title and lang (581ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:54] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:54] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:54] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:54] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:54] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:54] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:54] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:54] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 2 [chromium] › tests/e2e/01-page.spec.js:14:5 › Page structure › nav has all seven section links pointing at existing targets (547ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:54] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:54] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:54] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:54] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:54] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:54] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:54] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:54] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 3 [chromium] › tests/e2e/01-page.spec.js:24:5 › Page structure › all major sections exist and are in the DOM (470ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:55] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:55] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:55] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:55] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:55] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:55] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:55] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:55] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 4 [chromium] › tests/e2e/01-page.spec.js:30:5 › Page structure › profile image loads (486ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:55] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:55] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:55] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:55] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:55] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:55] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:55] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:55] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 5 [chromium] › tests/e2e/01-page.spec.js:38:5 › Page structure › server rack background is generated with a terminal unit (468ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:56] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:56] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:56] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:56] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:56] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:56] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:56] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:56] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 6 [chromium] › tests/e2e/01-page.spec.js:45:5 › Page structure › GPG section shows both fingerprints and key blocks (480ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:56] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:56] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:56] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:56] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:56] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:56] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:56] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:56] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 7 [chromium] › tests/e2e/01-page.spec.js:59:5 › Page structure › external links all carry rel="noopener" (497ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:57] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:57] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:57] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:57] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:57] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:57] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:57] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:57] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:57] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
✓ 8 [chromium] › tests/e2e/01-page.spec.js:68:5 › Page structure › hashed assets are referenced and served (480ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:57] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:57] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:57] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:57] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:57] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:57] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:57] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:57] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 9 [chromium] › tests/e2e/02-terminal.spec.js:11:5 › Fake terminal — basic commands › hero click expands the terminal and shifts the hero (549ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:58] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:58] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:58] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:58] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:58] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:58] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:58] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:58] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 10 [chromium] › tests/e2e/02-terminal.spec.js:17:5 › Fake terminal — basic commands › initial boot lines are rendered (545ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:58] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:58] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:58] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:58] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:58] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:58] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:58] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:58] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 11 [chromium] › tests/e2e/02-terminal.spec.js:23:5 › Fake terminal — basic commands › uptime shows the load-average line (554ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:59] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:59] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:59] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:59] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:59] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:59] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:59] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:59] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 12 [chromium] › tests/e2e/02-terminal.spec.js:28:5 › Fake terminal — basic commands › ls lists the portfolio files (563ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:59] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:59] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:59] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:59] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:59] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:59] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:59] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:45:59] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 13 [chromium] › tests/e2e/02-terminal.spec.js:36:5 › Fake terminal — basic commands › pwd / whoami / hostname / id (656ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:00] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:00] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:00] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:00] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:00] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:00] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:00] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:00] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 14 [chromium] › tests/e2e/02-terminal.spec.js:47:5 › Fake terminal — basic commands › date shows a plausible current date (577ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:01] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:01] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:01] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:01] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:01] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:01] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:01] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:01] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 15 [chromium] › tests/e2e/02-terminal.spec.js:53:5 › Fake terminal — basic commands › uname and cat /etc/os-release (589ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:01] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:01] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:01] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:01] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:01] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:01] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:01] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:01] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 16 [chromium] › tests/e2e/02-terminal.spec.js:62:5 › Fake terminal — basic commands › echo prints its argument as plain text (571ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:02] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:02] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:02] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:02] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:02] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:02] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:02] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:02] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 17 [chromium] › tests/e2e/02-terminal.spec.js:67:5 › Fake terminal — basic commands › ss shows listening ports (602ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:02] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:02] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:02] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:02] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:02] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:02] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:02] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:02] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 18 [chromium] › tests/e2e/02-terminal.spec.js:74:5 › Fake terminal — basic commands › docker ps and podman ps (607ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:03] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:03] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:03] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:03] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:03] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:03] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:03] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:03] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 19 [chromium] › tests/e2e/02-terminal.spec.js:85:5 › Fake terminal — basic commands › ps aux and df -h and free -h (628ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:04] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:04] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:04] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:04] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:04] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:04] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:04] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:04] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 20 [chromium] › tests/e2e/02-terminal.spec.js:94:5 › Fake terminal — basic commands › neofetch renders the ASCII logo and colored blocks (566ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:04] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:04] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:04] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:04] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:04] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:04] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:04] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:04] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 21 [chromium] › tests/e2e/02-terminal.spec.js:102:5 › Fake terminal — basic commands › sl prints the locomotive (542ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:05] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:05] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:05] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:05] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:05] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:05] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:05] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:05] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 22 [chromium] › tests/e2e/02-terminal.spec.js:107:5 › Fake terminal — basic commands › help lists the available commands (522ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:05] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:05] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:05] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:05] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:05] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:05] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:05] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:05] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 23 [chromium] › tests/e2e/02-terminal.spec.js:115:5 › Fake terminal — basic commands › systemctl, ip addr, cat ssh key (596ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:06] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:06] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:06] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:06] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:06] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:06] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:06] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:06] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 24 [chromium] › tests/e2e/02-terminal.spec.js:124:5 › Fake terminal — basic commands › unknown command produces no output and a fresh prompt (527ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:06] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:06] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:06] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:06] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:06] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:06] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:06] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:06] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 25 [chromium] › tests/e2e/02-terminal.spec.js:139:5 › Fake terminal — state and special commands › history: ArrowUp/ArrowDown recall previous commands (583ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:07] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:07] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:07] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:07] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:07] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:07] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:07] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:07] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 26 [chromium] › tests/e2e/02-terminal.spec.js:156:5 › Fake terminal — state and special commands › history recall renders markup payloads as literal text (no DOM injection) (859ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:08] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:08] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:08] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:08] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:08] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:08] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:08] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:08] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 27 [chromium] › tests/e2e/02-terminal.spec.js:195:5 › Fake terminal — state and special commands › Tab completes a command (529ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:08] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:08] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:08] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:08] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:08] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:08] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:08] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:08] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 28 [chromium] › tests/e2e/02-terminal.spec.js:203:5 › Fake terminal — state and special commands › Tab cycles between multiple matches (544ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:09] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:09] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:09] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:09] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:09] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:09] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:09] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:09] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 29 [chromium] › tests/e2e/02-terminal.spec.js:218:5 › Fake terminal — state and special commands › clear empties the terminal and leaves one prompt line (562ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:10] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:10] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:10] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:10] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:10] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:10] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:10] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:10] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 30 [chromium] › tests/e2e/02-terminal.spec.js:226:5 › Fake terminal — state and special commands › sudo su - switches the prompt to root (#) (581ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:10] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:10] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:10] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:10] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:10] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:10] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:10] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:10] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 31 [chromium] › tests/e2e/02-terminal.spec.js:239:5 › Fake terminal — state and special commands › rm -rf / as a normal user is refused (535ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:11] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:11] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:11] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:11] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:11] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:11] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:11] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:11] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 32 [chromium] › tests/e2e/02-terminal.spec.js:247:5 › Fake terminal — state and special commands › rm -rf / as root triggers the destruction easter egg (1.2s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:12] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:12] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:12] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:12] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:12] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:12] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:12] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:12] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 33 [chromium] › tests/e2e/02-terminal.spec.js:257:5 › Fake terminal — state and special commands › exit as a normal user swaps the page for a login screen (552ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:12] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:12] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:12] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:12] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:12] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:12] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:12] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:12] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 34 [chromium] › tests/e2e/02-terminal.spec.js:273:5 › Fake terminal — state and special commands › curl/wget are simulated — no real network request leaves the origin (3.1s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:16] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:16] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:16] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:16] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:16] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:16] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:16] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:16] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 35 [chromium] › tests/e2e/02-terminal.spec.js:303:5 › Fake terminal — state and special commands › backspace edits the current command (557ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:16] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:16] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:16] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:16] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:16] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:16] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:16] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:16] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 36 [chromium] › tests/e2e/03-vim.spec.js:15:5 › Fake terminal — vim simulator › vim with no filename shows the splash and q exits (579ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:17] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:17] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:17] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:17] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:17] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:17] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:17] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:17] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 37 [chromium] › tests/e2e/03-vim.spec.js:26:5 › Fake terminal — vim simulator › vim with a filename opens a buffer; insert, save & quit (572ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:17] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:17] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:17] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:17] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:17] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:17] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:17] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:17] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 38 [chromium] › tests/e2e/03-vim.spec.js:48:5 › Fake terminal — vim simulator › vim normal-mode navigation and line deletion (618ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:18] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:18] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:18] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:18] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:18] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:18] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:18] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:18] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 39 [chromium] › tests/e2e/04-achievements.spec.js:8:5 › Achievements system › starts hidden until the first unlock (452ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:18] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:18] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:18] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:18] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:18] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:18] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:18] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:18] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 40 [chromium] › tests/e2e/04-achievements.spec.js:14:5 › Achievements system › uptime unlock shows a toast, persists to localStorage, reveals the section (548ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:19] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:19] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:19] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:19] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:19] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:19] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:19] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:19] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:19] "GET / HTTP/1.1" 304 -
✓ 41 [chromium] › tests/e2e/04-achievements.spec.js:43:5 › Achievements system › unlocks survive a page reload (localStorage restore) (559ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:20] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:20] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:20] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:20] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:20] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:20] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:20] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:20] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:20] "GET / HTTP/1.1" 304 -
✓ 42 [chromium] › tests/e2e/04-achievements.spec.js:55:5 › Achievements system › special achievements: sudo, nice-try rm, vim splash (688ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:20] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:20] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:20] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:20] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:20] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:20] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:20] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:20] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 43 [chromium] › tests/e2e/04-achievements.spec.js:80:5 › Achievements system › multiple unlocks stack toasts and increment the counter (564ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:21] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:21] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:21] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:21] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:21] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:21] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:21] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:21] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 44 [chromium] › tests/e2e/05-menu.spec.js:5:5 › Navigation menu › desktop: inline nav visible, hamburger hidden (471ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:21] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:21] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:21] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:21] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:21] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:21] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:21] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:21] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 45 [chromium] › tests/e2e/05-menu.spec.js:12:5 › Navigation menu › mobile: hamburger opens and closes the menu (2.3s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:24] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:24] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:24] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:24] "GET /terminal-commands.b11ee656c4a1c395dae70c8ccde84707.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:24] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:24] "GET /terminal.ec0e2ff734985cc54efeb2a46a3f262b.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:24] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 23:46:24] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 46 [chromium] › tests/e2e/05-menu.spec.js:30:5 › Navigation menu › clicking outside closes an open mobile menu (650ms)
46 passed (31.6s)
To open last HTML report run:

 npx playwright show-report

>> building image (podman)...
time="2026-10-22T23:47:26-04:00" level=warning msg="HEALTHCHECK is not supported for OCI image format and will be ignored. Must use `docker` format"
83faed371f8dded42ad3456a28cff69d4f72c0f23c7b29ca83e288c2eba77ea8
>> starting container on 127.0.0.1:18099...
>> checking headers...
OK: all security headers present on /
OK: all security headers present on /index.html
OK: all security headers present on /style.342793b0a19255e7ce615729a45053fe.css
HEADER CHECK PASSED
+3 -1
View File
@@ -1,8 +1,10 @@
FROM docker.io/library/nginx:alpine
RUN rm /etc/nginx/conf.d/default.conf && \
apk add --no-cache coreutils
apk add --no-cache coreutils && \
mkdir -p /etc/nginx/snippets
COPY nginx-security-headers.inc /etc/nginx/snippets/security-headers.inc
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY src/ /src/
+34 -10
View File
@@ -34,21 +34,42 @@ Visit `http://localhost:8080` in your browser.
## Serving & configuration
`nginx.conf` is copied into the image as the site config. It listens on
**8080 over plain HTTP**, serves the hashed build, declares the hardening
headers (`X-Frame-Options`, `X-Content-Type-Options`, `Referrer-Policy`,
`Content-Security-Policy`), serves `index.html` with `no-cache`, and caches the
hashed assets as `immutable` for a year.
**8080 over plain HTTP**, serves the hashed build, serves `index.html` with
`no-cache`, and caches the hashed assets as `immutable` for a year.
Known gap (audit finding M-4, Phase 03): nginx does not merge `add_header`
across configuration levels, so the `location` blocks that set their own headers
drop the server-level security headers — measured against the built image, `/`,
`/index.html` and a hashed asset currently get only the cache headers. Every
`add_header` block must repeat the hardening headers until that phase lands.
The four hardening headers (`X-Frame-Options`, `X-Content-Type-Options`,
`Referrer-Policy`, `Content-Security-Policy`) live in
`nginx-security-headers.inc`, which the Dockerfile copies to
`/etc/nginx/snippets/security-headers.inc`. nginx does **not** merge
`add_header` across configuration levels, so every `location` block `include`s
that snippet instead of inheriting from the `server` block — otherwise the
locations that set their own cache headers would silently drop the security
headers (audit finding M-4, Phase 03). `server_tokens off;` hides the nginx
version from the `Server` header (audit finding L-2). When adding a new
`location`, `include` the snippet there too and keep the security headers out of
`nginx.conf` itself.
TLS and HSTS are the job of the reverse proxy in front of the container
(`reeseapps.com` terminates at the Caddy edge). Do **not** add
`Strict-Transport-Security` or a `listen 443` block to `nginx.conf`.
### Verify the headers
```bash
./scripts/check-headers.sh
```
This is the integration test for the header fix: it builds the **real** image
with podman (or docker), runs it on the scratch address `127.0.0.1:18099`, and
asserts all four security headers on each response class — `/`, `/index.html`
and the first hashed asset found in `index.html`. On success it prints one
`OK:` line per path and `HEADER CHECK PASSED` (exit 0); a missing header prints
`FAIL: <header> missing on <path>` and exits non-zero, aborting at the first
failing path. No local `./build.sh` is needed — the image builds itself. The
container is removed by the script; `.agents/validate.sh` removes the leftover
`homepage-headercheck-*` image tag. Run it after **any** change to
`nginx.conf`, `nginx-security-headers.inc` or the `Dockerfile`.
## Deploy with Quadlet
The `homepage.container` Quadlet unit is **not** tracked in this repository — it
@@ -115,4 +136,7 @@ revision cached for the pinned Playwright version — run
bumping the pin.
The validation gate the phased pipeline runs per task is `.agents/validate.sh`
(full E2E suite plus repo-hygiene checks): `bash .agents/validate.sh`.
(full E2E suite, the container security-header check from
`scripts/check-headers.sh`, plus repo-hygiene checks): `bash
.agents/validate.sh`. The header check is skipped with a loud `WARN:` line on a
host with no container runtime; everything else still runs.
+7
View File
@@ -0,0 +1,7 @@
# Shared security headers — included by EVERY nginx location.
# A location that defines its own add_header inherits none from the
# server block, so each location includes this snippet directly.
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';" always;
+5 -5
View File
@@ -5,11 +5,8 @@ server {
root /usr/share/nginx/html;
index index.html;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';" always;
# Hide the nginx version in the Server header (audit L-2)
server_tokens off;
# Gzip compression
gzip on;
@@ -19,6 +16,7 @@ server {
# Never cache index.html so the latest HTML is always served
location = /index.html {
include /etc/nginx/snippets/security-headers.inc;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
@@ -27,11 +25,13 @@ server {
# Cache hashed assets forever (filename contains content hash)
location ~* \.(css|js|jpeg|jpg|png|gif|ico|svg|woff2?)$ {
include /etc/nginx/snippets/security-headers.inc;
add_header Cache-Control "public, max-age=31536000, immutable";
try_files $uri =404;
}
location / {
include /etc/nginx/snippets/security-headers.inc;
try_files $uri $uri/ /index.html;
}
+53
View File
@@ -0,0 +1,53 @@
#!/usr/bin/env bash
set -euo pipefail
# Verify every response class (/, /index.html, a hashed asset) carries the
# full security-header set, using the REAL nginx image on a scratch port.
# Requires a container runtime (podman or docker).
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT"
if command -v podman >/dev/null 2>&1; then RUNTIME=podman
elif command -v docker >/dev/null 2>&1; then RUNTIME=docker
else echo "ERROR: neither podman nor docker found" >&2; exit 2; fi
IMAGE="homepage-headercheck-$$"
PORT=18099
CID=""
trap 'if [ -n "$CID" ]; then $RUNTIME rm -f "$CID" >/dev/null 2>&1 || true; fi' EXIT
echo ">> building image ($RUNTIME)..."
$RUNTIME build -q -t "$IMAGE" .
echo ">> starting container on 127.0.0.1:$PORT..."
CID="$($RUNTIME run -d --rm -p 127.0.0.1:$PORT:8080 "$IMAGE")"
for i in $(seq 1 30); do
curl -sf -o /dev/null "http://127.0.0.1:$PORT/" && break
sleep 0.5
if [ "$i" -eq 30 ]; then echo "ERROR: container not ready" >&2; exit 1; fi
done
ASSET="$(curl -s "http://127.0.0.1:$PORT/" \
| grep -oE '(style|script|terminal)[a-z-]*\.[0-9a-f]{32}\.(css|js)' | head -n1 || true)"
if [ -z "$ASSET" ]; then echo "ERROR: no hashed asset found in index.html" >&2; exit 1; fi
fail=0
check_headers() {
local path="$1" hdrs h
hdrs="$(curl -sI "http://127.0.0.1:$PORT$path")"
for h in "X-Frame-Options" "X-Content-Type-Options" "Referrer-Policy" "Content-Security-Policy"; do
if ! printf '%s' "$hdrs" | grep -qi "^${h}:"; then
echo "FAIL: ${h} missing on ${path}" >&2; fail=1
fi
done
[ "$fail" -eq 0 ] && echo "OK: all security headers present on ${path}"
}
echo ">> checking headers..."
check_headers "/"
check_headers "/index.html"
check_headers "/${ASSET}"
if [ "$fail" -ne 0 ]; then echo "HEADER CHECK FAILED" >&2; exit 1; fi
echo "HEADER CHECK PASSED"