| 64 |
64 |
|
| 65 |
65 |
## Production deployment verification (filled in Phase 6) |
| 66 |
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 |
|