feat(release): laat de webbundel met licentie, bron, SBOM en checksums reizen (#520) #665

Merged
brenno merged 3 commits from feat/release-artefacten into main 2026-07-22 18:10:12 +00:00
Owner

Werkt #520 af voor zover het zonder certificaat kan. Het taggen blijft van de beheerder.

Wat er verandert

Een webbundel die je aan iemand geeft was tot nu toe de app plus de SBOM. Daar horen drie dingen bij die er niet in zaten:

  • LICENSE.md en THIRD_PARTY_NOTICES.md — zonder die voorwaarden mag de ontvanger het ding niet doorgeven. Dat is geen nettigheid maar de afspraak waaronder de afhankelijkheden zélf meereizen.
  • SOURCE.mdmain.dart.js is gecompileerd. EUPL-1.2 artikel 5 vraagt bij het distribueren of communiceren van het Werk om de bron of een aanwijzing ernaartoe, en artikel 1 rekent hosten uitdrukkelijk tot communiceren. Zonder dit kreeg de ontvanger onleesbare JavaScript met een licentie eronder die zegt dat hij het mag bestuderen en aanpassen, en geen route om dat te doen.
  • SHA256SUMS — in het gewone sha256sum-formaat, zodat shasum -a 256 -c SHA256SUMS volstaat.

Dat de checksumstap de láátste is, is de hele reden dat het één gereedschap is (tool/pack_web_release.dart) en niet een paar cp-regels: zolang kopiëren en hashen op twee plekken staan, komt er een dag waarop iemand er een bestand tussen schuift en de lijst stil onvolledig wordt. --check loopt een klaargezette bundel na en klaagt óók over een bestand dat er onaangekondigd bíj is gekomen.

.last_build_id gaat er juist uit vóór het hashen — zie hieronder.

Daarnaast staat de op 22-07 genomen scopebeslissing nu in de gepubliceerde tekst in plaats van alleen in het issue: 0.1.0 is een webbundel, desktop blijft zelf-bouwen-uit-de-bron.

Wat het níét belooft

SHA256SUMS is geen handtekening, en de teksten zeggen dat met zoveel woorden. De lijst laat je nákijken; uit zichzelf bewijst hij niets. De controle die wél iets zegt is de sha256 van SHA256SUMS afzetten tegen de aankondiging, via een ander kanaal — en ook dáár staat de grens bij: het vangt een beschadigde download, een gewijzigde spiegel en een herhost, níet een compromittering van onze eigen publicatieketen. Daar helpt alleen een handtekening of een reproduceerbare build tegen, en die hebben we vandaag geen van beide.

Die kernzin staat als constante in de code met een test eromheen, zodat niemand hem later stelliger maakt dan hij is.

Bewakerreview

Gedraaid vóór de poort, want dit raakt publieke beloftes. Twee blokkerende bevindingen, beide nagemeten en verholpen in 908c9719:

  1. Geen bronaanwijzing in de bundel (EUPL art. 5). De repo-URL stond er alleen in .well-known/security.txt — een beveiligingscontactbestand dat een herhoster door zijn eigen vervangt. → SOURCE.md.
  2. .last_build_id werd mee verzegeld. De inhoud is een md5 over onder meer het absolute pad van de uitvoermap op de bouwmachine. Wie zelf bouwt kreeg daardoor gegarandeerd een andere digest dan de aankondiging, bij byte-identieke bron — de ene controle die een zelf-bouwer een onafhankelijk oordeel geeft, stond structureel op rood. → eruit vóór het hashen, en de claim "sorteren maakt de lijst reproduceerbaar" is teruggebracht tot wat sorteren wérkelijk doet.

Vier kleinere bevindingen zijn in dezelfde ronde verwerkt: de bescheidenheidsformulering van checksumUitleg, de grens van het aankondigingskanaal, de vertrouwensruil van een gehoste webapp tegenover een binair (die stond als "geen probleem" opgeschreven terwijl hij juist de mínst soevereine vorm is), en een standaardrecept voor "er is niets bíjgekomen" dat geen Dart-toolchain vraagt.

Getoetst

  • make check groen.
  • make check-web op een echt gebouwde bundel: 134 bestanden, hardening OK, artefacten OK.
  • shasum -a 256 -c SHA256SUMS leest de lijst en wordt rood zodra er één byte wijzigt.
  • Het diff-recept dat de documentatie geeft levert niets op een schone bundel en wijst een gepland extra bestand aan.
  • 17 tests in test/pack_web_release_test.dart, elke klacht apart rood gezien.

Niet gedraaid: make check-secrets en make sast — gitleaks, trufflehog en semgrep staan geen van drieën op deze machine (make check-secrets breekt af op "gitleaks not found"). DAST evenmin. Deze wijziging voegt geen sleutel, geen netwerkpad en geen afhankelijkheid toe, maar de eis is daarmee niet gehaald en dat hoort hier te staan.

Buiten scope

version.json en de SBOM zeggen 0.2.0+1 terwijl de nieuwe teksten over 0.1.0 gaan. Dat is #629 en blijft daar.

Closes #520

Werkt #520 af voor zover het zonder certificaat kan. Het taggen blijft van de beheerder. ## Wat er verandert Een webbundel die je aan iemand geeft was tot nu toe de app plus de SBOM. Daar horen drie dingen bij die er niet in zaten: - **`LICENSE.md` en `THIRD_PARTY_NOTICES.md`** — zonder die voorwaarden mag de ontvanger het ding niet doorgeven. Dat is geen nettigheid maar de afspraak waaronder de afhankelijkheden zélf meereizen. - **`SOURCE.md`** — `main.dart.js` is gecompileerd. EUPL-1.2 artikel 5 vraagt bij het distribueren *of communiceren* van het Werk om de bron of een aanwijzing ernaartoe, en artikel 1 rekent hosten uitdrukkelijk tot communiceren. Zonder dit kreeg de ontvanger onleesbare JavaScript met een licentie eronder die zegt dat hij het mag bestuderen en aanpassen, en geen route om dat te doen. - **`SHA256SUMS`** — in het gewone `sha256sum`-formaat, zodat `shasum -a 256 -c SHA256SUMS` volstaat. Dat de checksumstap de láátste is, is de hele reden dat het één gereedschap is (`tool/pack_web_release.dart`) en niet een paar `cp`-regels: zolang kopiëren en hashen op twee plekken staan, komt er een dag waarop iemand er een bestand tussen schuift en de lijst stil onvolledig wordt. `--check` loopt een klaargezette bundel na en klaagt óók over een bestand dat er onaangekondigd bíj is gekomen. `.last_build_id` gaat er juist uit vóór het hashen — zie hieronder. Daarnaast staat de op 22-07 genomen scopebeslissing nu in de gepubliceerde tekst in plaats van alleen in het issue: **0.1.0 is een webbundel, desktop blijft zelf-bouwen-uit-de-bron.** ## Wat het níét belooft `SHA256SUMS` is geen handtekening, en de teksten zeggen dat met zoveel woorden. De lijst laat je nákijken; uit zichzelf bewijst hij niets. De controle die wél iets zegt is de sha256 van `SHA256SUMS` afzetten tegen de aankondiging, via een ander kanaal — en ook dáár staat de grens bij: het vangt een beschadigde download, een gewijzigde spiegel en een herhost, níet een compromittering van onze eigen publicatieketen. Daar helpt alleen een handtekening of een reproduceerbare build tegen, en die hebben we vandaag geen van beide. Die kernzin staat als constante in de code met een test eromheen, zodat niemand hem later stelliger maakt dan hij is. ## Bewakerreview Gedraaid vóór de poort, want dit raakt publieke beloftes. Twee blokkerende bevindingen, beide nagemeten en verholpen in `908c9719`: 1. **Geen bronaanwijzing in de bundel** (EUPL art. 5). De repo-URL stond er alleen in `.well-known/security.txt` — een beveiligingscontactbestand dat een herhoster door zijn eigen vervangt. → `SOURCE.md`. 2. **`.last_build_id` werd mee verzegeld.** De inhoud is een md5 over onder meer het absolute pad van de uitvoermap op de bouwmachine. Wie zelf bouwt kreeg daardoor gegarandeerd een andere digest dan de aankondiging, bij byte-identieke bron — de ene controle die een zelf-bouwer een onafhankelijk oordeel geeft, stond structureel op rood. → eruit vóór het hashen, en de claim "sorteren maakt de lijst reproduceerbaar" is teruggebracht tot wat sorteren wérkelijk doet. Vier kleinere bevindingen zijn in dezelfde ronde verwerkt: de bescheidenheidsformulering van `checksumUitleg`, de grens van het aankondigingskanaal, de vertrouwensruil van een gehoste webapp tegenover een binair (die stond als "geen probleem" opgeschreven terwijl hij juist de mínst soevereine vorm is), en een standaardrecept voor "er is niets bíjgekomen" dat geen Dart-toolchain vraagt. ## Getoetst - `make check` groen. - `make check-web` op een echt gebouwde bundel: 134 bestanden, hardening OK, artefacten OK. - `shasum -a 256 -c SHA256SUMS` leest de lijst en wordt rood zodra er één byte wijzigt. - Het `diff`-recept dat de documentatie geeft levert niets op een schone bundel en wijst een gepland extra bestand aan. - 17 tests in `test/pack_web_release_test.dart`, elke klacht apart rood gezien. **Niet gedraaid:** `make check-secrets` en `make sast` — gitleaks, trufflehog en semgrep staan geen van drieën op deze machine (`make check-secrets` breekt af op "gitleaks not found"). DAST evenmin. Deze wijziging voegt geen sleutel, geen netwerkpad en geen afhankelijkheid toe, maar de eis is daarmee niet gehaald en dat hoort hier te staan. ## Buiten scope `version.json` en de SBOM zeggen `0.2.0+1` terwijl de nieuwe teksten over 0.1.0 gaan. Dat is #629 en blijft daar. Closes #520
Een bundel die je aan iemand anders geeft is niet alleen de app. `LICENSE.md`
en `THIRD_PARTY_NOTICES.md` lagen er niet naast, terwijl die voorwaarden juist
de afspraak zijn waaronder de afhankelijkheden zelf meereizen — zonder hen mag
de ontvanger het ding niet doorgeven. De SBOM lag er al, met twee `cp`-regels
in de Makefile.

`tool/pack_web_release.dart` doet nu alle drie, en sluit af met een `SHA256SUMS`
over de afgeronde bundel. Dat het één stap is en niet een paar losse regels, is
de hele reden: de lijst moet over de bundel gaan zoals die de deur uit gaat,
dus ná het laatste bestand dat erbij komt. Zolang kopiëren en hashen op twee
plekken staan, komt er een dag waarop iemand er iets tussen schuift en de lijst
stil onvolledig wordt.

Het formaat is dat van `sha256sum`, zodat `shasum -a 256 -c SHA256SUMS`
volstaat en er geen OciDeck-eigen gereedschap voor nodig is — een eigen formaat
zou een eigen werktuig vragen, en dan controleert niemand het. `--check` loopt
een klaargezette bundel na en klaagt óók over een bestand dat er onaangekondigd
bíj is gekomen; dat is het geval dat er in de praktijk toe doet.

Getoetst op een nagebouwde bundel in een tijdelijke map (elke klacht apart rood
gezien) én tegen de echte boom: `make check-web` gedraaid, 134 bestanden,
`shasum -c` leest de lijst en wordt rood zodra je één byte wijzigt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
docs(release): schrijf op wat met de bundel meereist, hoe je hem nakijkt, en dat 0.1.0 web-only is (#520)
Some checks failed
CI / Gate (Linux) · Format · Analyze · Coverage (push) Has been cancelled
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Web hardening (push) Has been cancelled
CI / Docs links (push) Has been cancelled
CI / Supply-chain (Trivy · advisory) (push) Has been cancelled
6ec7774b1b
Twee dingen die zonder tekst geen besluit zijn.

**Verificatie.** BUILD.md krijgt de commando's (`shasum -a 256 -c SHA256SUMS`)
en, belangrijker, de grens eromheen: dit toont dat je kopie volledig en
onbeschadigd is, het is géén handtekening. Wie de bundel kan vervangen, kan de
lijst vervangen. De controle die wél iets zegt is de sha256 van `SHA256SUMS`
zelf vergelijken met de aankondiging, via een ander kanaal dan de download.
Die zin staat als constante in de code en wordt door een test bewaakt, zodat
niemand hem later stelliger maakt dan hij is.

**Web-only.** Het besluit van 22-07 stond alleen in issue #520 en nergens in de
gepubliceerde tekst. KNOWN_LIMITATIONS.md zegt nu waarom macOS, Windows en
Linux zelf-bouwen-uit-de-bron blijven — ad-hoc ondertekening zonder hardened
runtime betekent dat een gedownloade .app op andermans machine überhaupt niet
start, en notarisatie vereist die hardened runtime — als positie, niet als
plaatshouder voor een excuus later.

HOSTING.md noemt de vier artefacten die bereikbaar moeten blijven; CHECKS.md
beschrijft wat `make check-web` er sinds deze tak bij controleert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fix(release): bronaanwijzing erbij, machinegebonden bestand eruit (#520)
Some checks failed
CI / Gate (Linux) · Format · Analyze · Coverage (push) Failing after 21s
CI / Docs links (push) Failing after 24s
CI / Web hardening (push) Failing after 27s
CI / Supply-chain (Trivy · advisory) (push) Failing after 24s
CI / Gate (Linux) · Format · Analyze · Coverage (pull_request) Failing after 24s
CI / Web hardening (pull_request) Failing after 22s
CI / Docs links (pull_request) Failing after 22s
CI / Supply-chain (Trivy · advisory) (pull_request) Failing after 28s
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Test (macos-latest) (pull_request) Has been cancelled
CI / Test (windows-latest) (pull_request) Has been cancelled
908c9719dd
Twee bevindingen uit de bewakerreview op deze tak, allebei nagemeten voor ik
ze aannam.

**De bundel reisde zonder bronaanwijzing.** `main.dart.js` is gecompileerd, en
EUPL-1.2 artikel 5 vraagt bij het distribueren *of communiceren* van het Werk om
de broncode of een aanwijzing waar die staat — artikel 1 rekent hosten
uitdrukkelijk tot communiceren. De repo-URL stond in de hele bundel alleen in
`.well-known/security.txt` (een beveiligingscontactbestand, dat een herhoster
door zijn eigen vervangt) en in de meegebundelde app-documentatie. De ontvanger
kreeg dus onleesbare JavaScript met een licentie eronder die hem het recht geeft
te bestuderen en aan te passen, zonder route om dat te doen. `SOURCE.md` reist
nu mee en zegt ook tegen de herhoster dat artikel 5 óók voor hem geldt.

**`.last_build_id` werd mee verzegeld.** Dat is een intern markeringsbestand van
Flutter; de inhoud is een md5 over onder meer het absolute pad van de uitvoermap
op de bouwmachine. Wie zelf bouwt — precies wat KNOWN_LIMITATIONS aanraadt —
kreeg daardoor gegarandeerd een andere `SHA256SUMS` en dus een andere digest dan
de aankondiging, bij byte-identieke bron. De ene controle die de zelf-bouwer een
onafhankelijk oordeel geeft, stond structureel op rood om een reden die niets
met de code te maken had. Het bestand gaat er nu uit vóór het hashen.

Daarmee sneuvelde ook een claim die er stond: sorteren maakt de *volgorde*
bepaald, niet de build reproduceerbaar. Reproduceerbaarheid is hier niet
getoetst en wordt nu niet meer beweerd.

Nagemeten op de echt gebouwde bundel: `.last_build_id` weg uit map én lijst,
`SOURCE.md` aanwezig, en het `diff`-recept dat de documentatie nu geeft levert
niets op een schone bundel en wijst een geplant bestand aan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
brenno merged commit 0c9ffc2341 into main 2026-07-22 18:10:12 +00:00
Sign in to join this conversation.
No description provided.