release(v4.0.0): Shade GA — V3.x consolidation + audit prep
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
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>
This commit is contained in:
146
docs/archive/V3.2.md
Normal file
146
docs/archive/V3.2.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# Shade V3.2 — At-Rest Storage Encryption
|
||||
|
||||
**Status:** Implementert (0.4.0) — `@shade/storage-encrypted`, `@shade/keychain`,
|
||||
`shade migrate-storage`, `shade rotate-storage-key`
|
||||
**Effort:** L (4–8 uker)
|
||||
**Forrige:** V3.1
|
||||
**Adresserer:** V2.1 §2
|
||||
|
||||
---
|
||||
|
||||
## Mål
|
||||
|
||||
Opt-in beskyttelse av sensitiv state — identity-nøkler, session-state, valgfri
|
||||
stream-resume-secret — med nøkler som **ikke** ligger i klartekst i databasen.
|
||||
Trusselmodellen sier i dag eksplisitt at en stjålet DB eksponerer private
|
||||
nøkler; dette løser det for deploys som velger å aktivere det.
|
||||
|
||||
---
|
||||
|
||||
## Scope
|
||||
|
||||
### Inn
|
||||
|
||||
- Ny `EncryptedStorageProvider`-wrapper som dekorerer `SQLiteStorage` /
|
||||
`PostgresStorage`.
|
||||
- Per-rad AES-256-GCM på sensitive felter (`identity_*`, `session_*`,
|
||||
valgfritt `stream_state.streamSecret`).
|
||||
- KDF-pluggin (default `scrypt` fra `@noble/hashes`) for passphrase-basert
|
||||
master-nøkkel.
|
||||
- Tre nøkkelkilder ut av boksen:
|
||||
1. **Passphrase + KDF** — utvikler oppgir secret ved oppstart.
|
||||
2. **OS keychain** — macOS Keychain, Linux libsecret, Windows Credential
|
||||
Vault (Node-only).
|
||||
3. **App-injected key** — appens egen kode forsyner 32-byte nøkkel (mest
|
||||
fleksibel).
|
||||
- Migrasjons-CLI: `shade migrate-storage --encrypt --key-source=...`.
|
||||
- Trusselmodell-oppdatering: "når enabled, hva er fortsatt udekket" — memory
|
||||
compromise, swap, runtime-tap.
|
||||
|
||||
### Ut
|
||||
|
||||
- Browser/IndexedDB at-rest (egen pakke, vurderes etter V3.8).
|
||||
- HSM/Secure Enclave (separate driver senere).
|
||||
- "Always-on by default" — vi flyger opt-in for å ikke bryte eksisterende
|
||||
deploys.
|
||||
|
||||
---
|
||||
|
||||
## Design
|
||||
|
||||
### Krypteringsenhet
|
||||
|
||||
- Per-rad AEAD: `nonce(12) || ciphertext || tag(16)`.
|
||||
- `nonce = HKDF(rowKey, "shade-row-nonce-v1" || tableName || pk)[..12]` —
|
||||
deterministisk per (tabell, pk) for å unngå nonce-reuse uten å lagre nonce
|
||||
separat. Endring av (tabell, pk) → re-encryption.
|
||||
- AAD binder `tableName || columnName || pk` så feltombytting blokkeres.
|
||||
|
||||
### Nøkkelhierarki
|
||||
|
||||
```text
|
||||
masterKey (fra kilde — passphrase / keychain / app-injected)
|
||||
│
|
||||
├─ HKDF("shade-storage-v1") → storageKey (32 bytes)
|
||||
│ │
|
||||
│ └─ HKDF(storageKey, table || column) → fieldKey
|
||||
│
|
||||
└─ HKDF("shade-storage-version-v1") → versjonsnøkkel (rotasjon)
|
||||
```
|
||||
|
||||
### Migrasjon
|
||||
|
||||
1. CLI leser ukryptert DB.
|
||||
2. Skriver rad-for-rad-kryptering til ny `_v2`-tabell.
|
||||
3. Atomisk rename + drop gammel.
|
||||
4. Backup `.bak`-fil etterlatt i samme dir.
|
||||
|
||||
### Rotasjon
|
||||
|
||||
- `shade rotate-storage-key --new-source=...` re-krypterer med ny masterKey.
|
||||
- Online ratchet (les med gammel, skriv med ny) for store DB.
|
||||
|
||||
---
|
||||
|
||||
## Leveranser
|
||||
|
||||
### Pakker
|
||||
|
||||
- Ny modul: `@shade/storage-encrypted` (re-export over SQLite/PG).
|
||||
- Utvidelse i `@shade/cli`: `migrate-storage`, `rotate-storage-key`.
|
||||
- Hjelpe-pakke: `@shade/keychain` (Node-only, valgfri peer-dep) for OS-keychain.
|
||||
|
||||
### Tester
|
||||
|
||||
- Unit: KDF-derivasjon, nonce-determinisme, AAD-binding.
|
||||
- Integration: full lifecycle på SQLite + PG; start/stopp; krasj under
|
||||
migrasjon.
|
||||
- Tamper: bit-flip i ciphertext / AAD / nonce → dekrypterings-feil.
|
||||
- Vector-fil: kryss-sjekk masterKey → fieldKey-derivasjon mot
|
||||
`test-vectors/storage-encryption.json`.
|
||||
|
||||
### Dokumentasjon
|
||||
|
||||
- `docs/storage-encryption.md` — full guide.
|
||||
- `THREAT-MODEL.md` — ny kolonne "with at-rest enabled".
|
||||
- Migrasjonsnotat i `MIGRATION.md`.
|
||||
|
||||
---
|
||||
|
||||
## Akseptansekriterier
|
||||
|
||||
- [ ] Eksisterende ukryptert deploy fortsetter uten endringer (opt-in).
|
||||
- [ ] `shade migrate-storage --encrypt` migrerer en levende SQLite uten
|
||||
datatap, verifisert med dump-diff.
|
||||
- [ ] Rotasjon kan gjøres uten downtime > 5 s for små DB.
|
||||
- [ ] Wrong passphrase / wrong key → klar feilmelding, ikke krasj.
|
||||
- [ ] Test-vectors deles med Android-implementasjonen (V3.5 forplikter at
|
||||
vector-filen kjøres der).
|
||||
|
||||
---
|
||||
|
||||
## Avhengigheter
|
||||
|
||||
- V3.1 — `THREAT-MODEL.md` skal være lenket til testene først, så vi kan
|
||||
utvide tabellen.
|
||||
|
||||
---
|
||||
|
||||
## Risiko
|
||||
|
||||
**Datatap.** En migrasjon som krasjer halvveis kan etterlate korrupt DB.
|
||||
Mitigeres ved:
|
||||
|
||||
- Atomic-rename + `.bak`-fil.
|
||||
- Dry-run-modus (`--dry-run` validerer all dekryptering før skriving).
|
||||
- Refuser å starte hvis WAL har uncommitted writes.
|
||||
|
||||
**Nøkkeltap = totaltap.** Hvis bruker mister passphrase = ingen tilgang.
|
||||
Dokumenter klart, og pek på V3.10 (Social Recovery) som langtidsløsning.
|
||||
|
||||
---
|
||||
|
||||
## Migrasjon
|
||||
|
||||
0.3.x deploys er ukrypterte → fortsatt ukrypterte. Aktivering er én
|
||||
CLI-kommando. Backwards-kompatibel.
|
||||
Reference in New Issue
Block a user