cipher/migrations/0001_init.sql
maverick 360bfeb5ab Cipher: E2E encrypted messenger scaffold (Signal Protocol + Cloudflare)
- Hono Worker: auth, key directory (X3DH prekey bundles), message relay, R2 media
- Mailbox Durable Object: WebSocket delivery + offline ciphertext queue
- PWA client: libsignal (vendored), IndexedDB key store, chat UI, media E2E
- Server only ever holds public keys + ciphertext; private keys stay on device

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 01:56:59 +10:00

56 lines
2.4 KiB
SQL

-- Cipher schema. The server is a "dumb" key directory + relay.
-- It stores ONLY public keys and ciphertext. Private keys never leave the client.
-- A user account. Identified by username; discoverable by other users.
CREATE TABLE users (
id TEXT PRIMARY KEY, -- uuid
username TEXT NOT NULL UNIQUE, -- lowercase handle, e.g. "alice"
display_name TEXT NOT NULL,
pw_hash TEXT NOT NULL, -- PBKDF2(password) — account auth only, unrelated to E2E keys
pw_salt TEXT NOT NULL,
created_at INTEGER NOT NULL
);
CREATE INDEX idx_users_username ON users(username);
-- A device belonging to a user. Each device has its own Signal identity.
-- Multi-device: a user may register several (phone, desktop) via QR linking.
CREATE TABLE devices (
id TEXT PRIMARY KEY, -- uuid
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
registration_id INTEGER NOT NULL, -- Signal registrationId
identity_key TEXT NOT NULL, -- base64 public identity key
signed_prekey_id INTEGER NOT NULL,
signed_prekey_pub TEXT NOT NULL, -- base64
signed_prekey_sig TEXT NOT NULL, -- base64 signature over signed_prekey_pub
created_at INTEGER NOT NULL,
last_seen INTEGER NOT NULL
);
CREATE INDEX idx_devices_user ON devices(user_id);
-- One-time prekeys. Server hands one out per session-init request, then deletes it.
CREATE TABLE one_time_prekeys (
device_id TEXT NOT NULL REFERENCES devices(id) ON DELETE CASCADE,
prekey_id INTEGER NOT NULL,
prekey_pub TEXT NOT NULL, -- base64
PRIMARY KEY (device_id, prekey_id)
);
CREATE INDEX idx_otk_device ON one_time_prekeys(device_id);
-- Bearer auth sessions (account-level). Token proves control of the account.
CREATE TABLE sessions (
token TEXT PRIMARY KEY, -- random opaque token
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
device_id TEXT NOT NULL REFERENCES devices(id) ON DELETE CASCADE,
created_at INTEGER NOT NULL,
expires_at INTEGER NOT NULL
);
CREATE INDEX idx_sessions_user ON sessions(user_id);
-- Web Push subscriptions for wake-on-message notifications (endpoint is opaque).
CREATE TABLE push_subs (
device_id TEXT PRIMARY KEY REFERENCES devices(id) ON DELETE CASCADE,
endpoint TEXT NOT NULL,
p256dh TEXT NOT NULL,
auth TEXT NOT NULL,
created_at INTEGER NOT NULL
);