Commit Graph
58 Commits
Author SHA1 Message Date
Bastien Chanot aceb7e2c70 chore(cv): restructured CV + general variant, zone aligned
Owner-authored CV rework: technical skills promoted above experience,
'Centres d'intérêt' dropped, markup trimmed 656 -> 424 lines. Header
carries the Loire-Atlantique · Vendée · Morbihan zone and the presence
hierarchy (full remote, hybrid or on-site in the zone, Paris capped at
1-2 days/month).

Adds CV_Bastien_CHANOT_General.{html,pdf} as the general variant kept
alongside the served CV. Not linked from the landing and not in the
Dockerfile COPY whitelist, so it ships in the repo only, not to prod.

Both HTML/PDF pairs verified in sync via weasyprint re-render (text
identical, 2 pages each). New files normalized to mode 644.
2026-07-23 15:22:13 +02:00
Bastien Chanot e2f7ea4546 Merge chore/zone-loire-atlantique into develop 2026-07-23 14:56:24 +02:00
Bastien Chanot e13a4b1bb5 chore(profile): align geography to Loire-Atlantique · Vendée · Morbihan
Landing was still advertising Yerres (91) + a planned Nantes relocation,
and a presence rule that omitted on-site work in the target zone.

- about paragraph + callout: zone replaces 'Localisation actuelle';
  presence stated in order of preference — full remote, then hybrid or
  on-site in the zone, Paris only as a fallback at 1-2 days/month max
- ZenQuality timeline entry: drop the 'Yerres' location, keep 'Full remote'
- CLAUDE.md content rules: geography note rewritten to match, with an
  explicit 'never mention Yerres' guard

Verified: no 'Yerres' left outside the negative rule, CSP script hash
unchanged, headless render checked at 375px and 1440px.
2026-07-23 14:39:43 +02:00
Bastien Chanot 1c01cb20eb Merge release/1.0.0 into develop 2026-07-06 01:14:47 +02:00
Bastien Chanot 6b0ea8494b chore(release): 1.0.0 — version.txt + CHANGELOG (lineage starts) 2026-07-06 01:12:53 +02:00
Bastien Chanot 1d0b7ee8e7 Merge chore/tour-2026-07-05-3 into develop 2026-07-06 01:07:37 +02:00
Bastien Chanot 9af6aa4be8 chore(gitignore): ignore .gstack/ (browse daemon session state, contains tokens) 2026-07-06 01:07:26 +02:00
Bastien Chanot 136e1df5e3 docs(tour): follow-up — 10 residuals closed 2026-07-06 01:06:54 +02:00
Bastien Chanot c8c72c24aa chore(memory): capitalize — LRN-004, EVAL-001, BDR-006 update note, journal 2026-07-06 2026-07-06 01:06:54 +02:00
Bastien Chanot dd8c327162 docs(claude): document white family + CV typography exception (tour J1/J2) 2026-07-06 01:06:54 +02:00
Bastien Chanot 84288c5c58 fix(nginx+compose): dotfile block first, no pdf gzip, single healthcheck (tour J4/N4/J5)
Dotfile location moved above caching regex locations (first match wins).
application/pdf out of gzip_types (already flate-compressed). Compose
healthcheck block removed — image HEALTHCHECK is the single source,
inherited. Oracles: nginx -t, dotfiles 404, PDF no Content-Encoding,
HTML still gzipped, headers 5/5, inherited health = healthy.
2026-07-06 01:06:54 +02:00
Bastien Chanot a589b99878 perf(index): trim unused Google Fonts faces, drop contact-grid no-ops (tour N1/N3)
Fraunces 0,300/0,500/0,700 + DM Sans 300 unused (all serif-300 usages
are italic -> served by 1,400; no strong/em inside serif elements).
.contact-grid grid props no-op around single child. Verified headless
Chromium 375px + 1440px: real italic renders, layout intact, zero
console errors. Inline script untouched, CSP hash unchanged.
2026-07-06 01:06:54 +02:00
Bastien Chanot b86a5129f0 style(cv): french date chips, pill radius, font trim (tour N1/N2/J3)
Chips: avr./mars/fév + en-dash, mirrors landing wording. Tags radius
10px -> 999px (true pills). Fonts URL drops Fraunces 0,300/0,600 +
DM Sans 300 — trim proven render-identical (per-page hash == baseline)
BEFORE the intended chip/radius changes; PDF regenerated, 2 pages
eyeballed.
2026-07-06 01:06:54 +02:00
Bastien Chanot cc65225b3d docs(tour): report — run 2026-07-05-3 (converged, 3 iterations) 2026-07-06 00:51:17 +02:00
Bastien Chanot 2f5e51a1b4 docs: sync README base-image reference (1.28 -> 1.30-alpine) 2026-07-05 22:57:48 +02:00
Bastien Chanot 613bfc0d49 chore(clean): dedup CV/index CSS, drop dead directives (tour F1-F8)
CV: shared block for xp/project/edu headers + date chips + roles + tags,
2 identical inline style attrs -> .inline-link class, no-op body margin/
padding removed, stray blank collapsed. Proven behavior-preserving: PDF
text-hash + per-page render-hash + full byte-identity vs committed PDF.
index: .stack-note/.theme-list code grouped, 2 no-op .formation overrides
removed. nginx.conf: dead 'deny all' after return 404 removed (nginx -t +
dotfile-404 oracle PASS). .dockerignore: phantom nginx.conf.bak entry.
Snippet comment: CV style attrs no longer exist. CSP hash unchanged.
2026-07-05 22:52:39 +02:00
Bastien Chanot 1aa97f0af0 fix(security): bump base to nginx-unprivileged 1.30-alpine — CVE-2026-42945 (tour SEC-1)
1.28 stable branch retired; 2026-05-13 nginx security batch (rewrite-module
buffer overflow, fixed 1.30.1+) never backported to 1.28.x. New digest pin
carries nginx/1.30.3. Verified: build, nginx -t, uid 101, hardened run,
5/5 security headers + HTTP 200 on /, .html, .pdf, favicon.
2026-07-05 22:41:58 +02:00
Bastien Chanot 7967afff08 Merge chore/tour-2026-07-05-2 into develop 2026-07-05 22:20:32 +02:00
Bastien Chanot 7984a7d2df 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.
2026-07-05 21:28:17 +02:00
Bastien Chanot f5158758b2 content: align landing geo to CV — Nantes relocation (tour CLN-9)
CLAUDE.md requires the profile/job-search state to stay consistent across
index.html and the CV. The CV stated a concrete Nantes relocation + a
hybride-Nantes option the landing lacked. Per owner decision, the CV is
canonical: propagate those facts into the landing (about paragraph +
callout) and update CLAUDE.md's geography note to match. No invented claims
— mirrors what the CV already states. CV unchanged (no PDF regen).
2026-07-05 21:25:16 +02:00
Bastien Chanot ede75765cd style(palette): map 5 off-palette colors to palette tokens (tour CLN-7/8)
Brings both files back inside the CLAUDE.md palette (any color outside the
6 brand hex + documented neutrals is a violation). Nearest-allowed mappings,
minimal visual delta (verified by rendering the CV):
- index .footer bg #061008 -> var(--dark) #0d1b12 (the documented footer color).
- CV .tag border #a8d4bc -> var(--g300) (nearest visible green; keeps the pill outline).
- CV body+print texture rgba(26,71,48,.05) -> rgba(27,94,59,.05) (--g700 green primary).
- CV body+print gradient stops #edeadf/#f2efe6 -> var(--tag)/var(--page).
PDF regenerated (renders 2 pages, layout intact).
2026-07-05 21:24:08 +02:00
Bastien Chanot 607124aa70 fix(a11y): aria-hidden on 2 decorative CTA arrows (tour CLN-6)
The 'Me contacter' and 'Voir le CV' arrow SVGs were missing the
aria-hidden the sibling download arrow already carries; they are purely
decorative, so screen readers should skip them. Visual output unchanged.
2026-07-05 21:22:28 +02:00
Bastien Chanot 7b3d9bec4c docs(tour): report chore/tour-2026-07-05-2 — CONVERGED (2 it., 1 clean fix commit, 5 suggestions) 2026-07-05 21:05:43 +02:00
Bastien Chanot 30b0e44a45 chore(clean): remove dead CSS + normalize whitespace (tour CLN)
index.html: drop unused .reveal.d6 rule (markup uses d1-d5 only).

CV_Bastien_Chanot.html:
- remove dead `position: running(siteFooter)` — no `element()` consumer,
  and .footer-bar is `display:none` in @media print (the @page
  auto-numbered footer replaces it); on screen running() is an invalid
  position value, ignored.
- remove no-op `box-shadow: none` on .page (weasyprint ignores box-shadow;
  .page sets a shadow nowhere).
- remove dead `.skills-grid { font-size: 8.4pt }` (every direct child is a
  .skill-label/.skill-values div that sets its own size; no bare text).
- normalize stray blank lines.

Behavior-preserving: PDF regenerated from the edited HTML is byte-identical
to the pre-edit baseline (text sha256 + per-page PNG render hash match),
so CV_Bastien_Chanot.pdf is unchanged and the PDF=HTML invariant holds.
2026-07-05 20:47:51 +02:00
Bastien Chanot d7256ffe0e chore(deploy): mark 2026-07-05-2 @ b24c58b 2026-07-05 20:25:07 +02:00
Bastien Chanot b24c58b8a4 Merge chore/tour-residuals into develop 2026-07-05 20:06:12 +02:00
Bastien Chanot ef7e2312c6 docs: legalize functional neutrals (CLN-4) + CSP-hash invariant + TOUR follow-up
CLAUDE.md palette now two enforceable lists (6 brand + 8 documented
neutrals — anything else is a violation); workflow gains the recompute-
CSP-hash-after-JS-edit invariant with the exact command. README points to
the neutrals list. TOUR.md follow-up: CLN-3/CLN-4/SEC-7 closed, INF-2
corrected (false positive — .gitignore exists).
2026-07-05 19:59:45 +02:00
Bastien Chanot c0632aefa8 fix(security): pin script-src to the inline script's sha256 hash (SEC-7)
unsafe-inline dropped for scripts (index has zero style/script attributes;
the single inline script is hash-pinned). style-src keeps unsafe-inline
(CV carries 2 style attributes + single-file convention). Verified in
hardened container: served-script hash == policy hash, JS executes.
2026-07-05 19:59:45 +02:00
Bastien Chanot d63a52ec50 chore(clean): dedup card CSS via grouped selectors (CLN-3)
Shared chrome/hover/head/title/tag blocks for stack/project/theme cards +
methode items; per-class blocks keep only specifics. Zero HTML change,
cascade-order verified (no interfering rules between shared and specific
blocks). Net -60 lines; the audit's ~421 estimate was overstated.
2026-07-05 19:59:45 +02:00
Bastien Chanot bd7f6e4984 docs(deploy): runbook style — one command per line, session style 2026-07-05 15:31:10 +02:00
Bastien Chanot 395c77b597 chore(deploy): mark 2026-07-05 @ 5fe8b41 2026-07-05 15:23:46 +02:00
Bastien Chanot 5fe8b4119b feat(deploy): bootstrap runbook 2026-07-05 15:17:00 +02:00
Bastien Chanot 7b2d033761 Merge chore/tour-2026-07-05 into develop 2026-07-05 15:07:30 +02:00
Bastien Chanot c335769e1a docs(tour): auto run 2026-07-05 — converged in 2 iterations, 10 fixed, 3 open 2026-07-05 14:19:44 +02:00
Bastien Chanot 840632a6f8 docs: .githooks + hooksPath clone note; deploy section synced (native-nginx prod, hardened container path, headers snippet) 2026-07-05 14:12:43 +02:00
Bastien Chanot 7e7bd66384 chore(clean): enforce palette + reduced-motion, drop dead CSS
- 5x background:#fff -> var(--page) (stack/project/theme/methode cards +
  CV body) per CLAUDE.md 'no pure white background' (user-approved strict
  conformity; visual change: cards now blend with parchment, border-kept)
- prefers-reduced-motion now also kills transitions (universal rule)
- dead .screen-label rule removed (no matching element)
- PDF regenerated via weasyprint (must match HTML invariant)
2026-07-05 14:12:01 +02:00
Bastien Chanot ba13d697a5 fix(security): unprivileged nginx + security headers on every location
- base image -> nginxinc/nginx-unprivileged:1.28-alpine, digest-pinned
  (BREAKING for the docker path: container port 80 -> 8080; compose
  mapping/healthcheck updated in the same change, cap_add dropped)
- nginx add_header inheritance fix: shared snippets file re-included in
  every location that sets Cache-Control -- previously ALL security
  headers were dropped on real responses (verified live before/after)
- server_tokens off; set_real_ip_from restricted to 127.0.0.1
- expires directives removed (duplicated Cache-Control); gzip_types
  text/html redundancy removed (nginx -t warn)
2026-07-05 14:10:55 +02:00
Bastien Chanot 5a813df015 docs(tour): report-only audit 2026-07-05 — 7 security, 5 clean, 2 doc findings; reconcile zero-drift 2026-07-05 13:09:42 +02:00
Bastien Chanot f8b32d0797 Merge feature/doc-sync into develop 2026-07-01 14:31:37 +02:00
Bastien ChanotandClaude Opus 4.8 ce5c0481df docs: Docker deploy + contents table
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNaYKPEkjH1jbgoX1TwKMX
2026-07-01 14:31:37 +02:00
Bastien Chanot b5e127489b Merge chore/reconcile-memory into develop 2026-07-01 14:27:48 +02:00
Bastien ChanotandClaude Opus 4.8 dd186c9dac chore(memory): reconcile TODO with shipped extended-vitrine (1369d27)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNaYKPEkjH1jbgoX1TwKMX
2026-07-01 00:20:23 +02:00
Bastien Chanot 195188f518 chore: adopt gitflow socle + pre-commit hook 2026-06-29 02:37:20 +02:00
Bastien Chanot 1ae73e0534 cv definitif 2026-05-17 04:26:29 +02:00
Bastien ChanotandClaude Opus 4.7 aa52153b2c docs(memory): BLK-001 favicon 404 in prod — Dockerfile COPY whitelist
Root cause + fix logged. New repo assets must be added to Dockerfile
COPY whitelist explicitly; future option = glob pattern if asset count
grows. Journal updated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 04:08:18 +02:00
Bastien ChanotandClaude Opus 4.7 f1e4392c65 fix(docker): COPY favicon assets into image + cache header
Dockerfile selectively COPYs files into /usr/share/nginx/html. Favicon
assets (favicon.svg, favicon-32.png, favicon.ico, apple-touch-icon.png)
were added to the repo in ef31fb3 but never wired into the Dockerfile,
so a rebuilt container served 404 for /favicon.svg and friends — broken
favicon in prod even after `docker compose up -d --build`.

nginx.conf gets a matching long-cache rule for icon/image assets
(30 days, immutable, access_log off) — they rarely change and the file
name is the cache key anyway.

Deploy: on the VPS, `docker compose up -d --build`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 04:07:32 +02:00
Bastien Chanot 1f9416edf0 added pdf and html cv version 2026-05-17 03:54:39 +02:00
Bastien ChanotandClaude Opus 4.7 86d4c729ed docs(memory): capitalize BDR-005 favicon strategy + LRN-002 PIL icon recipe
- BDR-005: SVG primary + PIL-generated PNG/ICO fallback for favicon set;
  alternatives (rsvg-convert/inkscape, SVG-only, online generator) rejected
  with reasons; CV mirror deferred to user finalization.
- LRN-002: PIL supersample x8 + Lanczos downscale produces clean
  small-format icon antialiasing without rsvg-convert/inkscape/ImageMagick.
- journal: 2026-05-17 entry — extended-vitrine refactor (1369d27) +
  favicon set (ef31fb3); CV files left untouched (user WIP).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 03:53:42 +02:00
Bastien ChanotandClaude Opus 4.7 ef31fb3059 feat(landing): add favicon set — SVG primary + PNG/ICO fallback
Brand pulse-dot translated to favicon: dark rounded square (#0d1b12) +
inner green dot (#6ab98a) + faint outer ring (#2d7a4f @60%). Identical
visual language to .brand::before in the nav.

Assets:
- favicon.svg          — vector primary (modern browsers, scales)
- favicon-32.png       — PNG hint
- favicon.ico          — legacy multi-size (16/24/32/48)
- apple-touch-icon.png — iOS home-screen 180x180

PIL-generated PNG/ICO at 8x supersample + Lanczos downscale for clean
antialiasing. No external dependency added (PIL already on system).

index.html: 4 <link> tags wired in <head> (SVG, PNG 32, ICO alternate,
apple-touch). CV HTML left untouched; browser auto-fetches /favicon.ico
from root as fallback — TODO logged to mirror the link block when the
user finalizes CV edits.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 03:51:14 +02:00
Bastien ChanotandClaude Opus 4.7 1369d27b5b feat(landing): extended-vitrine refactor — CV-aligned, +Projets, +Méthode
Landing now says more than the CV instead of duplicating it.

- meta/title: synced with new positioning (kernel, AOSP, cloud gaming, GPU)
- nav: added #projets and #methode anchors
- hero: subtitle "Développeur Systèmes · Embarqué · Backend",
  tech banner Backend·Cloud
- about: senior wording + 3 new paragraphs (philosophy, target context,
  what I'm not chasing)
- stack: 6 → 8 cards
  - dropped VMware, Gitflow, Agile
  - added cgroups, namespaces, SELinux, GitHub Actions
  - new Cloud/Infra card (AWS EC2, g4dn bare-metal, IAM, S3, CloudWatch,
    Scaleway VPS, OVH/Hetzner, Nginx, Apache, Let's Encrypt)
  - new IA/Outils card (Claude Code agents/skills, N8N, automation)
  - Familier avec: C++ sub-row in Langages
- parcours: removed lone-wolf wording (seul / responsable unique);
  CareGame / ZenQuality / Deewee rewritten as intro + technical bullets +
  per-experience stack pills; Deewee dates corrected to fév.-nov. 2017
  with Stage 42 + CDD contract line
- new Projets section between Parcours and Formation: Git auto-hébergé
  (git.bchanot.fr) and Homelab
- new Méthode section between Formation and Contact: 5 habits
- contact email: chanot.bastien@gmail.com → bastien@bchanot.fr
- CSS: extensions only (.timeline-bullets, .timeline-stack,
  .timeline-intro, .timeline-contract, .projects-grid, .project-card*,
  .methode-list, .methode-item, .methode-num, .stack-note, .pill-context),
  all reusing existing design tokens

TODO.md tracks the refactor milestone.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 03:50:41 +02:00