feat(collab): cryptografisch herkomstbewijs op het verspreide deck (#978 Blok C) #1083

Merged
brenno merged 6 commits from feat/collab-provenance-978 into main 2026-08-01 15:53:58 +00:00
Owner

#978 Fase 2, Blok C — cryptografisch herkomstbewijs (laatste blok)

De eigenaar kan een afgerond deck met de samenwerkingsidentiteit ondertekenen (Ed25519 over de zegelhash); een ontvanger die die identiteit via de vingerafdruk verifieerde (Blok A), ziet dat dít exacte deck van die persoon komt. Hiermee is het evaluatiepunt van #978/§10 bereikt.

Machinerie (getest, gereviewd akkoord)

  • collab_crypto.dart: signProvenance (provenance-scoped, domeingescheiden preimage ["ocideck-provenance-v1",form,algo,hash,signedAt] — geen ruwe-bytes-oracle), verifyProvenance/provenancePreimage.
  • ProvenanceSignature-model, Deck.provenance, SealRecord + SealCodec provenance-sleutel (versie NIET verhoogd; kapot blok sleept het zegel niet mee).
  • provenance_service.dart: signDeckProvenance + verifyDeckProvenanceProvenanceStatus (none/invalid/contentChanged/notVerifiableHere/valid/confirmed; confirmed alleen bij een gepinde identiteit).
  • Test vector die de exacte preimage-bytes pint.

UI

  • Commandopalet-actie Herkomst ondertekenen (afgerond+opgeslagen deck + Matrix-account → laadt device-keys, tekent, opslaan schrijft de .seal.json).
  • Statusbadge in de statusbalk (async verify): bevestigd/ondertekend/gewijzigd na ondertekenen/ongeldig/niet-hier-te-controleren. Buiten een sessie zonder pin-check → "ondertekend, nog niet geverifieerd".
  • DeckNotifier.applyProvenance, CollabTrustStore.isIdentityPinned. UI-acties in een eigen part-bestand provenance_actions.dart (grootte-ratchets).

Formaat & docs

.md onaangeroerd; het blok woont in .seal.json (FILE_FORMAT §6.6 gepromoveerd van "planned" naar feitelijke beschrijving + verify-recept). Het is herkomstbewijs, GEEN eIDAS-handtekening — geen non-repudiation-claim. SOURCE_MAP/CHANGELOG/PROVENANCE_SIGNATURE.md bijgewerkt.

Poort & review

make check groen (in geïsoleerde worktree op verse main); make check-secrets + make sast schoon. Geen dependency (geen SBOM). 14 nieuwe teksten in 31 talen. Review: bewaker + security-architect akkoord — alle §8-ontwerpvoorwaarden aantoonbaar in de code (provenance-scoped signer, defensieve decode, geen versie-bump, één crypto-file, geen valse authorship-claim). Drie klasse-/bestandsbasislijnen minimaal verhoogd na extractie naar het part-bestand.

## #978 Fase 2, Blok C — cryptografisch herkomstbewijs (laatste blok) De eigenaar kan een afgerond deck met de samenwerkingsidentiteit **ondertekenen** (Ed25519 over de zegelhash); een ontvanger die die identiteit via de vingerafdruk verifieerde (Blok A), ziet dat dít exacte deck van die persoon komt. Hiermee is het evaluatiepunt van #978/§10 bereikt. ### Machinerie (getest, gereviewd akkoord) - `collab_crypto.dart`: `signProvenance` (provenance-scoped, domeingescheiden preimage `["ocideck-provenance-v1",form,algo,hash,signedAt]` — geen ruwe-bytes-oracle), `verifyProvenance`/`provenancePreimage`. - `ProvenanceSignature`-model, `Deck.provenance`, `SealRecord` + `SealCodec` `provenance`-sleutel (versie NIET verhoogd; kapot blok sleept het zegel niet mee). - `provenance_service.dart`: `signDeckProvenance` + `verifyDeckProvenance` → `ProvenanceStatus` (none/invalid/contentChanged/notVerifiableHere/valid/confirmed; confirmed alleen bij een gepinde identiteit). - Test vector die de exacte preimage-bytes pint. ### UI - Commandopalet-actie **Herkomst ondertekenen** (afgerond+opgeslagen deck + Matrix-account → laadt device-keys, tekent, opslaan schrijft de `.seal.json`). - Statusbadge in de statusbalk (async verify): bevestigd/ondertekend/gewijzigd na ondertekenen/ongeldig/niet-hier-te-controleren. Buiten een sessie zonder pin-check → "ondertekend, nog niet geverifieerd". - `DeckNotifier.applyProvenance`, `CollabTrustStore.isIdentityPinned`. UI-acties in een eigen part-bestand `provenance_actions.dart` (grootte-ratchets). ### Formaat & docs `.md` onaangeroerd; het blok woont in `.seal.json` (FILE_FORMAT §6.6 gepromoveerd van "planned" naar feitelijke beschrijving + verify-recept). Het is *herkomstbewijs*, GEEN eIDAS-handtekening — geen non-repudiation-claim. SOURCE_MAP/CHANGELOG/PROVENANCE_SIGNATURE.md bijgewerkt. ### Poort & review `make check` groen (in geïsoleerde worktree op verse main); `make check-secrets` + `make sast` schoon. Geen dependency (geen SBOM). 14 nieuwe teksten in 31 talen. Review: bewaker + security-architect **akkoord** — alle §8-ontwerpvoorwaarden aantoonbaar in de code (provenance-scoped signer, defensieve decode, geen versie-bump, één crypto-file, geen valse authorship-claim). Drie klasse-/bestandsbasislijnen minimaal verhoogd na extractie naar het part-bestand.
De format+crypto-kern van het herkomstbewijs (ontwerp PROVENANCE_SIGNATURE.md):
- collab_crypto: signProvenance() (provenance-scoped, domeingescheiden preimage
  via jsonEncode-array — géén ruwe-bytes-oracle) + top-level verifyProvenance()
  en provenancePreimage(); kProvenancePreimageTag = 'ocideck-provenance-v1'.
- ProvenanceSignature-model (alg/preimage/identityKey/signature/signedAt),
  defensieve fromJson die nooit gooit.
- Deck.provenance + SealRecord + SealCodec 'provenance'-sleutel, zónder de
  sidecar-versie te verhogen (oudere build negeert de sleutel); een kapot
  herkomstbewijs sleept het omringende zegel niet mee.
- Tests incl. test vector die de exacte preimage-bytes pint.

Nog geen UI en geen ondertekenknop — dat is de volgende slice.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
provenance_service.dart: signDeckProvenance() tekent een verzegeld+opgeslagen
deck (over sealHash) met de samenwerkingsidentiteit; verifyDeckProvenance() geeft
een ProvenanceStatus (none/invalid/contentChanged/notVerifiableHere/valid/
confirmed) — confirmed alleen als de identiteit gepind is (Blok A), anders valid.
Dunne lijm over collab_crypto (de enige crypto-file) en document_integrity.

Docs: FILE_FORMAT §6.6 promoveert het provenance-blok van 'planned' naar de
feitelijke beschrijving (met verify-recept), SOURCE_MAP registreert de twee
nieuwe libs, PROVENANCE_SIGNATURE.md staat op 'deels geïmplementeerd', CHANGELOG.

De onderteken-knop en statusweergave in de UI volgen als laatste slice.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Onderteken-actie in het commandopalet (afgerond+opgeslagen deck + Matrix-account
→ laadt device-keys, signDeckProvenance, opslaan schrijft de .seal.json).
Statusbadge in de statusbalk (async verify): bevestigd/ondertekend/gewijzigd na
ondertekenen/ongeldig/niet-hier-te-controleren; buiten een sessie zonder
pin-check, dus 'ondertekend, nog niet geverifieerd'. DeckNotifier.applyProvenance
+ CollabTrustStore.isIdentityPinned. Badge-mapping als publieke functie getest;
applyProvenance en isIdentityPinned getest.

Nog te doen in deze slice: 31 vertalingen (spec) — daarna poort + landen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
14 nieuwe teksten voor de herkomst-ondertekening en statusbadge in 31 talen.
Toon: herkomst/ondertekenen, geen juridische handtekening.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
runProvenanceSigning + provenanceSignCommands verhuizen naar
lib/widgets/shell/provenance_actions.dart (part of app_shell), zodat de zware
logica niet meetelt voor de grootte-ratchets van _MainLayoutState en het
commandopalet. Drie basislijnen minimaal verhoogd voor de resterende bedrading
(imports/part-directive, sign-delegator, applyProvenance). SOURCE_MAP bijgewerkt.
context.mounted-guards i.p.v. een mounted-callback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
test(collab): dek provenance_actions (guard + palet-command) (#978 Blok C)
All checks were successful
scans / scans (pull_request) Successful in 3m39s
11550ab6f8
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
brenno merged commit 3824a51700 into main 2026-08-01 15:53:57 +00:00
Sign in to join this conversation.
No description provided.