fix(db): add AUTOINCREMENT to prevent SQLite ROWID reuse
Without AUTOINCREMENT, SQLite can reassign the highest deleted ROWID to a new row. This is a data integrity bug: a deleted entity's ID could be assigned to a completely different entity, breaking bookmarks, API caches, and URL stability.
This commit is contained in:
parent
d9d87ef849
commit
97c46d034b
4 changed files with 14 additions and 14 deletions
|
|
@ -1,14 +1,14 @@
|
|||
-- Authentication and authorisation tables
|
||||
|
||||
CREATE TABLE users (
|
||||
id INTEGER PRIMARY KEY,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username TEXT NOT NULL UNIQUE,
|
||||
uuid TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
||||
);
|
||||
|
||||
CREATE TABLE tokens (
|
||||
id INTEGER PRIMARY KEY,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
token_hash TEXT NOT NULL UNIQUE,
|
||||
name TEXT NOT NULL,
|
||||
|
|
@ -20,7 +20,7 @@ CREATE INDEX idx_tokens_user_id ON tokens(user_id);
|
|||
CREATE INDEX idx_tokens_token_hash ON tokens(token_hash);
|
||||
|
||||
CREATE TABLE sessions (
|
||||
id INTEGER PRIMARY KEY,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
session_token_hash TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL,
|
||||
|
|
@ -31,7 +31,7 @@ CREATE INDEX idx_sessions_user_id ON sessions(user_id);
|
|||
CREATE INDEX idx_sessions_expires_at ON sessions(expires_at);
|
||||
|
||||
CREATE TABLE passkey_credentials (
|
||||
id INTEGER PRIMARY KEY,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
credential_json TEXT NOT NULL,
|
||||
name TEXT NOT NULL DEFAULT 'default',
|
||||
|
|
@ -41,7 +41,7 @@ CREATE TABLE passkey_credentials (
|
|||
CREATE INDEX idx_passkey_credentials_user_id ON passkey_credentials(user_id);
|
||||
|
||||
CREATE TABLE registration_tokens (
|
||||
id INTEGER PRIMARY KEY,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
token_hash TEXT NOT NULL UNIQUE,
|
||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
||||
expires_at TEXT NOT NULL,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
-- Coffee supply chain and equipment tables
|
||||
|
||||
CREATE TABLE roasters (
|
||||
id INTEGER PRIMARY KEY,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
country TEXT NOT NULL,
|
||||
city TEXT,
|
||||
|
|
@ -12,7 +12,7 @@ CREATE TABLE roasters (
|
|||
CREATE UNIQUE INDEX idx_roasters_slug ON roasters(slug);
|
||||
|
||||
CREATE TABLE roasts (
|
||||
id INTEGER PRIMARY KEY,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
roaster_id INTEGER NOT NULL REFERENCES roasters(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
origin TEXT,
|
||||
|
|
@ -27,7 +27,7 @@ CREATE INDEX idx_roasts_roaster_id ON roasts(roaster_id);
|
|||
CREATE UNIQUE INDEX idx_roasts_roaster_slug ON roasts(roaster_id, slug);
|
||||
|
||||
CREATE TABLE bags (
|
||||
id INTEGER PRIMARY KEY,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
roast_id INTEGER NOT NULL REFERENCES roasts(id) ON DELETE CASCADE,
|
||||
roast_date TEXT,
|
||||
amount REAL NOT NULL,
|
||||
|
|
@ -41,7 +41,7 @@ CREATE INDEX idx_bags_roast_id ON bags(roast_id);
|
|||
CREATE INDEX idx_bags_closed ON bags(closed);
|
||||
|
||||
CREATE TABLE gear (
|
||||
id INTEGER PRIMARY KEY,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
category TEXT NOT NULL CHECK (category IN ('grinder', 'brewer', 'filter_paper')),
|
||||
make TEXT NOT NULL,
|
||||
model TEXT NOT NULL,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
-- Brew, cafe, and cup tables
|
||||
|
||||
CREATE TABLE brews (
|
||||
id INTEGER PRIMARY KEY,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
bag_id INTEGER NOT NULL REFERENCES bags(id) ON DELETE CASCADE,
|
||||
coffee_weight REAL NOT NULL,
|
||||
grinder_id INTEGER NOT NULL REFERENCES gear(id) ON DELETE RESTRICT,
|
||||
|
|
@ -18,7 +18,7 @@ CREATE INDEX idx_brews_bag_id ON brews(bag_id);
|
|||
CREATE INDEX idx_brews_created_at ON brews(created_at DESC);
|
||||
|
||||
CREATE TABLE cafes (
|
||||
id INTEGER PRIMARY KEY,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
slug TEXT NOT NULL,
|
||||
city TEXT NOT NULL,
|
||||
|
|
@ -32,7 +32,7 @@ CREATE TABLE cafes (
|
|||
CREATE UNIQUE INDEX idx_cafes_slug ON cafes(slug);
|
||||
|
||||
CREATE TABLE cups (
|
||||
id INTEGER PRIMARY KEY,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
roast_id INTEGER NOT NULL REFERENCES roasts(id) ON DELETE RESTRICT,
|
||||
cafe_id INTEGER NOT NULL REFERENCES cafes(id) ON DELETE RESTRICT,
|
||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
-- Timeline events and AI usage tracking
|
||||
|
||||
CREATE TABLE timeline_events (
|
||||
id INTEGER PRIMARY KEY,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
entity_type TEXT NOT NULL CHECK (entity_type IN ('roaster', 'roast', 'bag', 'gear', 'brew', 'cafe', 'cup')),
|
||||
entity_id INTEGER NOT NULL,
|
||||
action TEXT NOT NULL,
|
||||
|
|
@ -17,7 +17,7 @@ CREATE INDEX idx_timeline_events_entity ON timeline_events(entity_type, entity_i
|
|||
CREATE INDEX idx_timeline_events_occurred_at ON timeline_events(occurred_at DESC);
|
||||
|
||||
CREATE TABLE ai_usage (
|
||||
id INTEGER PRIMARY KEY,
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
model TEXT NOT NULL,
|
||||
endpoint TEXT NOT NULL,
|
||||
|
|
|
|||
Loading…
Reference in a new issue