-- Inou Database Schema -- Created: 2025-12-29 -- All IDs are 64-bit integers (hash of UUID) -- All timestamps are Unix epoch (INTEGER) -- String fields are encrypted unless noted -------------------------------------------------------------------------------- -- ENUMS (defined in code, documented here) -------------------------------------------------------------------------------- -- sex (ISO 5218): 0=unknown, 1=male, 2=female, 9=not_applicable -- relation: 0=self, 1=parent, 2=child, 3=spouse, 4=sibling, 5=caregiver, 6=medical_professional, 7=other -- status: 0=active, 1=deleted, 2=pending, 3=revoked, 4=processed, 5=in_review, ... -------------------------------------------------------------------------------- -- DOSSIERS -------------------------------------------------------------------------------- CREATE TABLE dossiers ( dossier_id INTEGER PRIMARY KEY, email_hash TEXT UNIQUE, -- plaintext, for lookup email TEXT, -- encrypted name TEXT, -- encrypted date_of_birth DATE, -- plaintext sex INTEGER DEFAULT 0, -- enum phone TEXT, -- encrypted language TEXT DEFAULT 'en', -- plaintext timezone TEXT, -- plaintext auth_code INTEGER, -- 6-digit code auth_code_expires_at INTEGER, -- epoch last_login INTEGER, -- epoch invited_by_dossier_id INTEGER, -- FK created_at INTEGER -- epoch ); CREATE UNIQUE INDEX idx_dossiers_email_hash ON dossiers(email_hash); -------------------------------------------------------------------------------- -- DOSSIER ACCESS (sharing permissions) -------------------------------------------------------------------------------- CREATE TABLE dossier_access ( accessor_dossier_id INTEGER, -- who has access target_dossier_id INTEGER, -- whose dossier relation INTEGER DEFAULT 0, -- enum is_care_receiver INTEGER DEFAULT 0, -- boolean can_edit INTEGER DEFAULT 0, -- boolean status INTEGER DEFAULT 0, -- enum created_at INTEGER, -- epoch accessed_at INTEGER, -- epoch PRIMARY KEY (accessor_dossier_id, target_dossier_id) ); CREATE INDEX idx_access_accessor ON dossier_access(accessor_dossier_id); CREATE INDEX idx_access_target ON dossier_access(target_dossier_id); -------------------------------------------------------------------------------- -- ENTRIES (all data: imaging, labs, vitals, genome, uploads, etc.) -------------------------------------------------------------------------------- CREATE TABLE entries ( entry_id INTEGER PRIMARY KEY, dossier_id INTEGER NOT NULL, -- FK parent_id INTEGER, -- FK self-ref (hierarchy) product_id INTEGER, -- FK to products (optional) category TEXT NOT NULL, -- encrypted, deterministic type TEXT NOT NULL, -- encrypted, deterministic value TEXT, -- encrypted ordinal INTEGER DEFAULT 0, -- sort order within parent timestamp INTEGER NOT NULL, -- epoch timestamp_end INTEGER, -- epoch (for ranges) status INTEGER DEFAULT 0, -- enum tags TEXT, -- encrypted data TEXT -- encrypted JSON ); CREATE INDEX idx_entries_dossier_category_type ON entries(dossier_id, category, type); CREATE INDEX idx_entries_dossier_timestamp ON entries(dossier_id, timestamp); CREATE INDEX idx_entries_parent ON entries(parent_id, ordinal); -------------------------------------------------------------------------------- -- AUDIT -------------------------------------------------------------------------------- CREATE TABLE audit ( audit_id INTEGER PRIMARY KEY, dossier_id INTEGER, -- who performed action action TEXT, -- encrypted target_dossier_id INTEGER, -- affected dossier (if applicable) details TEXT, -- encrypted JSON timestamp INTEGER -- epoch ); CREATE INDEX idx_audit_dossier_timestamp ON audit(dossier_id, timestamp); CREATE INDEX idx_audit_target_timestamp ON audit(target_dossier_id, timestamp); -------------------------------------------------------------------------------- -- OBJECTS (binary files) -- Stored on disk at: /objects/{dossier_id}/{aa}/{bb}/{entry_id} -- where aa/bb are first 4 chars of entry_id for sharding --------------------------------------------------------------------------------