chore(memory): LRN-101 nginx add_header trap + EVAL-015 first real /tour run + journal

This commit is contained in:
Bastien Chanot
2026-07-05 13:14:59 +02:00
parent d933f6af20
commit 74d3804f59
3 changed files with 18 additions and 0 deletions
+8
View File
@@ -152,3 +152,11 @@ rules:
- **method**: main session verified ON DISK, not from agent summary: TODO zero-diff vs develop ✓, no target `.claude/memory/` created ✓, per-iteration semgrep report files present ✓, TOUR.md committed ✓, zero scope creep (no .gitignore) ✓, main/develop untouched + branch unmerged ✓, 3-iteration bound held ✓. - **method**: main session verified ON DISK, not from agent summary: TODO zero-diff vs develop ✓, no target `.claude/memory/` created ✓, per-iteration semgrep report files present ✓, TOUR.md committed ✓, zero scope creep (no .gitignore) ✓, main/develop untouched + branch unmerged ✓, 3-iteration bound held ✓.
- **anomalies**: (1) scratch semgrep files untracked → tree dirty at end, would self-block next run — patched STEP 3.2 [[LRN-100]]; (2) SEC-2 API-BREAKING fix (new required header) unflagged — patched template BREAKING tag; (3) positive: it2 re-verify caught regression of agent's OWN fix (`compare_digest(str)` raises on non-ASCII → 500 not 403), fixed + functionally proven it3 — re-verify loop has real teeth. - **anomalies**: (1) scratch semgrep files untracked → tree dirty at end, would self-block next run — patched STEP 3.2 [[LRN-100]]; (2) SEC-2 API-BREAKING fix (new required header) unflagged — patched template BREAKING tag; (3) positive: it2 re-verify caught regression of agent's OWN fix (`compare_digest(str)` raises on non-ASCII → 500 not 403), fixed + functionally proven it3 — re-verify loop has real teeth.
- **action**: keep (skill shipped). REFACTOR additions not re-run through 3rd full pass — re-test at first real use ([[LRN-100]]). - **action**: keep (skill shipped). REFACTOR additions not re-run through 3rd full pass — re-test at first real use ([[LRN-100]]).
## EVAL-015 — /tour first REAL run (report-only, bchanot-cv): REFACTOR additions validated; premise corrected by user
- **Date**: 2026-07-05
- **output**: report-only tour on live repo bchanot-cv: 4 parallel read-only audits (security-auditor semgrep BLOCK(1), cso posture 3 med/2 low/5 info, clean 10 findings, doc 2 drifts) + inline reconcile (ZERO drift — BLK-001 even live-confirmed via prod favicon 200). 14 findings folded into committed TOUR.md (5a813df, `.claude/**` on develop), scratch reports deleted, tree clean at end.
- **method**: real repo, no fixture. Deferred re-test executed: STEP 3.2 cleanup HELD (no self-block for next run), BREAKING tag correctly N/A (zero fixes in report-only). Cross-checks: cso live-confirmed SEC-2 (zero security headers served) — config-only review would have missed it ([[LRN-101]]).
- **anomalies**: (1) skill gap — report-only + clean tree has no branch, so the report commit lands on develop via the `.claude/**` exemption; works, but the placement is a judgment call the SKILL.md doesn't specify → candidate patch (needs its own failing test per Iron Law). (2) premise corrected by USER after the run: prod = native nginx, NOT the repo's Docker stack → container findings (SEC-1/4) latent, live header fix (SEC-2/3) belongs to VPS config outside the repo; audit scoping must confirm the serving stack first ([[LRN-101]] corollary). (3) parallel-phases deviation from the skill's sequential A→D held safely (report-only ⇒ no mutations between phases).
- **action**: keep. Skill validated on real drift; two refinement candidates noted (report-commit placement, serving-stack precheck), neither blocking.
+1
View File
@@ -334,3 +334,4 @@ rules:
## 2026-07-05 ## 2026-07-05
- Built /tour skill (grouped sweep clean+security+reconcile+doc, auto, 1..N projects, convergence loop bounded 3×) via writing-skills TDD + skill-creator guidance: RED 6 gaps → GREEN 6/6 closed disk-verified → REFACTOR 2 holes (scratch self-block, BREAKING tag). [[BDR-052]] [[LRN-099]] [[LRN-100]] [[EVAL-014]]. Merged feature/tour-skill → develop + release/1.0.0 on user GO. settings.json /model side-effect reverted (Opus 4.8 1M default restored, attribution backstop kept). - Built /tour skill (grouped sweep clean+security+reconcile+doc, auto, 1..N projects, convergence loop bounded 3×) via writing-skills TDD + skill-creator guidance: RED 6 gaps → GREEN 6/6 closed disk-verified → REFACTOR 2 holes (scratch self-block, BREAKING tag). [[BDR-052]] [[LRN-099]] [[LRN-100]] [[EVAL-014]]. Merged feature/tour-skill → develop + release/1.0.0 on user GO. settings.json /model side-effect reverted (Opus 4.8 1M default restored, attribution backstop kept).
- /tour first real run (report-only, bchanot-cv): 14 findings (1 high, 3 med — top value: nginx add_header inheritance wipes all security headers live, [[LRN-101]]), reconcile zero-drift, REFACTOR additions validated ([[EVAL-015]]). User corrected infra premise post-run: prod = NATIVE nginx, Docker stack latent → auto tour rescoped (ask-prod-info gate authorized by user).
+9
View File
@@ -120,6 +120,7 @@ rules:
| LRN-098 | 2026-07-04 | `/model` rewrites settings.json (model line + key reorder) — pending diff after model switch = side-effect, not intent; 2 occurrences | any settings.json commit; any "commit file X" — read diff, verify content matches intent | | LRN-098 | 2026-07-04 | `/model` rewrites settings.json (model line + key reorder) — pending diff after model switch = side-effect, not intent; 2 occurrences | any settings.json commit; any "commit file X" — read diff, verify content matches intent |
| LRN-099 | 2026-07-05 | auto-orchestrator autonomy boundary: git discipline transfers naturally (branch, no-merge), declared-state discipline does NOT — baseline silently rewrote target TODO + authored registries + scope-crept | designing any auto/headless flow — enumerate declared surfaces, mark each read-only or gated | | LRN-099 | 2026-07-05 | auto-orchestrator autonomy boundary: git discipline transfers naturally (branch, no-merge), declared-state discipline does NOT — baseline silently rewrote target TODO + authored registries + scope-crept | designing any auto/headless flow — enumerate declared surfaces, mark each read-only or gated |
| LRN-100 | 2026-07-05 | tool gated on clean tree must clean its OWN scratch (else self-DoS next run); contract-changing auto-fix needs structural BREAKING flag in the reviewed artifact | any recurring tool w/ cleanliness precondition; any auto-fix touching an API contract | | LRN-100 | 2026-07-05 | tool gated on clean tree must clean its OWN scratch (else self-DoS next run); contract-changing auto-fix needs structural BREAKING flag in the reviewed artifact | any recurring tool w/ cleanliness precondition; any auto-fix touching an API contract |
| LRN-101 | 2026-07-05 | nginx `add_header` inheritance trap: ANY add_header in a location block drops ALL inherited server-level headers on those responses — audit headers on LIVE responses (`curl -I`), never by reading the config; declared infra can be stale (prod ≠ repo stack) | any nginx project audit (zenquality, faunosteo…); any security-header claim |
--- ---
@@ -1049,3 +1050,11 @@ rules:
- **context**: 2026-07-04 /tour GREEN on fixture; both patched at REFACTOR (SKILL.md STEP 3). Additions template-structural, NOT re-run through 3rd full pass (cost) — re-test first real use. - **context**: 2026-07-04 /tour GREEN on fixture; both patched at REFACTOR (SKILL.md STEP 3). Additions template-structural, NOT re-run through 3rd full pass (cost) — re-test first real use.
- **future application**: any recurring tool gated on repo cleanliness → audit what IT leaves behind; any auto-applied fix changing a contract → structural BREAKING flag in the human-reviewed artifact. - **future application**: any recurring tool gated on repo cleanliness → audit what IT leaves behind; any auto-applied fix changing a contract → structural BREAKING flag in the human-reviewed artifact.
- **cousin**: [[LRN-099]] same chantier; [[LRN-071]] swallowed-failure class (silent residue ≈ masked state). - **cousin**: [[LRN-099]] same chantier; [[LRN-071]] swallowed-failure class (silent residue ≈ masked state).
## LRN-101 — nginx add_header inheritance: one child header wipes ALL parent headers — verify LIVE, not in config
- **pattern**: nginx `add_header` inherits from server level ONLY if a location block declares NONE of its own. One `add_header Cache-Control ...` in a location → ALL 5 server-level security headers (CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy) silently dropped on every response matching that location. bchanot-cv live: pages served ZERO security headers while the config declared all 5; only the 404 path (no location-level add_header) carried them. Corollary, same audit: declared infra was STALE — prod turned out native nginx, repo's Docker stack latent (user correction post-audit) → container findings latent, live fix belongs to the VPS config outside the repo.
- **why**: config review says "headers present" — a lie by inheritance. Only oracle = live responses (`curl -sI` per content type: html, pdf, image). Fix = repeat the headers in every location that uses add_header (or `include security-headers.conf`).
- **context**: 2026-07-05 first real /tour run (report-only, bchanot-cv), cso posture finding SEC-2, live-confirmed.
- **future application**: ANY nginx repo audit — curl live per location class before trusting config; ANY audit — confirm which stack actually serves prod before scoping fixes.
- **cousin**: [[LRN-034]] narrated ≠ ground truth; [[LRN-046]] verify before trust.