From 3177ffe61dc3d82494dbe7b76123b1f39a440f47 Mon Sep 17 00:00:00 2001 From: Jesse_Chen Date: Wed, 30 Sep 2026 10:15:06 +0800 Subject: [PATCH] fix(account): deletion freeze trigger reads amount via jsonb so shared inserts don't fail; list the new tables (BUG-1118) Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE --- docs/BUG_HISTORY.md | 13 +++++++++++++ docs/tasks/PROGRESS-compliance-launch-20260930.md | 6 ++++++ .../20260930020000_account_deletion_requests.sql | 6 +++++- frontend/tests/database-local-business.test.ts | 10 ++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index 90b84111..c157af23 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -14922,3 +14922,16 @@ - 相关记录:BUG-560、BUG-1084、BUG-1090、BUG-1091 - 复发自:无 - 修复版本:研究分支 `codex/rectification-varga-resolution-research-20260930`(未合入) + +## BUG-1118 | 注销冻结触发器引用不存在的 `new.amount`,会让所有扣点写入报错(门禁拦下,未上线) + +- 状态:resolved(代码 + 本机真实 PostgreSQL 17 数据库测试;未部署) +- 首次发现 / 最近更新:2026-09-30 / 2026-09-30 +- 影响面:`frontend/supabase/migrations/20260930020000_account_deletion_requests.sql::refuse_charge_while_deletion_pending`,挂在 `usage_reservations`、`birth_time_rectification_billing`、`credit_transactions` 三张表的 insert 触发器上。 +- 现象:合规轮推 staging(`2f6581ff`)后门禁 validate 失败;本机复现:`record "new" has no field "amount"`,计费、免费完成、人物删除释放预留等 4 个数据库测试失败。若上线,所有咨询 / 校正扣点写入都会报错。 +- 根因:同一个触发器函数服务三张表,只有 `credit_transactions` 有 `amount` 列;PL/pgSQL 在另两张表上解析 `new.amount` 时即报错,表名判断在前也挡不住。执行方本机无 Docker,数据库测试被跳过,问题只在门禁里暴露。 +- 修复:改为 `(to_jsonb(new) ->> 'amount')::integer` 读取。该迁移从未在任何库执行过(门禁在 publish / migrate 之前失败),因此原地修改。另把六张新表补进 `database-local-business.test.ts` 的表清单(三栏注释)。 +- 验证:本机 PostgreSQL 17.11(zonky 预编译二进制)+ 临时 `docker compose` 替身跑全部 `database-*.test.ts`:修复前本分支比基线多 4 条失败,修复后失败名单与基线逐条相同(6 条,均为替身不支持的 pg_dump / 部署类),并多通过 1 条新测试。 +- 防复发:新增或修改迁移的轮次,交付前必须在真实 PostgreSQL 上跑 `database-*` 测试;无 Docker 时用同样的本机替身(方法见 PROGRESS-compliance-launch-20260930)。触发器函数跨表复用时不得直接引用只存在于某一张表的列。 +- 相关记录:TASK / PROGRESS-account-deletion-20260930、PROGRESS-compliance-launch-20260930 +- 修复版本:分支 `codex/compliance-launch-20260930` diff --git a/docs/tasks/PROGRESS-compliance-launch-20260930.md b/docs/tasks/PROGRESS-compliance-launch-20260930.md index 9ee7c48b..f23f38d3 100644 --- a/docs/tasks/PROGRESS-compliance-launch-20260930.md +++ b/docs/tasks/PROGRESS-compliance-launch-20260930.md @@ -44,3 +44,9 @@ ## 环境缺口 无 Docker(数据库测试);无 staging 测试账号与真机(浏览器全流程、注销 7 天后真实清除);阿里云密钥;协议文本未经律师审定。 + +## 门禁失败与修复(BUG-1118) + +推 `2f6581ff` 后 staging 门禁 validate 失败(Gitea 日志需令牌,看不到)。本机排查:隐私扫描、Python 编译均通过;在本机用 PostgreSQL 17.11 预编译二进制 + 一个只支持 up / down / exec psql 的 `docker compose` 替身(脚本在会话临时目录,不入仓)跑全部 `database-*.test.ts`,比基线多 4 条失败:3 条是注销迁移的冻结触发器引用 `new.amount`(跨表复用,另两张表没有该列),1 条是表清单缺六张新表。修复后失败名单与基线逐条相同。 + +本机数据库测试方法(供以后无 Docker 时复用):`embedded-postgres-binaries-linux-amd64-17.x.jar` 解出 `initdb/pg_ctl/postgres`;用 `pg` 客户端重放 `deploy/postgres/001-bootstrap-roles.sh` 做模板库;替身 `docker` 在 `compose up` 时复制模板启动实例、`exec psql` 用 `pg` 客户端执行 `-Atc` / `-f -`。已知替身局限:不支持 `pg_dump`、部署脚本类测试(基线同样 6 条失败)。 diff --git a/frontend/supabase/migrations/20260930020000_account_deletion_requests.sql b/frontend/supabase/migrations/20260930020000_account_deletion_requests.sql index ffe8f5d9..daaf6f6e 100644 --- a/frontend/supabase/migrations/20260930020000_account_deletion_requests.sql +++ b/frontend/supabase/migrations/20260930020000_account_deletion_requests.sql @@ -207,7 +207,11 @@ security definer set search_path = pg_catalog, public as $$ begin - if tg_table_name = 'credit_transactions' and coalesce(new.amount, 0) >= 0 then + -- The same function guards three tables, and only credit_transactions has an + -- amount column: read it through jsonb, because `new.amount` fails at run + -- time on the other two even behind the table-name test. + if tg_table_name = 'credit_transactions' + and coalesce((to_jsonb(new) ->> 'amount')::integer, 0) >= 0 then return new; end if; if exists ( diff --git a/frontend/tests/database-local-business.test.ts b/frontend/tests/database-local-business.test.ts index b9ce10cc..1b9557a9 100644 --- a/frontend/tests/database-local-business.test.ts +++ b/frontend/tests/database-local-business.test.ts @@ -202,6 +202,11 @@ test("local PostgreSQL applies the reviewed business schema and serves authentic where schemaname = 'public' `), [ + // 原值: 列表以 admin_permissions 开头,且无下面标注的五张表 + // 新值: 加入 account_deletion_requests、moderation_events、reply_quality_snapshots、 + // reply_ratings、user_consents、user_feedback + // 原因: 2026-09-30 合规轮 20260930010000~050000 新增的六张表;本清单必须与 pg_tables 一致 + "account_deletion_requests", "admin_permissions", "admin_role_permissions", "admin_roles", @@ -265,6 +270,7 @@ test("local PostgreSQL applies the reviewed business schema and serves authentic "model_connection_test_evidence", "model_providers", "model_publish_events", + "moderation_events", "notification_templates", "payment_orders", "payment_packages", @@ -282,10 +288,14 @@ test("local PostgreSQL applies the reviewed business schema and serves authentic "rectification_telemetry_reported_cases", "redemption_attempts", "redemption_codes", + "reply_quality_snapshots", + "reply_ratings", "synastry_reports", "usage_events", "usage_ledger", "usage_reservations", + "user_consents", + "user_feedback", "user_product_redemptions", "user_subscriptions", ].join(","),