initial commit

This commit is contained in:
Filip
2026-03-11 16:06:00 +01:00
parent b3c69053f6
commit 5fd80e6dd6
127 changed files with 39684 additions and 0 deletions

158
zaloha/schema.sql Normal file
View File

@@ -0,0 +1,158 @@
CREATE DATABASE IF NOT EXISTS encrypted_chat
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE encrypted_chat;
-- Users: identity_key is Ed25519 (32B), rsa_public_key for login challenge only
CREATE TABLE IF NOT EXISTS users (
id CHAR(36) NOT NULL PRIMARY KEY,
username VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
rsa_public_key TEXT NOT NULL,
identity_key BLOB NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
-- Devices: each user can have multiple devices
CREATE TABLE IF NOT EXISTS devices (
id CHAR(36) NOT NULL PRIMARY KEY,
user_id CHAR(36) NOT NULL,
device_name VARCHAR(255) DEFAULT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
last_seen_at DATETIME DEFAULT NULL,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
INDEX idx_devices_user (user_id)
) ENGINE=InnoDB;
-- Signed Pre-Keys (X25519, signed by Ed25519 identity key) — per device
CREATE TABLE IF NOT EXISTS signed_prekeys (
id CHAR(36) NOT NULL PRIMARY KEY,
user_id CHAR(36) NOT NULL,
device_id CHAR(36) DEFAULT NULL,
public_key BLOB NOT NULL,
signature BLOB NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
INDEX idx_spk_user_device (user_id, device_id)
) ENGINE=InnoDB;
-- One-Time Pre-Keys (consumed on use) — per device
CREATE TABLE IF NOT EXISTS one_time_prekeys (
id CHAR(36) NOT NULL PRIMARY KEY,
user_id CHAR(36) NOT NULL,
device_id CHAR(36) DEFAULT NULL,
public_key BLOB NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
INDEX idx_opk_user_device (user_id, device_id)
) ENGINE=InnoDB;
-- Conversations
CREATE TABLE IF NOT EXISTS conversations (
id CHAR(36) NOT NULL PRIMARY KEY,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
name VARCHAR(255) DEFAULT NULL,
created_by CHAR(36) DEFAULT NULL,
avatar_file VARCHAR(255) DEFAULT NULL
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS conversation_members (
conversation_id CHAR(36) NOT NULL,
user_id CHAR(36) NOT NULL,
joined_at DATETIME NULL,
PRIMARY KEY (conversation_id, user_id),
FOREIGN KEY (conversation_id) REFERENCES conversations(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB;
-- Group invitations (pending invitations to join a group)
CREATE TABLE IF NOT EXISTS group_invitations (
id CHAR(36) NOT NULL PRIMARY KEY,
conversation_id CHAR(36) NOT NULL,
user_id CHAR(36) NOT NULL,
invited_by CHAR(36) NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uq_conv_user (conversation_id, user_id),
FOREIGN KEY (conversation_id) REFERENCES conversations(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (invited_by) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB;
-- Messages: per-recipient ciphertext (Double Ratchet = each recipient has different ciphertext)
CREATE TABLE IF NOT EXISTS messages (
id CHAR(36) NOT NULL PRIMARY KEY,
conversation_id CHAR(36) NOT NULL,
sender_id CHAR(36) NOT NULL,
sender_device_id CHAR(36) DEFAULT NULL,
ratchet_header BLOB NOT NULL,
x3dh_header BLOB DEFAULT NULL,
sender_chain_id BLOB DEFAULT NULL,
sender_chain_n INT DEFAULT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at DATETIME DEFAULT NULL,
image_file_id CHAR(36) DEFAULT NULL,
FOREIGN KEY (conversation_id) REFERENCES conversations(id) ON DELETE CASCADE,
FOREIGN KEY (sender_id) REFERENCES users(id) ON DELETE CASCADE,
INDEX idx_messages_conv_created (conversation_id, created_at)
) ENGINE=InnoDB;
-- Per-recipient encrypted content — per device
-- device_id '00000000-0000-0000-0000-000000000000' = self-encrypted / legacy
CREATE TABLE IF NOT EXISTS message_recipients (
message_id CHAR(36) NOT NULL,
user_id CHAR(36) NOT NULL,
device_id CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
encrypted_content BLOB NOT NULL,
nonce BLOB NOT NULL,
ratchet_header BLOB DEFAULT NULL,
x3dh_header BLOB DEFAULT NULL,
PRIMARY KEY (message_id, user_id, device_id),
FOREIGN KEY (message_id) REFERENCES messages(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB;
-- Sender Keys for groups (distributed via pairwise ratchet) — per device
CREATE TABLE IF NOT EXISTS group_sender_keys (
conversation_id CHAR(36) NOT NULL,
sender_id CHAR(36) NOT NULL,
device_id CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
chain_id BLOB NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (conversation_id, sender_id, device_id),
FOREIGN KEY (conversation_id) REFERENCES conversations(id) ON DELETE CASCADE,
FOREIGN KEY (sender_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB;
-- Read receipts
CREATE TABLE IF NOT EXISTS message_reads (
message_id CHAR(36) NOT NULL,
user_id CHAR(36) NOT NULL,
read_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (message_id, user_id),
FOREIGN KEY (message_id) REFERENCES messages(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB;
-- User profiles
CREATE TABLE IF NOT EXISTS user_profiles (
user_id CHAR(36) NOT NULL PRIMARY KEY,
phone VARCHAR(50) DEFAULT NULL,
phone_visible TINYINT(1) NOT NULL DEFAULT 0,
email_visible TINYINT(1) NOT NULL DEFAULT 1,
location VARCHAR(255) DEFAULT NULL,
location_visible TINYINT(1) NOT NULL DEFAULT 0,
avatar_file VARCHAR(255) DEFAULT NULL,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB;
-- Image uploads
CREATE TABLE IF NOT EXISTS image_uploads (
file_id CHAR(36) NOT NULL PRIMARY KEY,
conversation_id CHAR(36) NOT NULL,
uploader_id CHAR(36) NOT NULL,
file_size BIGINT NOT NULL DEFAULT 0,
completed BOOLEAN NOT NULL DEFAULT FALSE,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (conversation_id) REFERENCES conversations(id) ON DELETE CASCADE,
FOREIGN KEY (uploader_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB;