fix(schema-v25): drop FK refs from store tables
Past migration finalize steps RENAME / DROP COLUMN / ALTER on the
`users` table (e.g. _v12_to_v13_finalize, _v13_to_v14_finalize,
_v17_to_v18_finalize, the v5 backfill). DuckDB rejects an ALTER on a
table that any other table references via FOREIGN KEY, so the new
store_entities / user_store_installs / user_plugin_optouts entries —
which the self-heal pass writes to _SYSTEM_SCHEMA before the migration
ladder runs — broke 6 legacy-migration tests with:
Cannot alter entry "users" because there are entries that depend on it
Pre-existing convention (see personal_access_tokens at v6) is to omit
FK constraints to `users` and validate user existence at the app
layer. Sync the three v25 tables with that convention. Same edit in
both _SYSTEM_SCHEMA and _V24_TO_V25_MIGRATIONS so fresh installs and
upgraded installs land in the same shape.
App-level cascade behavior is unchanged: store entity DELETE explicitly
deletes user_store_installs rows in app/api/store.py, and the admin
grant-deletion hook explicitly deletes user_plugin_optouts rows for the
plugin. The dropped FK constraints were defense-in-depth, not the only
guard.
This commit is contained in:
parent
d5a7c9ad79
commit
9d53efc6e1
1 changed files with 15 additions and 8 deletions
23
src/db.py
23
src/db.py
|
|
@ -449,9 +449,15 @@ CREATE TABLE IF NOT EXISTS claude_md_template (
|
|||
-- (admin_granted ∖ opt_outs) ∪ store_installs
|
||||
--
|
||||
-- See src/marketplace_filter.py:resolve_user_marketplace.
|
||||
-- FK refs to users(id) intentionally omitted (matches the
|
||||
-- personal_access_tokens / marketplace_registry pattern). DuckDB blocks
|
||||
-- ALTER on a referenced parent — past finalize steps RENAME / DROP COLUMN
|
||||
-- on `users`, which would fail if these store tables held FK refs at the
|
||||
-- time the ladder reaches them. App-level deletes already cascade
|
||||
-- explicitly (see app/api/store.py + the resource_grant-deletion hook).
|
||||
CREATE TABLE IF NOT EXISTS store_entities (
|
||||
id VARCHAR PRIMARY KEY,
|
||||
owner_user_id VARCHAR NOT NULL REFERENCES users(id),
|
||||
owner_user_id VARCHAR NOT NULL,
|
||||
owner_username VARCHAR NOT NULL,
|
||||
type VARCHAR NOT NULL CHECK (type IN ('skill','agent','plugin')),
|
||||
name VARCHAR NOT NULL,
|
||||
|
|
@ -469,14 +475,14 @@ CREATE TABLE IF NOT EXISTS store_entities (
|
|||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_store_installs (
|
||||
user_id VARCHAR NOT NULL REFERENCES users(id),
|
||||
entity_id VARCHAR NOT NULL REFERENCES store_entities(id),
|
||||
user_id VARCHAR NOT NULL,
|
||||
entity_id VARCHAR NOT NULL,
|
||||
installed_at TIMESTAMP DEFAULT current_timestamp,
|
||||
PRIMARY KEY (user_id, entity_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_plugin_optouts (
|
||||
user_id VARCHAR NOT NULL REFERENCES users(id),
|
||||
user_id VARCHAR NOT NULL,
|
||||
marketplace_id VARCHAR NOT NULL,
|
||||
plugin_name VARCHAR NOT NULL,
|
||||
opted_out_at TIMESTAMP DEFAULT current_timestamp,
|
||||
|
|
@ -1726,10 +1732,11 @@ _V22_TO_V23_MIGRATIONS = [
|
|||
|
||||
# v25: store + opt-out tables backing the /store and /my-ai-stack pages.
|
||||
_V24_TO_V25_MIGRATIONS = [
|
||||
# FK refs deliberately omitted — see the matching note in _SYSTEM_SCHEMA.
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS store_entities (
|
||||
id VARCHAR PRIMARY KEY,
|
||||
owner_user_id VARCHAR NOT NULL REFERENCES users(id),
|
||||
owner_user_id VARCHAR NOT NULL,
|
||||
owner_username VARCHAR NOT NULL,
|
||||
type VARCHAR NOT NULL CHECK (type IN ('skill','agent','plugin')),
|
||||
name VARCHAR NOT NULL,
|
||||
|
|
@ -1748,15 +1755,15 @@ _V24_TO_V25_MIGRATIONS = [
|
|||
""",
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS user_store_installs (
|
||||
user_id VARCHAR NOT NULL REFERENCES users(id),
|
||||
entity_id VARCHAR NOT NULL REFERENCES store_entities(id),
|
||||
user_id VARCHAR NOT NULL,
|
||||
entity_id VARCHAR NOT NULL,
|
||||
installed_at TIMESTAMP DEFAULT current_timestamp,
|
||||
PRIMARY KEY (user_id, entity_id)
|
||||
)
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS user_plugin_optouts (
|
||||
user_id VARCHAR NOT NULL REFERENCES users(id),
|
||||
user_id VARCHAR NOT NULL,
|
||||
marketplace_id VARCHAR NOT NULL,
|
||||
plugin_name VARCHAR NOT NULL,
|
||||
opted_out_at TIMESTAMP DEFAULT current_timestamp,
|
||||
|
|
|
|||
Loading…
Reference in a new issue