docs(memory): capitalize tour residuals — BDR-006/007, LRN-003, journal, TOUR follow-up
BDR-006 supersedes BDR-004 infra detail (hardened container: nginx-unprivileged :1.28 / port 8080 / uid 101) — closes reconcile REC-1. BDR-007 supersedes BDR-003 geo (canonical = Nantes relocation) — records the CLN-9 owner decision. LRN-003: prove CSS cleanup behavior-preserving via before/after PDF render-hash. journal 2026-07-05; TOUR.md follow-up documenting all 5 residuals closed.
This commit is contained in:
@@ -27,6 +27,8 @@ rules:
|
||||
| BDR-003 | 2026-05-15 | Position pro: CDI prioritaire, freelance parallèle | accepted |
|
||||
| BDR-004 | 2026-05-15 | Containerize site with nginx:alpine behind reverse proxy | accepted |
|
||||
| BDR-005 | 2026-05-17 | Favicon: SVG primary + PIL raster fallback | accepted |
|
||||
| BDR-006 | 2026-07-05 | Hardened container: nginx-unprivileged + port 8080 | accepted (supersedes BDR-004 infra detail) |
|
||||
| BDR-007 | 2026-07-05 | Profile geo canonical: Nantes relocation | accepted (supersedes BDR-003 geo) |
|
||||
|
||||
---
|
||||
|
||||
@@ -95,3 +97,25 @@ rules:
|
||||
- Online favicon generator — external dep, opaque rendering, no source control.
|
||||
- **CV HTML**: not modified (user's WIP M state). Browser auto-fetches `/favicon.ico` from root → CV tab still shows icon. Link block mirror logged in `.claude/tasks/TODO.md` for later.
|
||||
- **Reference**: `favicon.svg`, `favicon-32.png`, `favicon.ico`, `apple-touch-icon.png`, `index.html` head, commit `ef31fb3`.
|
||||
|
||||
---
|
||||
|
||||
## BDR-006 — Hardened container: nginx-unprivileged base + port 8080
|
||||
|
||||
- **Date**: 2026-07-05
|
||||
- **Status**: accepted — supersedes the base-image/port detail of BDR-004
|
||||
- **Decision**: Container base = `nginxinc/nginx-unprivileged:1.28-alpine` (digest-pinned), runs as uid 101, listens on **8080** (not 80). Compose maps `127.0.0.1:${PORT}:8080`; `USER root` scoped to the one build-time `rm` only; `cap_add` dropped; `server_tokens off`; `set_real_ip_from 127.0.0.1`; `nginx-security-headers.conf` re-included per `location`; CSP `script-src` hash-pinned.
|
||||
- **Why**: SEC-1 tour finding — stock `nginx:*-alpine` runs its master as root inside the container. Unprivileged image + port 8080 removes the root master; the rest shrinks blast radius. BDR-004's "port 80 / nginx:1.27-alpine / HSTS omitted at container" no longer matched the tree.
|
||||
- **Supersedes**: BDR-004 — topology unchanged (native front proxy → container on loopback); only the base image, internal port, and uid change.
|
||||
- **Reference**: `Dockerfile`, `docker-compose.yml`, `nginx.conf`, `nginx-security-headers.conf`. Fix commit `ba13d69`; drift caught by tour REC-1 (`.claude/audits/TOUR.md`, run 2026-07-05-2).
|
||||
|
||||
---
|
||||
|
||||
## BDR-007 — Profile geo canonical: Nantes relocation
|
||||
|
||||
- **Date**: 2026-07-05
|
||||
- **Status**: accepted — supersedes the geography detail of BDR-003
|
||||
- **Decision**: Canonical profile geo = "Yerres (91) now; installation région nantaise prévue à moyen terme; full remote, hybride possible sur Nantes, ou 1–2 j/mois Paris." CV was the source of truth; `index.html` + `CLAUDE.md` aligned to it.
|
||||
- **Why**: tour CLN-9 found the landing ("mobilité Pays de la Loire") drifting from the CV ("installation région nantaise" + "hybride Nantes"). Owner chose the CV wording as truth — more current/specific, and Nantes ∈ Pays de la Loire so not contradictory. Cross-file profile-state consistency is a CLAUDE.md content rule.
|
||||
- **Alternatives rejected**: align CV down to the landing (would delete real, more-specific relocation info).
|
||||
- **Reference**: `index.html` (about para + about-callout), `CV_Bastien_Chanot.html`, `CLAUDE.md` geography note. Commit `f515875`.
|
||||
|
||||
@@ -33,3 +33,11 @@ rules:
|
||||
- Favicon set added (commit `ef31fb3`): SVG primary + PIL-generated PNG/ICO/apple-touch. Brand pulse-dot translated to icon. BDR-005 + LRN-002 logged.
|
||||
- CV files (`CV_Bastien_Chanot.html`, `.pdf`) untouched — user's WIP M state, off-scope per brief.
|
||||
- User pushed + reported favicon 404 in prod. Root cause: Dockerfile selective `COPY` whitelist never included favicon files. Fix shipped (commit `f1e4392`): COPY line appended + nginx long-cache rule for image assets. BLK-001 logged. VPS rebuild required.
|
||||
|
||||
## 2026-07-05
|
||||
|
||||
- Grouped tours (security+clean+reconcile+doc): container hardened (SEC-1..7 → nginx-unprivileged:1.28 / port 8080 / uid 101, per-location security headers, `server_tokens off`, CSP script-src hash-pinned), palette + dead-code clean, README synced. Merged via chore/tour + chore/tour-residuals. Detail in `.claude/audits/TOUR.md`.
|
||||
- Re-run tour (chore/tour-2026-07-05-2) CONVERGED 2 it: fresh semgrep PASS, dead CSS removed (`30b0e44`, render-hash proven behavior-preserving → LRN-003), reconcile caught BDR-004 drift, doc no-drift.
|
||||
- Closed all 5 residuals on owner GO: CLN-6 aria-hidden CTA arrows (`607124a`), CLN-7/8 palette conformance (5 off-palette colors → tokens, PDF regen render-verified, `ede7576`), CLN-9 geo aligned landing→CV = Nantes relocation (`f515875`).
|
||||
- Decided: BDR-006 (hardened container, supersedes BDR-004 infra), BDR-007 (geo canonical = Nantes, supersedes BDR-003 geo).
|
||||
- Branch chore/tour-2026-07-05-2 finished → develop + pushed.
|
||||
|
||||
@@ -21,6 +21,7 @@ rules:
|
||||
|----|------|---------|------------|
|
||||
| LRN-001 | 2026-05-15 | certbot --nginx matches `server_name`, not filename | nginx + certbot on multi-site VPS |
|
||||
| LRN-002 | 2026-05-17 | PIL supersample ×8 + Lanczos = clean icon antialiasing | Python stdlib icon generation |
|
||||
| LRN-003 | 2026-07-05 | Prove CSS cleanup behavior-preserving via before/after PDF render-hash | weasyprint / paged-media PDF projects |
|
||||
|
||||
---
|
||||
|
||||
@@ -39,3 +40,12 @@ rules:
|
||||
- **Pattern**: Render icon at 8× target size via `ImageDraw.rounded_rectangle` + `ellipse` on RGBA canvas, then `Image.resize((target, target), Image.LANCZOS)`. Output rivals `rsvg-convert` / `inkscape` for simple geometric shapes. Crisp at 16×16 favicon scale, no visible jaggies.
|
||||
- **Context**: Generated `favicon-32.png`, `apple-touch-icon.png` (180×180), `favicon.ico` (multi-size 16/24/32/48) for `bchanot.fr` from scratch — no `rsvg-convert` / `inkscape` / `ImageMagick` on host. Single PIL script, ~20 lines.
|
||||
- **Future application**: Any project needing a PNG/ICO icon set with a stdlib-only Python toolchain. Skip if shape is complex (text rendering, gradients, curves) — use `rsvg-convert` or commit a finalized PNG instead.
|
||||
|
||||
---
|
||||
|
||||
## LRN-003 — Prove CSS cleanup is behavior-preserving via before/after PDF render-hash
|
||||
|
||||
- **Date**: 2026-07-05
|
||||
- **Pattern**: To confirm a CSS/HTML edit is truly behavior-preserving on a project whose deliverable is a weasyprint PDF: render a baseline PDF from the pre-edit HTML, apply the edit, regenerate, then compare (a) `pdftotext | sha256` and (b) per-page `pdftoppm -r 150 -png | sha256`. Text-hash alone misses `font-size`/color changes — the render-hash catches them. Identical render-hash = provably no visual change; and since weasyprint output is deterministic, an unchanged render yields a byte-identical PDF → nothing new to commit.
|
||||
- **Context**: tour clean phase on `bchanot-cv` removed dead CSS (`.reveal.d6`, `position:running()`, no-op `box-shadow`, dead `.skills-grid font-size`). Render-hash matched on both pages → proven before commit `30b0e44`. The same tooling later confirmed the intentional palette edit DID change the render (expected), distinguishing dead-code removal from real visual change.
|
||||
- **Future application**: Any weasyprint / paged-media project where you must tell "dead code removal" (must render identically) apart from "intended visual change". General trick: verify a refactor by hashing the rendered artifact, not the source.
|
||||
|
||||
Reference in New Issue
Block a user