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

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:
2026-05-03 18:35:35 +02:00
parent 8b055912b7
commit e6fdf31b49
298 changed files with 37909 additions and 256 deletions

View File

@@ -34,6 +34,45 @@ future-project (Docker container, SQLite volume) ← Any future app
Each project owns its own container, its own volume, its own observer token. Zero cross-project coupling. If one project's Shade is down, the others keep running.
## Keys vs. payloads — what this server is, and isn't
The prekey server is a **public-key directory**. It exists so a brand-
new client can find the right Ed25519 + X25519 bundle to start an
X3DH handshake with a peer it has never talked to. After that, the
peers ratchet directly.
What lives on this server:
- Identity public keys
- Signed prekey + one-time prekey bundles
- Activity timestamps (used by stale cleanup)
- Operator metadata: `/health`, `/metrics`, `/openapi.yaml`,
`/shade-observer/*`
What never lives on this server:
- **Message plaintext.** Ratchet envelopes flow peer-to-peer.
- **Transfer chunks.** `@shade/transfer` POSTs ciphertext directly to
the receiver's `/v1/transfer/:streamId/chunk` route — not here.
- **Identity private keys** or **session state**. Both are device-
local.
- **Resume secrets** for in-flight transfers. Encrypted under a
device-key derived from the identity signing key, never uploaded.
This is the bright line that lets you deploy one shared prekey
container per project even when consumer apps don't trust each other:
the worst a compromised prekey server can do is hand out a fake
bundle (MITM at first contact). Out-of-band fingerprint comparison
detects this — see `THREAT-MODEL.md § 2` and the `getIdentityFingerprint()`
API.
For deployment-time gates (TLS, backup, observer-token rotation, log
level, secret rotation) see
[`docs/PRODUCTION-CHECKLIST.md`](../../docs/PRODUCTION-CHECKLIST.md).
For the wire contract — including the peer-served
`/v1/transfer/*` and `ShadeTransferAuthenticator` security scheme —
see [`openapi.yaml`](./openapi.yaml).
## Environment variables
| Var | Default | Description |