Files
Shade/docs/audit/SCOPE.md
Sterister e6fdf31b49
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
release(v4.0.0): Shade GA — V3.x consolidation + audit prep
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>
2026-05-03 18:35:35 +02:00

3.6 KiB

Shade 4.0 — Audit Scope

A short, structural list a reviewer can scan before opening a single file. Everything here is a pointer to the deeper material in REVIEW-BUNDLE.md and the package READMEs.

In scope

  • Protocol primitives: X3DH, Double Ratchet, sender keys.
  • Wire format: 0x01 PreKeyMessage, 0x02 RatchetMessage, 0x11 StreamChunk. Length prefixes (u32) and AAD bindings.
  • Storage encryption (@shade/storage-encrypted): KDF chain, per-(table,column) DEKs, AEAD AAD layout, online re-key.
  • Recovery (@shade/recovery): Shamir over GF(2^8), AEAD-authenticated reconstruction, fingerprint gate on guardian release, share-grant / share-decline envelope schema.
  • WebRTC P2P (@shade/transport-webrtc): SDP/ICE signaling rides the ratchet; chunk frames AEAD-bound to streamId/laneId/seq; glare resolution determinism.
  • Key Transparency (@shade/key-transparency): Merkle log over pre-hashed leaves, address-sorted index, signed STH, witness cross-check, split-view detection.
  • Inbox (@shade/inbox-server): TOFU registration, per-PUT signed blobs, idempotent on (address, msgId), replay window.
  • Bridge (@shade/transport-bridge): SSE / long-poll / WS carriers; signed-query auth (no headers on EventSource).
  • Crypto in workers (@shade/crypto-web/worker): key-isolation boundary, postMessage protocol, idle terminate.
  • Trust UX gates (@shade/sdk Shade.beforeFirstLargeFile, beforeBackupImport, beforeNewDeviceTrust).

Out of scope

  • Voice / Video / Broadcast (@shade/voice etc.) — V5.0; reviewed when the package ships.
  • Build system (Vite, Rollup, Gradle wiring) — out of crypto scope.
  • App-level UI (@shade/widgets) — re-renders the primitives above; the cryptographic decisions are in the SDK / core packages the widgets consume.
  • Browser / native WebRTC stacks — we ride the platform's RTCPeerConnection and SubtleCrypto.
  • Operating system / hardware threat model — filesystem encryption, secure-enclave key storage, swap-encryption, coredump handling. Operator responsibility.

Methodology suggestions

  1. Start with THREAT-MODEL.md — every entry has a [tests:] footnote. Toggle each test off, confirm it fails; toggle the corresponding mitigation off, confirm it fails.
  2. Re-derive every KDF label from the spec; check scripts/generate-vectors.ts and the recorded vectors in test-vectors/ match.
  3. Run the cross-platform suite on both TS (bun) and Kotlin (gradle) — divergence is a vector-format bug.
  4. Audit the AEAD AAD construction at every layer:
    • Ratchet: header bytes (counter + DH pub) → AES-GCM AAD.
    • Streams: streamId || laneId || seq || isLast → AES-GCM AAD.
    • Storage: (table, column, pk) → AES-GCM AAD.
  5. Trace the boundary between the worker-side crypto thread and the main thread — confirm that no handle to a wrapped DEK or a ratcheted chain key crosses over.

Open questions for reviewer commentary

  • The witness gossip channel for V3.12 is currently in-band over the ratchet; should we cross-pin against an out-of-band log mirror in 4.x, or wait for a federated relay tier?
  • WebRTC peer-glare is resolved by lexicographic address compare — a reviewer could confirm the equivalent constructions in libsignal or Matrix and flag if our edge cases match.
  • Storage encryption uses AES-GCM with a per-row IV. The IV is random, not deterministic; reviewers should confirm the combinatorial-collision threshold matches the per-column row count bounds.