Some checks failed
Test / test (push) Has been cancelled
Cross-platform vectors / TypeScript vectors (bun) (push) Has been cancelled
Cross-platform vectors / Kotlin vectors (gradle) (push) Has been cancelled
Docker build and publish / docker (push) Has been cancelled
Publish / publish (push) Has been cancelled
V3.1 → V3.12 consolidated and tagged for the first GA release. Wire format unchanged from 0.4.x — 4.0 peers interoperate with 0.4.x peers byte-for-byte. The version bump is semantic: audit-cycle complete, opt-in surface fully exposed, threat model refreshed for every new surface. Highlights: - All 24 @shade/* packages bumped to 4.0.0 in lockstep. - CHANGELOG 4.0.0 section is the canonical manifest of what landed. - THREAT-MODEL extended (§10 fingerprint gates, §11 WebRTC P2P, §12 Web-Worker boundary) + residual-risks table refreshed. - OpenAPI now covers all 27 routes: prekey, transfer, KT, inbox, bridge, observer, /metrics, /healthz, /ready. - MIGRATION 0.3.x → 4.0 documented + smoke-tested against shade migrate-storage on a real SQLite DB. - docs/audit/REVIEW-BUNDLE.md + SCOPE.md ready for external reviewer. - scripts/soak.ts harness for the GA-stable 2-week soak window. - All V*.md plans archived under docs/archive/ with Status: Done. - Voice/Video carved out into V5.0; 4.0 audit focuses on the frozen non-realtime stack. Tests: TS 1000/1000 + Kotlin 11/11 cross-platform vectors green. Docker: gt.zyon.no/stian/shade-prekey:4.0.0 builds and reports version 4.0.0 on /health. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
148 lines
4.2 KiB
Markdown
148 lines
4.2 KiB
Markdown
# Shade V3.3 — Fingerprint Gates & Trust UX
|
||
|
||
**Status:** Done
|
||
**Effort:** M (2–4 uker)
|
||
**Forrige:** V3.1
|
||
**Adresserer:** V2.3 §1B
|
||
**Implementert:** se `docs/trust-ux.md`
|
||
|
||
---
|
||
|
||
## Mål
|
||
|
||
Gjør safety numbers **handlingspålagte** — ikke bare synlige — i flyt der
|
||
MITM-risikoen er reell. I dag finnes `FingerprintCompare`-widget og
|
||
`requireFingerprintVerifiedFor` i `@shade/files`, men hovedkjernen
|
||
(`Shade.send`, first-large-file, backup-import) har ingen automatisk gate.
|
||
Resultat: alert-fatigue-fri, men også gate-fri.
|
||
|
||
Dette legger inn **eksplisitt blokkerende verifisering** på et lite antall
|
||
kritiske hendelser, plus widget-støtte for å eksponere det i UI.
|
||
|
||
---
|
||
|
||
## Scope
|
||
|
||
### Inn — kritiske hendelser
|
||
|
||
1. **Før første store fil** — `Shade.upload` over en bytes-terskel uten
|
||
verifisert peer.
|
||
2. **Før backup-import** — `Shade.importBackup` blokkerer til peer (eller egen
|
||
identitet) er bekreftet.
|
||
3. **Ny enhet med rotert identitet** — `acceptIdentityChange` blokkerer på
|
||
første bruk inntil verifisert.
|
||
4. **Før `@shade/inbox` fan-out** (V3.6) — gate per mottaker.
|
||
|
||
### Inn — APIer
|
||
|
||
- `Shade.beforeFirstLargeFile(threshold, handler)` — appen får mulighet til å
|
||
vise modal og returnere bekreftelse.
|
||
- `Shade.beforeBackupImport(handler)` — samme mønster.
|
||
- `Shade.beforeNewDeviceTrust(handler)` — ditto.
|
||
- `Shade.markPeerVerified(address)` / `Shade.isPeerVerified(address)` —
|
||
persistent state.
|
||
|
||
### Inn — widgets
|
||
|
||
- `<FingerprintGate />` — render-prop wrapper som blokkerer barn til
|
||
verifisert.
|
||
- `<FingerprintCompare />` utvides med "kopier OOB-tekst" + "jeg har
|
||
verifisert".
|
||
|
||
### Ut
|
||
|
||
- "Tving alle peers verifisert før hver melding" — alert fatigue.
|
||
- Cross-device sync av verified-state (kommer evt. via V3.6 inbox).
|
||
|
||
---
|
||
|
||
## Design
|
||
|
||
### Persistent verified-state
|
||
|
||
Ny tabell `peer_verifications`:
|
||
|
||
```sql
|
||
CREATE TABLE peer_verifications (
|
||
peer_address TEXT PRIMARY KEY,
|
||
fingerprint TEXT NOT NULL,
|
||
verified_at INTEGER NOT NULL,
|
||
verified_by TEXT, -- "user" | "transitive" | "tofu-after-warning"
|
||
identity_version INTEGER NOT NULL -- knytter verifikasjon til identity-rotasjon
|
||
);
|
||
```
|
||
|
||
Når peer roterer identitet → `identity_version` bumper → verifikasjon "ugyldig"
|
||
til ny verifisering.
|
||
|
||
### Hook-flyt
|
||
|
||
```text
|
||
shade.upload(peer, file)
|
||
│
|
||
├─ if !verified(peer) AND file.size > threshold
|
||
│ │
|
||
│ └─ await beforeFirstLargeFileHandler(peer, fingerprint)
|
||
│ ├─ true → markPeerVerified(peer); proceed
|
||
│ └─ false → throw FingerprintNotVerifiedError
|
||
│
|
||
└─ proceed
|
||
```
|
||
|
||
---
|
||
|
||
## Leveranser
|
||
|
||
### Kode
|
||
|
||
- `@shade/core` — `peer_verifications`-tabell + storage methods.
|
||
- `@shade/sdk` — gate-hooks + `markPeerVerified` / `isPeerVerified`.
|
||
- `@shade/widgets` — `<FingerprintGate />`, utvidet `<FingerprintCompare />`.
|
||
|
||
### Tester
|
||
|
||
- Unit: gate kalles, ikke kalles, retur false → throw, retur true → proceed.
|
||
- Integration: fil < threshold går gjennom uten gate; fil > threshold
|
||
blokkerer.
|
||
- Identity-rotasjon ugyldiggjør verifikasjon.
|
||
- Backup-import blokkerer.
|
||
|
||
### Dokumentasjon
|
||
|
||
- `docs/trust-ux.md` — guide til hvilke gates som finnes og når de bør tunes.
|
||
|
||
---
|
||
|
||
## Akseptansekriterier
|
||
|
||
- [ ] Gate kan ikke bypasses ved å nulle `threshold` ut — minimum gate finnes
|
||
alltid for backup-import og new-device.
|
||
- [ ] App uten registrerte gates får sane defaults (logger en warning, men
|
||
kjører — ikke krasj).
|
||
- [ ] Identity-rotasjon resetter verifikasjon i en testet ende-til-ende-flow.
|
||
- [ ] Widget kan rendres SSR uten å trigge runtime-gate.
|
||
|
||
---
|
||
|
||
## Avhengigheter
|
||
|
||
- V3.1 — threat-matrise oppdatert til å vise hvilke gates som dekker hvilke
|
||
rader.
|
||
|
||
---
|
||
|
||
## Risiko
|
||
|
||
- **Alert fatigue.** Hvis terskler er for lave → bruker klikker blindt.
|
||
Mitiger ved å sette default-terskler høyt (10 MiB for first-large-file)
|
||
og dokumenter justerings-guide.
|
||
- **DX-friksjon.** Apper som ikke vet om gates får uventede prompts. Mitiger
|
||
ved å logge tydelig ved første aktivering: "Shade.beforeFirstLargeFile not
|
||
configured — using default modal".
|
||
|
||
---
|
||
|
||
## Migrasjon
|
||
|
||
0.3.x apps får defaults aktivert med warning. Ingen breaking change.
|