Files
praxis/db/migrations/0003_mastery.sql
T
Praxis CI 813bd586d6 docs(milestone): merge v0.3-mastery-scoring → main
v0.3 milestone merged to main. Mastery scoring + competency rubrics +
verifiable credentials (formative-tier) shipped. 13/13 REQ-IDs covered.
Next milestone: v0.4 (operator tier — cohort dashboard + auth + Postgres).

---ci---
project: praxis
phase: 2
milestone: v0.3
status: complete
milestone_complete: true
milestone_merged_to_main: true
---/ci---
2026-08-04 00:14:59 +00:00

77 lines
3.1 KiB
SQL

-- 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'))
);