Sterister 9ceab037ca
Some checks failed
Test / test (push) Has been cancelled
feat(observer): M-Obs 4-7 — widgets, dashboard, docs, integration example
M-Obs 4: @shade/widgets React library
- ShadeProvider context with observer URL + token + theme
- useShadeState (polling) + useShadeEvents (SSE) hooks
- 7 widgets: IdentityCard, SessionList, PrekeyStock, RecentActivity,
  ServerStatus, FingerprintCompare, WidgetCatalog (meta-widget for
  user-selectable layout with localStorage persistence)
- Self-contained CSS via inline styles, no external CSS conflicts
- Light/dark/auto theme via tokens

M-Obs 5: @shade/dashboard standalone SPA
- Vite + React app composing all widgets into a full debugger layout
- Login screen with token persistence to localStorage
- Build script copies dist/ to @shade/observer/dist/ for embedded serving
- 211 KB JS bundle (66 KB gzipped)

M-Obs 6: Documentation + integration example
- READMEs for @shade/observer and @shade/widgets
- examples/06-observer-dashboard runnable demo: spins up prekey server +
  observer, runs Alice ↔ Bob conversation loop, dashboard at :3901
- Updated root README and docker-compose.yml with observer integration

M-Obs 7: End-to-end verification
- StateAggregator now drains buffered events on subscription, so
  identity.initialized fires before observer construction are still seen
- Verified live: snapshot endpoint returns full state, dashboard serves,
  401 without auth, sessions/messages/ratchet steps all tracked

220 tests passing, 0 failures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 19:00:21 +02:00
2026-04-09 20:12:01 +02:00

Shade

End-to-end encryption library implementing the Signal Protocol (X3DH + Double Ratchet) for TypeScript/Bun. Drop into any project — frontend, backend, mobile — to get forward secrecy, post-compromise recovery, and self-healing security.

What you get

  • X3DH initial key agreement (works asynchronously via prekey bundles)
  • Double Ratchet for per-message forward secrecy and post-compromise security
  • Self-authenticated prekey server (Hono, Docker-ready) with rate limiting, metrics, health checks
  • Persistent storage backends: SQLite (zero-config) and PostgreSQL (Drizzle)
  • Identity rotation with grace period for old sessions
  • Safety numbers (Signal-style fingerprints) for out-of-band verification
  • Constant-time comparisons and memory zeroization for hardened operation
  • Binary wire format that's significantly smaller than JSON
  • Crash-safe — sessions survive container restarts, power outages, SIGKILL
  • Live observability — bundled dashboard SPA + embeddable React widgets to see what's happening between every step

Quick start

# In your project
bun add @shade/core @shade/crypto-web @shade/storage-sqlite
import { ShadeSessionManager } from '@shade/core';
import { SubtleCryptoProvider } from '@shade/crypto-web';
import { SQLiteStorage } from '@shade/storage-sqlite';

const crypto = new SubtleCryptoProvider();
const storage = new SQLiteStorage('/data/shade-client.db');

const manager = new ShadeSessionManager(crypto, storage);
await manager.initialize();

// Establish a session with a peer (after fetching their bundle)
await manager.initSessionFromBundle('bob', bobBundle);

// Encrypt
const envelope = await manager.encrypt('bob', 'Hello, encrypted world!');

// Decrypt
const plaintext = await manager.decrypt('alice', incomingEnvelope);

Architecture

                     Shade Prekey Server (Hono)
                              │
              POST /v1/keys/register (signed)
              GET  /v1/keys/bundle/:address
              POST /v1/keys/replenish (signed)
              DELETE /v1/keys/:address (signed)
                              │
        ┌─────────────────────┴─────────────────────┐
        │                                           │
    [Client A]                                  [Client B]
    ShadeSessionManager                         ShadeSessionManager
        │                                           │
        ├──── X3DH ────────────────────────────────►│
        │                                           │
        │◄──── Double Ratchet messages ────────────►│
        │                                           │
    SQLiteStorage / PostgresStorage             SQLiteStorage / PostgresStorage

Packages

Package Purpose
@shade/core Protocol logic (X3DH, Double Ratchet, session manager, errors, events)
@shade/crypto-web SubtleCrypto + @noble/curves provider, in-memory storage
@shade/storage-sqlite Persistent SQLite storage (zero-config, bun:sqlite)
@shade/storage-postgres PostgreSQL storage with Drizzle for shared databases
@shade/server Prekey server (Hono routes, auth, rate limit, health, metrics)
@shade/transport HTTP + WebSocket transport wrappers with auto-encryption
@shade/proto Compact binary wire format (smaller than JSON)
@shade/observer Live debugger backend (snapshot, SSE, dashboard) — see README
@shade/widgets Embeddable React widgets — see README
@shade/dashboard Standalone dashboard SPA bundled into the observer

Security properties

Property Description
Forward secrecy Compromising a key cannot decrypt past messages
Post-compromise security Self-heals after key compromise on next DH ratchet
Authentication Ed25519 identity signatures on prekey server writes
Replay protection ±5 minute timestamp window on signed requests
Constant-time comparisons Timing attacks on identity keys are blocked
Memory zeroization Key material is zeroed after use (best-effort in JS)
Identity verification Safety numbers (60 digits) for out-of-band comparison
Identity rotation 7-day grace period for old sessions during rotation

Documentation

Deployment

For containerized deployment (Docker/Dokploy):

services:
  shade-prekey:
    image: shade-prekey-server:latest
    ports:
      - "3900:3900"
    volumes:
      - shade-data:/data
    environment:
      - SHADE_PREKEY_DB_PATH=/data/shade-prekeys.db
volumes:
  shade-data:

The SQLite database persists to a Docker volume so all keys and prekey bundles survive restarts.

License

MIT

Description
E2EE library implementing Signal Protocol (X3DH + Double Ratchet)
Readme MIT 2.8 MiB
Languages
TypeScript 93.1%
Kotlin 6.7%
Shell 0.1%