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
|
-- Authentication and authorisation tables
|
||||||
|
|
||||||
CREATE TABLE users (
|
CREATE TABLE users (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
username TEXT NOT NULL UNIQUE,
|
username TEXT NOT NULL UNIQUE,
|
||||||
uuid TEXT,
|
uuid TEXT,
|
||||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE tokens (
|
CREATE TABLE tokens (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
token_hash TEXT NOT NULL UNIQUE,
|
token_hash TEXT NOT NULL UNIQUE,
|
||||||
name TEXT NOT NULL,
|
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 INDEX idx_tokens_token_hash ON tokens(token_hash);
|
||||||
|
|
||||||
CREATE TABLE sessions (
|
CREATE TABLE sessions (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
session_token_hash TEXT NOT NULL,
|
session_token_hash TEXT NOT NULL,
|
||||||
created_at 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 INDEX idx_sessions_expires_at ON sessions(expires_at);
|
||||||
|
|
||||||
CREATE TABLE passkey_credentials (
|
CREATE TABLE passkey_credentials (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
credential_json TEXT NOT NULL,
|
credential_json TEXT NOT NULL,
|
||||||
name TEXT NOT NULL DEFAULT 'default',
|
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 INDEX idx_passkey_credentials_user_id ON passkey_credentials(user_id);
|
||||||
|
|
||||||
CREATE TABLE registration_tokens (
|
CREATE TABLE registration_tokens (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
token_hash TEXT NOT NULL UNIQUE,
|
token_hash TEXT NOT NULL UNIQUE,
|
||||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
||||||
expires_at TEXT NOT NULL,
|
expires_at TEXT NOT NULL,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
-- Coffee supply chain and equipment tables
|
-- Coffee supply chain and equipment tables
|
||||||
|
|
||||||
CREATE TABLE roasters (
|
CREATE TABLE roasters (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
country TEXT NOT NULL,
|
country TEXT NOT NULL,
|
||||||
city TEXT,
|
city TEXT,
|
||||||
|
|
@ -12,7 +12,7 @@ CREATE TABLE roasters (
|
||||||
CREATE UNIQUE INDEX idx_roasters_slug ON roasters(slug);
|
CREATE UNIQUE INDEX idx_roasters_slug ON roasters(slug);
|
||||||
|
|
||||||
CREATE TABLE roasts (
|
CREATE TABLE roasts (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
roaster_id INTEGER NOT NULL REFERENCES roasters(id) ON DELETE CASCADE,
|
roaster_id INTEGER NOT NULL REFERENCES roasters(id) ON DELETE CASCADE,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
origin TEXT,
|
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 UNIQUE INDEX idx_roasts_roaster_slug ON roasts(roaster_id, slug);
|
||||||
|
|
||||||
CREATE TABLE bags (
|
CREATE TABLE bags (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
roast_id INTEGER NOT NULL REFERENCES roasts(id) ON DELETE CASCADE,
|
roast_id INTEGER NOT NULL REFERENCES roasts(id) ON DELETE CASCADE,
|
||||||
roast_date TEXT,
|
roast_date TEXT,
|
||||||
amount REAL NOT NULL,
|
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 INDEX idx_bags_closed ON bags(closed);
|
||||||
|
|
||||||
CREATE TABLE gear (
|
CREATE TABLE gear (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
category TEXT NOT NULL CHECK (category IN ('grinder', 'brewer', 'filter_paper')),
|
category TEXT NOT NULL CHECK (category IN ('grinder', 'brewer', 'filter_paper')),
|
||||||
make TEXT NOT NULL,
|
make TEXT NOT NULL,
|
||||||
model TEXT NOT NULL,
|
model TEXT NOT NULL,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
-- Brew, cafe, and cup tables
|
-- Brew, cafe, and cup tables
|
||||||
|
|
||||||
CREATE TABLE brews (
|
CREATE TABLE brews (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
bag_id INTEGER NOT NULL REFERENCES bags(id) ON DELETE CASCADE,
|
bag_id INTEGER NOT NULL REFERENCES bags(id) ON DELETE CASCADE,
|
||||||
coffee_weight REAL NOT NULL,
|
coffee_weight REAL NOT NULL,
|
||||||
grinder_id INTEGER NOT NULL REFERENCES gear(id) ON DELETE RESTRICT,
|
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 INDEX idx_brews_created_at ON brews(created_at DESC);
|
||||||
|
|
||||||
CREATE TABLE cafes (
|
CREATE TABLE cafes (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
slug TEXT NOT NULL,
|
slug TEXT NOT NULL,
|
||||||
city TEXT NOT NULL,
|
city TEXT NOT NULL,
|
||||||
|
|
@ -32,7 +32,7 @@ CREATE TABLE cafes (
|
||||||
CREATE UNIQUE INDEX idx_cafes_slug ON cafes(slug);
|
CREATE UNIQUE INDEX idx_cafes_slug ON cafes(slug);
|
||||||
|
|
||||||
CREATE TABLE cups (
|
CREATE TABLE cups (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
roast_id INTEGER NOT NULL REFERENCES roasts(id) ON DELETE RESTRICT,
|
roast_id INTEGER NOT NULL REFERENCES roasts(id) ON DELETE RESTRICT,
|
||||||
cafe_id INTEGER NOT NULL REFERENCES cafes(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')),
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
-- Timeline events and AI usage tracking
|
-- Timeline events and AI usage tracking
|
||||||
|
|
||||||
CREATE TABLE timeline_events (
|
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_type TEXT NOT NULL CHECK (entity_type IN ('roaster', 'roast', 'bag', 'gear', 'brew', 'cafe', 'cup')),
|
||||||
entity_id INTEGER NOT NULL,
|
entity_id INTEGER NOT NULL,
|
||||||
action TEXT 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 INDEX idx_timeline_events_occurred_at ON timeline_events(occurred_at DESC);
|
||||||
|
|
||||||
CREATE TABLE ai_usage (
|
CREATE TABLE ai_usage (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
model TEXT NOT NULL,
|
model TEXT NOT NULL,
|
||||||
endpoint TEXT NOT NULL,
|
endpoint TEXT NOT NULL,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue