inou/docs/schema.sql

52 lines
2.5 KiB
SQL

-- ============================================================================
-- Inou Database Schema (inou.db)
-- ============================================================================
-- Medical data. Tables are NOT auto-created.
-- Use this file manually if you ever need to recreate tables.
--
-- OAuth tables are in separate auth.db (see schema-auth.sql)
-- ============================================================================
-- RBAC Access Grants
-- Stores who (grantee) can access whose (dossier) data with what permissions (ops)
CREATE TABLE IF NOT EXISTS access (
access_id TEXT PRIMARY KEY,
dossier_id TEXT, -- whose data (encrypted)
grantee_id TEXT, -- who gets access (encrypted)
entry_id TEXT, -- specific entry, or empty for dossier-wide
role TEXT NOT NULL, -- role name (Family, Doctor, etc.)
ops TEXT NOT NULL, -- operations: r=read, w=write, d=delete, m=manage
created_at INTEGER NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_access_grantee ON access(grantee_id);
CREATE INDEX IF NOT EXISTS idx_access_dossier ON access(dossier_id);
CREATE INDEX IF NOT EXISTS idx_access_entry ON access(entry_id);
-- Lab Test Properties (per LOINC code)
-- Public reference data (not PII). String fields auto-encrypted by db layer.
-- Values stored as int64 with x1,000,000 scaling for float precision.
CREATE TABLE IF NOT EXISTS lab_test (
loinc_id TEXT PRIMARY KEY, -- LOINC code e.g. "718-7"
name TEXT NOT NULL, -- English canonical e.g. "Hemoglobin"
si_unit TEXT NOT NULL, -- SI unit e.g. "g/L"
direction TEXT NOT NULL DEFAULT 'range', -- "range", "lower_better", "higher_better"
si_factor INTEGER NOT NULL DEFAULT 1000000 -- conventional→SI multiplier x1M
);
-- Lab Reference Ranges (always in SI units)
-- Synthetic PK: "loinc|source|sex|ageDays"
CREATE TABLE IF NOT EXISTS lab_reference (
ref_id TEXT PRIMARY KEY, -- synthetic composite key
loinc_id TEXT NOT NULL, -- FK to lab_test
source TEXT NOT NULL, -- "CALIPER", "IFCC"
sex TEXT NOT NULL DEFAULT '', -- "", "M", "F"
age_days INTEGER NOT NULL DEFAULT 0, -- start of age range (0 = birth)
age_end INTEGER NOT NULL, -- end of age range in days
ref_low INTEGER NOT NULL DEFAULT -1, -- lower bound x1M (-1 = no bound)
ref_high INTEGER NOT NULL DEFAULT -1, -- upper bound x1M (-1 = no bound)
unit TEXT NOT NULL -- SI unit these values are in
);
CREATE INDEX IF NOT EXISTS idx_lab_reference_loinc ON lab_reference(loinc_id);