Merge chore/tour-2026-07-05-2 into develop
This commit is contained in:
@@ -101,3 +101,69 @@ port — compose covered). Branch left UNMERGED — `gitflow finish` on GO.
|
||||
| CLN-4 | Norm aligned with reality: the 8 functional neutrals (inks, rule/tag, 2 green intermediates) are now DOCUMENTED as allowed in CLAUDE.md (+ README pointer). "Any color outside the two lists is a violation" keeps the norm enforceable. |
|
||||
| SEC-7 | script-src hardened: `unsafe-inline` replaced by the sha256 hash of the single inline script (index has zero style/script attributes). style-src keeps `unsafe-inline` (CV carries 2 style attributes + single-file convention) — documented. NEW INVARIANT in CLAUDE.md: recompute the hash after any inline-JS edit (stale hash = JS silently blocked in prod). |
|
||||
| INF-2 | CORRECTION: false positive in the 2026-07-05 report-only run — `.gitignore` exists (549B) and covers the expected classes. No action was ever needed. |
|
||||
|
||||
## Tour 2026-07-05-2 — AUTO — branch chore/tour-2026-07-05-2 — 2 iterations — CONVERGED
|
||||
|
||||
Re-run of /tour on develop (d7256ff) after the day's earlier tours merged. Goal:
|
||||
verify no regression + catch anything new. Branch suffixed `-2` to keep this
|
||||
header distinct from the earlier converged run. gstack OFF → optional It1 cso
|
||||
posture add-on not run; the security floor (security-auditor + pinned semgrep)
|
||||
ran BOTH iterations, not degraded. No package.json/Makefile → no automated
|
||||
tests/lint/build; project checks = domain invariants (CSP-hash, PDF↔HTML).
|
||||
|
||||
| ID | Axis | File | Sev | Finding | Status |
|
||||
|----|------|------|-----|---------|--------|
|
||||
| SEC-1 | security | (full tree) | - | Fresh semgrep both iterations → VERDICT PASS, 0 blocking. Sole note: `style-src 'unsafe-inline'` (accepted single-file convention, It1==It2). No regression from the prior SEC fixes; script-src hash still matches inline script | pass |
|
||||
| CLN-1 | clean | index.html:347 | - | dead `.reveal.d6` rule (markup uses reveal d1–d5 only) | fixed 30b0e44 |
|
||||
| CLN-2 | clean | CV:408 | - | dead `position: running(siteFooter)` — no `element(siteFooter)` consumer; `.footer-bar` is `display:none` in @media print (@page auto-numbered footer replaces it); on screen running() is an invalid position value, ignored | fixed 30b0e44 |
|
||||
| CLN-3 | clean | CV:438 | - | no-op `box-shadow: none` on `.page` (`.page` sets a shadow nowhere; weasyprint ignores box-shadow entirely — confirmed by its own warning) | fixed 30b0e44 |
|
||||
| CLN-4 | clean | CV:315 | - | dead `.skills-grid { font-size: 8.4pt }` — every direct child is a `.skill-label`(9.5pt)/`.skill-values`(10pt) div; no bare text node, no em-dependency → never renders | fixed 30b0e44 |
|
||||
| CLN-5 | clean | CV:46-48,54,316 | - | stray blank lines (triple blank before `.page`, blanks inside `.page`/`.skills-grid`) | fixed 30b0e44 |
|
||||
| CLN-6 | a11y | index.html:1003,1007 | - | 2 decorative `.arrow` SVGs miss the `aria-hidden="true"` the sibling download arrow (1011) has. NOT auto-fixed: adding it changes the a11y tree → outside the clean phase's behavior-preserving scope (belongs to an a11y pass; cf. TODO "WCAG AA contrast") | open (suggested) |
|
||||
| CLN-7 | norm | index.html:931 | - | `.footer` bg `#061008` is off-palette (darker than `--dark #0d1b12`, `--g900 #0e3320`). Design system documents footer = `#0d1b12`. Fix changes rendering (slightly lighter footer) → owner decision, not auto-fixed | open (suggested) |
|
||||
| CLN-8 | norm | CV:252,135-136,434-435 | - | off-palette colors: `#a8d4bc` tag border (252), gradient stops `#edeadf`/`#f2efe6` (136/435), texture fill `rgba(26,71,48,0.05)` (135/434). All rendering-changing → owner decision, not auto-fixed | open (suggested) |
|
||||
| CLN-9 | content | index.html vs CV:507-508 | - | profile-state wording drift: landing "Pays de la Loire / remote or 1–2j Paris" vs CV "région nantaise / hybride Nantes / 1–2j Paris" (not contradictory — Nantes ∈ PdL — but CV adds "hybride Nantes"). CLAUDE.md requires cross-file consistency → owner picks canonical wording, not auto-fixed | open (suggested) |
|
||||
| REC-1 | reconcile | .claude/memory/decisions.md | - | **BDR-004 stale**: text says `nginx:1.27-alpine` / container port 80 / "HSTS omitted at container", but the real Dockerfile+compose (post 2026-07-05 SEC-1 fix) = `nginxinc/nginx-unprivileged:1.28-alpine` / port 8080 / uid 101. That tour never added a superseding decision (index stops at BDR-005). Append-only registry + tour-read-only → SUGGEST a superseding **BDR-006**. README deploy section is already correct | suggested |
|
||||
| REC-2 | reconcile | .claude/memory/decisions.md | - | BDR-002 "Warnings connus: `box-shadow:none` ignoré par weasyprint" — that declaration was removed this tour (CLN-3), so the documented warning no longer fires. Minor note to add when BDR-002 is next touched | suggested |
|
||||
| REC-3 | reconcile | TODO.md + registries | - | ZERO false-done. Oracles: 1369d27 exists ✓; `og:image` absent = TODO item genuinely open ✓; CV favicon-block not mirrored = open, matches BDR-005 note ✓; WCAG-contrast + real-mobile-QA open ✓; develop==origin/develop (d7256ff), branch +1 unmerged ✓; BLK-001 resolved, favicon assets present ✓ | consistent |
|
||||
| DOC-1 | doc | README.md | - | doc-syncer automatic mode → `PATCHED_FILES: (none)`. Deploy section already reflects unprivileged image/port 8080 (prior tour sync); file table matches root inventory; cleanup touched nothing user-facing | no-op |
|
||||
| INV-1 | invariant | index.html / CV pdf | - | CSP hash `sha256-Al1M34KxI6Ye5Viu6aO//7CYyaLzqtpG9GX95FFlSOY=` recomputed == pinned (inline `<script>` untouched) ✓; PDF regenerated byte-identical to the pre-edit baseline (text sha256 083055…96a8 + per-page PNG @150dpi render hash all match) → PDF=HTML invariant holds, PDF file unchanged | held |
|
||||
|
||||
### Iterations
|
||||
1. **It1** — security-auditor fresh semgrep (94 rules / 25 files → VERDICT PASS,
|
||||
1 accepted LOW) + read-only clean audit (13 findings: C1–C8, N1–N5). Applied
|
||||
behavior-preserving fixes CLN-1..5 (commit 30b0e44); proven behavior-preserving
|
||||
(PDF renders pixel-identical, CSP hash unchanged). Fresh `analyzer` re-verify:
|
||||
RE-VERIFY PASS, braces balanced, zero new. Reconcile (report-only): BDR-004
|
||||
drift + BDR-002 note + zero false-done. Doc: no drift.
|
||||
2. **It2 (convergence)** — fresh full-tree semgrep: VERDICT PASS, identical to It1,
|
||||
0 new blocking. Clean stability: 4 removed selectors GONE, braces balanced
|
||||
(index 204/204, CV 68/68), known-open findings (CLN-6..9) persist = NOT new,
|
||||
zero new introduced. Zero fixes → CONVERGED.
|
||||
|
||||
### Residuals (open — all require owner judgment, none auto-fixable behavior-preservingly)
|
||||
CLN-6 (arrows aria-hidden — a11y pass), CLN-7/8 (off-palette colors — design
|
||||
decision), CLN-9 (profile-state wording — copy canonicalization), REC-1
|
||||
(superseding BDR-006 for the hardened container), REC-2 (BDR-002 warning note).
|
||||
SEC accepted-LOW (`style-src 'unsafe-inline'`) unchanged from prior runs.
|
||||
|
||||
Checks: semgrep PASS (both it.), CSP-hash MATCH, PDF↔HTML byte-identical render,
|
||||
CSS braces balanced. No automated tests/lint/build (static site).
|
||||
Commits: 2 (clean 30b0e44 + this report). BREAKING: 0. Branch left UNMERGED.
|
||||
Scratch reports (.tour-semgrep, .tour-clean, .tour-semgrep-it2) folded here then
|
||||
deleted (STEP 3.2).
|
||||
|
||||
## Follow-up 2026-07-05-2 — all 5 residuals closed (chore/tour-2026-07-05-2, owner GO)
|
||||
|
||||
| ID | Resolution |
|
||||
|----|-----------|
|
||||
| CLN-6 | `aria-hidden="true"` added to the 2 decorative CTA arrows (match sibling download arrow). Visual identical, a11y-tree only. Commit `607124a`. |
|
||||
| CLN-7 | `.footer` bg `#061008` → `var(--dark)` #0d1b12 (the design-system footer color). Commit `ede7576`. |
|
||||
| CLN-8 | CV off-palette → tokens: `.tag` border `#a8d4bc` → `var(--g300)` (nearest visible green); body+print texture `rgba(26,71,48,.05)` → `rgba(27,94,59,.05)` (--g700); gradient stops `#edeadf`/`#f2efe6` → `var(--tag)`/`var(--page)`. PDF regenerated, render verified (2 pages, layout intact, page-1 eyeballed). Commit `ede7576`. |
|
||||
| CLN-9 | Owner chose the CV wording as canonical (Option B): landing about-para + callout aligned to "installation région nantaise prévue" + "hybride Nantes"; `CLAUDE.md` geography note updated to match. CV unchanged. Commit `f515875` → BDR-007. |
|
||||
| REC-1 | BDR-004 drift resolved by superseding entry **BDR-006** (nginx-unprivileged:1.28 / port 8080 / uid 101). |
|
||||
| REC-2 | BDR-002 "box-shadow warning" note now historical (declaration removed in `30b0e44`) — left as-is (append-only registry), noted here. |
|
||||
|
||||
Checks: CSP-hash MATCH, braces balanced (index 204/204, CV 68/68), PDF 2 pages.
|
||||
Commits: 3 fixes (`607124a`/`ede7576`/`f515875`) + capitalize (BDR-006/007, LRN-003,
|
||||
journal) + this follow-up. Branch finished → develop + pushed on owner GO.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -115,8 +115,9 @@ Forbidden:
|
||||
- Profile state, including job search context, must stay consistent across
|
||||
index.html and CV. Currently: looking for **CDI** in embedded / systems
|
||||
software first; freelance missions (ZenQuality) in parallel.
|
||||
- Geography: Yerres (91) currently; targeting Pays de la Loire mid-term;
|
||||
full remote preferred or hybrid 1–2 days/month if Paris.
|
||||
- Geography: Yerres (91) currently; relocation to the Nantes area (Pays de
|
||||
la Loire) planned mid-term; full remote preferred, hybrid possible in
|
||||
Nantes, or hybrid 1–2 days/month if Paris.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+6
-12
@@ -44,14 +44,11 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.page {
|
||||
width: 210mm;
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
background: var(--page);
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -132,8 +129,8 @@
|
||||
.cv-body {
|
||||
padding: 10px 20mm 12px;
|
||||
background:
|
||||
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='6' height='6'%3E%3Ccircle cx='1' cy='1' r='0.6' fill='rgba(26,71,48,0.05)'/%3E%3C/svg%3E"),
|
||||
linear-gradient(160deg, #f5f3ec 0%, #edeadf 55%, #f2efe6 100%);
|
||||
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='6' height='6'%3E%3Ccircle cx='1' cy='1' r='0.6' fill='rgba(27,94,59,0.05)'/%3E%3C/svg%3E"),
|
||||
linear-gradient(160deg, var(--page) 0%, var(--tag) 55%, var(--page) 100%);
|
||||
}
|
||||
|
||||
.accroche {
|
||||
@@ -249,7 +246,7 @@
|
||||
.tag {
|
||||
display: inline-block;
|
||||
background: var(--g100);
|
||||
border: 1px solid #a8d4bc;
|
||||
border: 1px solid var(--g300);
|
||||
font-family: var(--mono);
|
||||
font-size: 6.5pt;
|
||||
padding: 1px 5px;
|
||||
@@ -312,8 +309,6 @@
|
||||
display: grid;
|
||||
grid-template-columns: 115px 1fr;
|
||||
gap: 1px 10px;
|
||||
font-size: 8.4pt;
|
||||
|
||||
}
|
||||
|
||||
.skill-label {
|
||||
@@ -405,7 +400,6 @@
|
||||
|
||||
/* ── FOOTER ── */
|
||||
.footer-bar {
|
||||
position: running(siteFooter);
|
||||
background: var(--dark);
|
||||
padding: 5px 20mm;
|
||||
display: flex;
|
||||
@@ -431,11 +425,11 @@
|
||||
@media print {
|
||||
body {
|
||||
background:
|
||||
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='6' height='6'%3E%3Ccircle cx='1' cy='1' r='0.6' fill='rgba(26,71,48,0.05)'/%3E%3C/svg%3E"),
|
||||
linear-gradient(160deg, #f5f3ec 0%, #edeadf 55%, #f2efe6 100%);
|
||||
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='6' height='6'%3E%3Ccircle cx='1' cy='1' r='0.6' fill='rgba(27,94,59,0.05)'/%3E%3C/svg%3E"),
|
||||
linear-gradient(160deg, var(--page) 0%, var(--tag) 55%, var(--page) 100%);
|
||||
padding: 0;
|
||||
}
|
||||
.page { box-shadow: none; background: transparent; }
|
||||
.page { background: transparent; }
|
||||
.cv-header { padding: 18px 14mm 14px; }
|
||||
.cv-body { padding: 10px 14mm 12px; background: transparent; }
|
||||
|
||||
|
||||
Binary file not shown.
+6
-7
@@ -344,7 +344,6 @@
|
||||
.reveal.d3 { animation-delay: .30s; }
|
||||
.reveal.d4 { animation-delay: .42s; }
|
||||
.reveal.d5 { animation-delay: .55s; }
|
||||
.reveal.d6 { animation-delay: .68s; }
|
||||
@keyframes rise {
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
@@ -928,7 +927,7 @@
|
||||
|
||||
/* ── FOOTER ── */
|
||||
.footer {
|
||||
background: #061008;
|
||||
background: var(--dark);
|
||||
color: rgba(223, 240, 231, 0.55);
|
||||
padding: 32px 24px;
|
||||
border-top: 1px solid rgba(106,185,138,0.1);
|
||||
@@ -1000,11 +999,11 @@
|
||||
<div class="hero-cta reveal d4">
|
||||
<a class="btn btn-primary" href="#contact">
|
||||
Me contacter
|
||||
<svg class="arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="19" x2="19" y2="5"/><polyline points="8 5 19 5 19 16"/></svg>
|
||||
<svg class="arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="5" y1="19" x2="19" y2="5"/><polyline points="8 5 19 5 19 16"/></svg>
|
||||
</a>
|
||||
<a class="btn btn-secondary" href="CV_Bastien_Chanot.html">
|
||||
Voir le CV
|
||||
<svg class="arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="19" x2="19" y2="5"/><polyline points="8 5 19 5 19 16"/></svg>
|
||||
<svg class="arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="5" y1="19" x2="19" y2="5"/><polyline points="8 5 19 5 19 16"/></svg>
|
||||
</a>
|
||||
<a class="btn btn-secondary" href="CV_Bastien_Chanot.pdf" download>
|
||||
Télécharger PDF
|
||||
@@ -1031,7 +1030,7 @@
|
||||
<p>Ce qui m'intéresse, c'est descendre jusqu'à ce qu'il n'y ait plus de magie — <strong>kernel, hardware, drivers</strong>. Là, soit ça marche, soit ça ne marche pas.</p>
|
||||
<p>C'est ce confort-là que je cherche dans une équipe : <strong>systèmes, embarqué, backend bas niveau</strong>, sur une stack dont on peut lire le code source. Pas envie d'aller vers le buzzword-driven — microservices à tout prix, framework du mois, archi conçue pour le pitch deck.</p>
|
||||
<p>Aujourd'hui indépendant sous la marque <strong>ZenQuality</strong>, mais avant tout en recherche d'un <strong>CDI en systèmes embarqués ou logiciel</strong> — les missions freelance se font en parallèle.</p>
|
||||
<p>Côté présence : <strong>full remote</strong> idéalement, ou <strong>hybride 1 à 2 jours par mois</strong> si l'équipe est à Paris. Mobilité visée à moyen terme : <strong>Pays de la Loire</strong>.</p>
|
||||
<p>Côté présence : <strong>full remote</strong> idéalement, <strong>hybride possible sur Nantes</strong>, ou <strong>1 à 2 jours par mois</strong> si l'équipe est à Paris. Installation en <strong>région nantaise</strong> prévue à moyen terme.</p>
|
||||
</div>
|
||||
<dl class="about-callout">
|
||||
<dt>Recherche prioritaire</dt>
|
||||
@@ -1039,9 +1038,9 @@
|
||||
<dt>En parallèle</dt>
|
||||
<dd>Missions freelance · ZenQuality</dd>
|
||||
<dt>Localisation actuelle</dt>
|
||||
<dd>Yerres (91) · mobilité Pays de la Loire</dd>
|
||||
<dd>Yerres (91) · installation région nantaise prévue</dd>
|
||||
<dt>Présence</dt>
|
||||
<dd>Full remote · ou 1–2 j/mois si Paris</dd>
|
||||
<dd>Full remote · hybride Nantes · ou 1–2 j/mois Paris</dd>
|
||||
<dt>Site pro</dt>
|
||||
<dd><a href="https://zenquality.fr" target="_blank" rel="noopener">zenquality.fr ↗</a></dd>
|
||||
</dl>
|
||||
|
||||
Reference in New Issue
Block a user