93 lines
4.5 KiB
SQL
93 lines
4.5 KiB
SQL
-- 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
|
|
--------------------------------------------------------------------------------
|