| 64 | |
64 | |
| 65 | ## Production deployment verification (filled in Phase 6) |
65 | ## Production deployment verification (filled in Phase 6) |
| 66 | See the bottom of this file. |
66 | See the bottom of this file. |
| |
67 | + |
| |
68 | +--- |
| |
69 | + |
| |
70 | +## Production deployment verification — 2026-11-02 (Phase 6) |
| |
71 | +| Check | Result | |
| |
72 | +|---|---| |
| |
73 | +| DNS | `tools.spboucher.ai` → 51.161.112.61 (BHS64), pre-existing GoDaddy A record, no change made | |
| |
74 | +| TLS | Let's Encrypt (issuer YE1), CN=tools.spboucher.ai, valid 2026-11-02 → 2027-01-31, issued automatically by Caddy at route creation | |
| |
75 | +| Route | `mld tunnel status`: `tools.spboucher.ai → 10.67.0.20:8540 (M2M32c)`; HTTP → HTTPS 308 | |
| |
76 | +| Registry | `mld status --live`: `tools-spboucher-ai M2M32c OK local 200 / public 200` | |
| |
77 | +| Deploy | `mld deploy tools-spboucher-ai --node M2M32c` 13:22:05–13:23:02 ET: sync, `pnpm install --frozen-lockfile`, migrations (3), content import (353 published), owner bootstrap, `next build` (353 SSG tool pages), PM2 `tools-web` + `tools-worker` online, local 200, public 200 | |
| |
78 | +| Public routes (HTTPS, curl) | `/`, `/tools`, `/tools?q=latex`, filtered directory, `/tools/duckdb`, `/tools/claude-code`, `/categories`, `/categories/hf-finance-research`, `/collections/high-frequency-finance-research`, `/compare?tools=…`, `/about`, `/robots.txt`, `/sitemap.xml`, `/api/health`, `/api/suggest` → all **200**, 50–410 ms including TLS from the laptop | |
| |
79 | +| Private isolation | `/admin` → 307 to `/login`; `/api/admin/stats` → 401; owner login returns `next: change_password` and `/admin` redirects to the forced password change; wrong password → 401 | |
| |
80 | +| Security headers | CSP, HSTS (2 y, includeSubDomains), X-Frame-Options DENY, nosniff, Referrer-Policy present; no `Server`/`X-Powered-By` leakage from the app | |
| |
81 | +| Security audit (live) | `E2E_BASE_URL=https://tools.spboucher.ai pnpm test:security` → **44/44 passed** | |
| |
82 | +| E2E public (live) | `pnpm exec playwright test tests/e2e/public.spec.ts` desktop + iPhone → **20/20 passed** | |
| |
83 | +| Accessibility (live) | `pnpm test:a11y` → **0 serious/critical** on 20 page/device combinations | |
| |
84 | +| Mobile layout | iPhone 15 (dark) screenshots of `/tools/claude-code` and the directory reviewed: header, search, breadcrumb, badges and CTA render correctly | |
| |
85 | +| Data | production DB: 353 public published, 92 deep, 6 private, 54 owner notes, 7 collections; owner `spbou4@icloud.com` created with `must_change_password = true`, TOTP off until the owner enrols | |
| |
86 | +| Backup | first encrypted backup `tools-2026-11-02T18-25-35.dump.enc` (1.3 MB) written to `M2M32c:~/backups/tools-spboucher-ai/` and rsynced to `M3U96b:~/backups/tools-spboucher-ai/` over the LAN; nightly 04:20 scheduled by the worker | |
| |
87 | +| Link sweep (production) | initial `link_sweep` queued at deploy; in progress at handover (worker processes one record every ~3 s). Early transient `fetch failed` errors on the node resolved on re-check; the checker now records the network error code for diagnosis | |
| |
88 | +| Git | node directory adopted (`mld adopt`), pushed to spbgit `tools-spboucher-ai.git` (`gitsrv` alias added to M2M32c); laptop is a mirror | |
| |
89 | + |
| |
90 | +Owner follow-ups after handover: sign in at https://tools.spboucher.ai/login with the initial password from `~/Desktop/Cluster/secrets/tools-spboucher-ai/owner-initial-password.txt`, change it, enrol a passkey and/or TOTP, then review Admin → Links once the first sweep completes. |
| 67 | |
91 | |