From 74dac6b96026a6fc81bb658bc19ce2f3f75caa87 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Tue, 26 May 2026 21:57:38 -0400 Subject: [PATCH] fix(extension+migration): MV3 CSP opt-out from upgrade-insecure-requests (v1.0.4) + alembic 0023 drops the ck_tag_fandom_requires_character check before the type swap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit extension/manifest.json: add content_security_policy.extension_pages = "script-src 'self'; object-src 'self';" — explicitly omits the upgrade-insecure-requests directive that MV3 inherits by default. Without this, every fetch(http://curator.../...) silently upgrades to https:// at the browser layer (Sec-Fetch-Site=same-origin, NS_ERROR_GENERATE_FAILURE), regardless of about:config. Bump XPI version 1.0.3 → 1.0.4 so a fresh signed build replaces the cached one. Operator-troubleshot 2026-05-26 via Inspect-the-extension dev tools showing the silent scheme upgrade. alembic 0023: drop ck_tag_fandom_requires_character before the tag_kind type swap and recreate after. Postgres can't resolve `kind = 'character'` across the rename (column on tag_kind_old, literal binds to new tag_kind → "operator does not exist"). Same dance on downgrade. Banked under reference_tag_kind_enum_swap_check_drop. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../0023_drop_meta_rating_tag_kinds.py | 32 +++++++++++++++++-- extension/manifest.json | 7 +++- extension/package.json | 2 +- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/alembic/versions/0023_drop_meta_rating_tag_kinds.py b/alembic/versions/0023_drop_meta_rating_tag_kinds.py index 1d2b052..fc65ea1 100644 --- a/alembic/versions/0023_drop_meta_rating_tag_kinds.py +++ b/alembic/versions/0023_drop_meta_rating_tag_kinds.py @@ -30,11 +30,22 @@ def upgrade() -> None: # 1. Delete tags of the retired kinds. CASCADE handles related tables. op.execute("DELETE FROM tag WHERE kind IN ('meta', 'rating')") - # 2. Drop the server default — ALTER COLUMN TYPE can't carry it + # 2. Drop the CHECK constraint that references the enum's literal + # values. Postgres can't resolve `kind = 'character'` across the + # type swap below — the literal would bind to the new tag_kind + # but the column is on tag_kind_old, producing + # "operator does not exist: tag_kind = tag_kind_old". + # (Operator-hit during the v26.05.26.5 deploy attempt; ck was + # originally added by alembic 0002.) Recreated post-swap. + op.drop_constraint( + "ck_tag_fandom_requires_character", "tag", type_="check" + ) + + # 3. Drop the server default — ALTER COLUMN TYPE can't carry it # across the type swap below. op.execute("ALTER TABLE tag ALTER COLUMN kind DROP DEFAULT") - # 3. Recreate the tag_kind enum without meta/rating. + # 4. Recreate the tag_kind enum without meta/rating. op.execute("ALTER TYPE tag_kind RENAME TO tag_kind_old") op.execute( "CREATE TYPE tag_kind AS ENUM (" @@ -49,13 +60,23 @@ def upgrade() -> None: ) op.execute("DROP TYPE tag_kind_old") - # 4. Restore the server default. + # 5. Restore the server default. op.execute("ALTER TABLE tag ALTER COLUMN kind SET DEFAULT 'general'") + # 6. Restore the CHECK constraint (now bound to the new tag_kind). + op.create_check_constraint( + "ck_tag_fandom_requires_character", + "tag", + "(fandom_id IS NULL) OR (kind = 'character')", + ) + def downgrade() -> None: # Add the values back to the enum so old code can boot. The deleted # tag rows are gone permanently — no safe restore. + op.drop_constraint( + "ck_tag_fandom_requires_character", "tag", type_="check" + ) op.execute("ALTER TABLE tag ALTER COLUMN kind DROP DEFAULT") op.execute("ALTER TYPE tag_kind RENAME TO tag_kind_old") op.execute( @@ -71,3 +92,8 @@ def downgrade() -> None: ) op.execute("DROP TYPE tag_kind_old") op.execute("ALTER TABLE tag ALTER COLUMN kind SET DEFAULT 'general'") + op.create_check_constraint( + "ck_tag_fandom_requires_character", + "tag", + "(fandom_id IS NULL) OR (kind = 'character')", + ) diff --git a/extension/manifest.json b/extension/manifest.json index 217f0a0..850a6fa 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "FabledCurator", - "version": "1.0.3", + "version": "1.0.4", "description": "Export cookies from supported platforms to FabledCurator and add creators as sources in one click.", "browser_specific_settings": { @@ -11,6 +11,11 @@ } }, + "content_security_policy": { + "_comment": "Override the MV3 default CSP to OMIT upgrade-insecure-requests. FC runs over plain HTTP per the homelab posture (feedback_homelab_http), and the default MV3 CSP would silently upgrade every fetch(http://curator.../...) to https:// and fail with NS_ERROR_GENERATE_FAILURE. Operator-flagged 2026-05-26 after the 'Test connection' button errored despite a working CORS preflight on the backend.", + "extension_pages": "script-src 'self'; object-src 'self';" + }, + "permissions": [ "cookies", "storage", diff --git a/extension/package.json b/extension/package.json index db94a39..f4c7db4 100644 --- a/extension/package.json +++ b/extension/package.json @@ -1,6 +1,6 @@ { "name": "fabledcurator-extension", - "version": "1.0.3", + "version": "1.0.4", "private": true, "description": "Firefox extension for FabledCurator", "scripts": {