Database Schema Reference
Database Schema Reference
Crucible persists execution history to a SQLite database managed by the @crucible/catalog package. This reference documents the tables that back ExecutionRepository and the invariants each column must satisfy. The authoritative schema lives in packages/catalog/src/db/schema.ts; the runtime ensureTables() path in packages/catalog/src/db/execution-repository.ts keeps existing databases in sync with that schema.
executions
One row per scenario run. Rows are keyed by a nanoid and are written by the scenario engine at execution creation time, then updated as the run progresses.
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
TEXT | NO (PK) | nanoid, engine-assigned at run creation |
scenario_id |
TEXT | NO | FK-style reference to a catalog scenario id |
mode |
TEXT | NO | simulation or assessment |
status |
TEXT | NO | pending, running, completed, failed, cancelled, paused, skipped |
started_at |
INTEGER | YES | Unix ms epoch |
completed_at |
INTEGER | YES | Unix ms epoch |
duration |
INTEGER | YES | Milliseconds |
error |
TEXT | YES | Human-readable failure message |
trigger_data |
TEXT (JSON) | YES | Arbitrary operator-supplied payload |
metadata |
TEXT (JSON) | YES | Engine-supplied metadata blob |
context |
TEXT (JSON) | YES | Step template context captured at run time |
paused_state |
TEXT (JSON) | YES | Snapshot used to resume paused executions |
parent_execution_id |
TEXT | YES | Self-reference for restart/retry chains |
target_url |
TEXT | NO | Effective target URL the run executed against |
report |
TEXT (JSON) | YES | Final report summary (populated on terminal status) |
target_url invariants
- Required. Every new execution must supply
target_url. The TypeScriptScenarioExecutiontype inpackages/catalog/src/db/execution-repository.tsenforces this as a required field; the SQLite column enforces it asNOT NULL. - Historical backfill. Pre-existing rows that predate the
NOT NULLconstraint are backfilled with the sentinel value'unknown'duringensureTables(). Reports and history views will display'unknown'for such rows so they are distinguishable from real targets. - Source of truth at read time. Reports, restart flows, and history rendering all read
target_urlfrom this column — not from the engine’s current default — so historical runs always replay or render against the target they originally used.
Indexes
| Index | Columns | Purpose |
|---|---|---|
idx_executions_scenario_started |
scenario_id, started_at |
Scenario-filtered history pagination |
idx_executions_status_started |
status, started_at |
Status-filtered history pagination |
idx_executions_target_url |
target_url |
Per-target filtering in multi-environment workflows |
execution_steps
One row per step result, keyed by autoincrement id with a (execution_id, step_id) logical key. Rows cascade-delete when the parent execution is removed.
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INTEGER | NO (PK, autoincrement) | |
execution_id |
TEXT | NO (FK → executions.id, ON DELETE CASCADE) | |
step_id |
TEXT | NO | Step identifier from the scenario definition |
status |
TEXT | NO | Same enum as executions.status |
started_at |
INTEGER | YES | Unix ms epoch |
completed_at |
INTEGER | YES | Unix ms epoch |
duration |
INTEGER | YES | Milliseconds |
error |
TEXT | YES | Human-readable failure message |
logs |
TEXT (JSON) | YES | Per-step log lines |
result |
TEXT (JSON) | YES | Legacy response payload column, preserved for read-side compatibility |
details |
TEXT (JSON) | YES | Structured { response, retention } detail used for report rendering |
attempts |
INTEGER | NO (default 0) | Retry counter |
assertions |
TEXT (JSON) | YES | Array of { field, expected, actual, passed } assertion records |
Indexes
| Index | Columns | Purpose |
|---|---|---|
idx_steps_execution_id |
execution_id |
Batch loading step rows for a set of executions |
Migrations
Forward migrations live in packages/catalog/drizzle/:
0000_burly_grim_reaper.sql— initial schema for both tables.0001_uneven_red_shift.sql— adds theresultanddetailsstep columns; addstarget_urltoexecutionsas nullable, backfills historical rows with'unknown', rebuildsexecutionswithtarget_url NOT NULL, and recreates all executions indexes.
The runtime ensureTables() path in execution-repository.ts performs the same upgrade in-process on startup using PRAGMA table_info to gate the table rebuild. Both paths produce schema-equivalent databases; deployments using drizzle-kit directly and deployments relying on runtime initialization converge on the same structure.