Follow-up from the store constraint audit on refactor-electron-side. Foreign keys are enforced (PRAGMA foreign_keys = ON per connection) and ownership edges/ordering are constraint-backed, but two invariants are app-enforced only:
-
glyph_layers needs UNIQUE(glyph_id, source_id) — "one layer per glyph per source" has no DB backing. With eager layer creation (new source → layer per glyph, new glyph → layer per source, VF-2) a bug could create duplicate layers silently and reads would pick arbitrary rows.
-
sources.name needs a unique index — duplicate source names are rejected in Rust validation only.
Open question (deliberate non-constraint for now): glyphs.name is not unique. Identity is id; names are editable display data — but the renderer's name-keyed directory assumes no collisions. Decide when the rename vocabulary (updateGlyphIdentity) returns; a unique index would need swap-safe rename handling.
Pre-release policy applies: edit the baseline schema in crates/shift-store/src/schema.rs in place, no migrations.
Follow-up from the store constraint audit on
refactor-electron-side. Foreign keys are enforced (PRAGMA foreign_keys = ONper connection) and ownership edges/ordering are constraint-backed, but two invariants are app-enforced only:glyph_layersneedsUNIQUE(glyph_id, source_id)— "one layer per glyph per source" has no DB backing. With eager layer creation (new source → layer per glyph, new glyph → layer per source, VF-2) a bug could create duplicate layers silently and reads would pick arbitrary rows.sources.nameneeds a unique index — duplicate source names are rejected in Rust validation only.Open question (deliberate non-constraint for now):
glyphs.nameis not unique. Identity isid; names are editable display data — but the renderer's name-keyed directory assumes no collisions. Decide when the rename vocabulary (updateGlyphIdentity) returns; a unique index would need swap-safe rename handling.Pre-release policy applies: edit the baseline schema in
crates/shift-store/src/schema.rsin place, no migrations.