-- Migration 0003 — mastery tables (SLICE-04, TASK-04-02). -- Adds learner_ability (IRT theta persistence) + mastery_progress (path state). CREATE TABLE IF NOT EXISTS learner_ability ( learner_id TEXT NOT NULL, path TEXT NOT NULL, theta REAL NOT NULL DEFAULT 0.0, sigma_sq REAL NOT NULL DEFAULT 1.0, observations INTEGER NOT NULL DEFAULT 0, updated_at TEXT NOT NULL DEFAULT (datetime('now')), PRIMARY KEY (learner_id, path) ); CREATE TABLE IF NOT EXISTS mastery_progress ( learner_id TEXT NOT NULL, path TEXT NOT NULL, current_week INTEGER NOT NULL DEFAULT 1, scenarios_passed_json TEXT NOT NULL DEFAULT '[]', mastery_score REAL NOT NULL DEFAULT 0.0, gate_open INTEGER NOT NULL DEFAULT 0, updated_at TEXT NOT NULL DEFAULT (datetime('now')), PRIMARY KEY (learner_id, path) ); -- Mastery gate event audit log (SLICE-07 TASK-07-02, REQ-NFR-MAST-02). -- One row per mastery-flow run that produced a score (scoring_inconclusive -- runs do NOT record a gate event — they surface a retry instead). CREATE TABLE IF NOT EXISTS mastery_gate_events ( id TEXT PRIMARY KEY, learner_id TEXT NOT NULL, path TEXT NOT NULL, week INTEGER NOT NULL, scenarios_passed_json TEXT NOT NULL DEFAULT '[]', rubric_scores_json TEXT NOT NULL DEFAULT '[]', mastery_score REAL NOT NULL DEFAULT 0.0, gate_open INTEGER NOT NULL DEFAULT 0, recorded_at TEXT NOT NULL DEFAULT (datetime('now')) ); CREATE INDEX IF NOT EXISTS idx_mastery_gate_events_learner ON mastery_gate_events (learner_id, path); -- SLICE-09 TASK-09-01 — VC issuer tables (SQLite-backed, D-042, D-043). -- issuer_keys: Ed25519 keypairs, private key encrypted at rest (app-layer -- SecretBox with PRAXIS_VC_ISSUER_KEY root key). status active|superseded. CREATE TABLE IF NOT EXISTS issuer_keys ( id TEXT PRIMARY KEY, public_key TEXT NOT NULL, private_key_enc BLOB NOT NULL, status TEXT NOT NULL DEFAULT 'active', created_at TEXT NOT NULL DEFAULT (datetime('now')) ); CREATE INDEX IF NOT EXISTS idx_issuer_keys_status ON issuer_keys (status); -- issued_credentials: one row per issued VC. status active|revoked. CREATE TABLE IF NOT EXISTS issued_credentials ( id TEXT PRIMARY KEY, learner_id TEXT NOT NULL, vc_payload_json TEXT NOT NULL, signature_b64 TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'active', issued_at TEXT NOT NULL DEFAULT (datetime('now')) ); CREATE INDEX IF NOT EXISTS idx_issued_credentials_learner ON issued_credentials (learner_id); -- status_lists: Bitstring Status List (W3C Bitstring Status List v1.0). -- One bitstring per list; bit i = revoked status for credential slot i. CREATE TABLE IF NOT EXISTS status_lists ( id TEXT PRIMARY KEY, bitstring BLOB NOT NULL, size INTEGER NOT NULL, updated_at TEXT NOT NULL DEFAULT (datetime('now')) );