Files
lage-chat-control/migration/inventory/diff-report.md
T
Aurealibe 8ebc1da9e4 Rebuild du site sur Astro : i18n multilingue, faits verifies, Docker, CI, tests
- Astro statique, EN par defaut + /fr/ + /nl/, detection langue navigateur
- i18n par fichiers JSON, ajouter une langue = ajouter des traductions
- Contenu original porte a l'identique (diff d'inventaire par langue)
- Chronologie legislative corrigee sur sources primaires (PE, Conseil, votes)
- Timeline 23 precedents + observatoire 35 items + annuaire 66 outils FOSS,
  chaque affirmation verifiee et sourcee
- Zero requete tierce (teste), lisible JS coupe, axe WCAG AA x2 themes
- Version offline monofichier par langue a chaque build
- Docker multi-stage vers nginx + CSP stricte auto-generee
- CI GitHub Actions (SHA-pinnees) + verification hebdo des liens
- CONTRIBUTING : divulgation d'affiliation obligatoire, allowlist de
  domaines testee en CI
2026-07-10 03:52:49 +01:00

8.0 KiB
Raw Blame History

Content-migration diff report

Legacy monolith index.html (591 tri-lingual span lines / 659 data-l spans per language) → per-locale MDX under src/content/sections/{en,fr,nl}/ + src/data/tools.json.

How the inventories were produced

  • legacy-<lang>.txt — the FULL legacy document reduced to one language (every data-l run resolved), one line of whitespace-collapsed text per block-level element. Chrome (topbar, hero, status banner, TOC, footer) is included so nothing is hidden from this audit.
  • built-<lang>.txt — same dump algorithm over dist/index.html, dist/fr/index.html, dist/nl/index.html after pnpm build. One deviation: <noscript> is skipped because parse5 exposes its children as raw text (it is new chrome, absent from the legacy page anyway).
  • <b class="lbl"> / <b class="tool-label"> elements are flushed to their own line on both sides so tool-card prose lines stay comparable.
  • Non-breaking spaces are folded into plain spaces on both sides.
  • node migration/compare.mjs then segments each file into head-chrome / narrative window / tail-chrome (narrative = first PART 00 · line through the manifesto paragraph) and walks the two narrative windows in order, line by line. Every line must either match exactly or fall in one of the categories below; anything else exits non-zero.

Result

lang legacy narrative lines built narrative lines unexplained differences
en 789 991 0
fr 789 991 0
nl 789 991 0

991 = 789 6 (deferred legislative rows) + 208 (tool-card labels) in every language. Full machine output: compare-report.json.

Explained differences, exhaustively

1. Tool-card labels are now real text (+208 lines per language)

In the legacy page the field labels ("What it's for / Why it matters / For whom & when", À quoi ça sert / Pourquoi / Pour qui & quand, Waarvoor dient het / …) and the Install & use summary were CSS ::before/::after generated content, so they never appeared in the DOM text. ToolCard.astro renders them as real, accessible text: 54 cards × 3 field labels + 46 install summaries = 208 new lines per language. The label strings are byte-identical to the legacy CSS content values.

2. Deferred legislative-status claims (6 lines per language)

Per the migration plan, adopted/extended claims are being rewritten from verified sources separately. Dropped from the #menace comparison table (rows 4 and 5), verbatim:

  • EN: Duration / Temporary, extended to 3 April 2028 / Permanent / Status (Jul 2026) / Adopted 9 July 2026 / Under negotiation, 5th trilogue failed 29 June
  • FR: Durée / Temporaire, prolongé jusqu'au 3 avril 2028 / Permanent / Statut (juil. 2026) / Adopté le 9 juillet 2026 / En négociation, 5e trilogue échoué le 29 juin
  • NL: Looptijd / Tijdelijk, verlengd tot 3 april 2028 / Permanent / Status (juli 2026) / Aangenomen op 9 juli 2026 / In onderhandeling, 5e trialoog mislukt op 29 juni

The status banner ("Dernière minute : 9 juillet 2026" block) was excluded wholesale with the chrome (see §4); it is replaced by StatusBanner.astro fed from verified sources in the parallel workstream.

Two borderline in-prose date claims were kept (judgment call — they are narrative argument, not adopted/extended status): the 19 March 2026 joint appeal, and the "kept scanning after the legal basis lapsed on 4 April 2026" sentence, both in #menace.

3. Typographic quotes (smartypants)

Astro's default markdown pipeline (markdown.smartypants, ON by default) typesets " as “ ” and ' as in the rendered pages (en: 138 lines affected, fr: 225, nl: 70). No other smartypants rule fires: the legacy prose contains no ASCII ... or -- (its 3 are literal and pass through unchanged). This is the only character-level transformation in the entire narrative.

It could not be disabled from inside this migration's ownership (astro.config.mjs is off-limits). If byte-identical glyphs are required, the config owner can add markdown: { smartypants: false } — one line — and the compare gate can then drop its quote normalization.

4. Chrome not migrated (rebuilt separately)

Legacy head-chrome (36 lines/language) and tail-chrome (8 lines/language) deliberately not migrated to MDX:

  • topbar: brand ◆ EXIT CHAT CONTROL, FR/NL/EN buttons, theme toggle;
  • hero: stamp (Mass surveillance · EU · 2026), eyebrow, Exit Chat Control_ h1, lede paragraph, three profile meta tags;
  • status banner: Breaking: 9 July 2026 + the vote paragraph (superseded content, see §2);
  • TOC (24 lines) — duplicates the section titles that ARE migrated;
  • footer: Resources / Sources / Act link lists, GitHub link, disclaimer (Facts last updated: 9 July 2026).

The built pages already contain replacement chrome from the parallel rebuild workstream (TopBar/Footer/StatusBanner components, new hero h1 + description, skip-link, noscript note, rewritten source lists citing official roll-call results). That text intentionally differs from the legacy chrome and is not part of this migration's fidelity claim; it sits outside the compared narrative window (built head-chrome: 6 lines, tail-chrome: 9 lines).

  • The legacy inline JS (lang/theme toggles, simpleicons CDN loader) was not migrated by design. Icon rendering will be rebuilt offline later; the legacy CDN slugs are preserved in tools.json.iconSlug (validated, §6).

5. NL gaps

None. Every one of the 649 data-l runs carries all three languages (en/fr/nl counts are equal in every run), so the EN-fallback path never fired. extract-log.json → nlGaps: [].

6. tools.json notes (language-neutral facts)

  • 54 entries; every entry has url (first neutral footer link), full links array (21 cards have 23 links), monogram, color, profiles (the 🟢🟡🔴 footer note), level where the legacy card carried a level tag (34 cards; the other 20 never had one).
  • iconSlug was validated against the installed simple-icons package. Renamed upstream and mapped: tutanota → tuta, aegis → aegisauthenticator. Removed upstream and therefore set to null (6): briar, molly, ivpn, protonpass, nostr, standardnotes. 5 cards never had an icon in the legacy map (t-bitchat, t-databrokers, t-mailbox, t-website, t-yunohost).
  • 7 cards have localized display names (e.g. Firefox (durci/hardened/gehard), Sauvegardes chiffrées / Encrypted backups / Versleutelde back-ups). tools.json.name stores the EN plain text; the localized display name is rendered through the ToolCard name slot from each locale's MDX.
  • One presentational attribute dropped: style="margin:.6rem 0 .4rem" on the warning box inside t-bitchat (styling is rebuilt later; text intact).

7. Anchors

anchors.json lists all 82 id= values of the legacy file. 78 exist in every built page: 23 section ids on <section> wrappers, 54 tool ids on ToolCard <article> roots, top on the hero h1. The 4 missing are the legacy control-widget ids lang-fr, lang-nl, lang-en, theme (toggle buttons, never used as link targets — chrome rebuilt separately).

8. External domains for the allowlist review

The migrated content links to 75 unique external hostnames (external-domains.txt). The parallel workstream's tests/unit/dist-links.test.ts fails until these are reviewed and added to src/data/domains-allowlist.json — that file requires review and is outside this migration's ownership, so it was left untouched.

Reproduce

node migration/extract.mjs          # MDX + tools.json + anchors + legacy dumps
pnpm build
node migration/extract.mjs --built  # built-page dumps
node migration/compare.mjs          # exits non-zero on any unexplained diff