@taopao/memoir 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +8 -2
  3. package/assets/migrations-pg/0100_baseline.sql +1115 -0
  4. package/assets/migrations-pg/0101_functions.sql +93 -0
  5. package/assets/migrations-pg/0102_views.sql +2425 -0
  6. package/assets/migrations-pg/0103_constraints.sql +147 -0
  7. package/assets/migrations-pg/0104_protection.sql +33 -0
  8. package/assets/migrations-pg/0105_bocom_credit_card.sql +43 -0
  9. package/assets/migrations-pg/0106_psbc_debit_card.sql +87 -0
  10. package/assets/migrations-pg/0107_tailong_debit_card.sql +87 -0
  11. package/assets/migrations-pg/0108_ccb_debit_card.sql +87 -0
  12. package/assets/migrations-pg/0109_ccb_credit_card.sql +63 -0
  13. package/assets/migrations-pg/0110_icbc_debit_card.sql +87 -0
  14. package/assets/migrations-pg/0111_icbc_credit_card.sql +66 -0
  15. package/assets/migrations-pg/0112_boc_debit_card.sql +88 -0
  16. package/assets/migrations-pg/0113_jsb_debit_card.sql +88 -0
  17. package/assets/migrations-pg/0114_cmbc_debit_card.sql +88 -0
  18. package/assets/migrations-pg/0115_hzbank_debit_card.sql +88 -0
  19. package/assets/migrations-pg/0116_unified_bank_documents.sql +197 -0
  20. package/assets/migrations-pg/0117_agent_submissions.sql +50 -0
  21. package/assets/migrations-pg/0118_agent_reversions_analysis.sql +34 -0
  22. package/assets/migrations-pg/0119_agent_extension_registry.sql +72 -0
  23. package/assets/migrations-pg/0120_agent_record_sources.sql +22 -0
  24. package/assets/migrations-pg/0121_agent_extension_deprecation.sql +30 -0
  25. package/assets/migrations-pg/0122_agent_extension_controlled_revert.sql +107 -0
  26. package/assets/migrations-pg/0123_agent_extension_versions.sql +54 -0
  27. package/assets/migrations-pg/0124_agent_extension_retirement_groups.sql +26 -0
  28. package/assets/migrations-pg/0125_agent_candidate_reviews.sql +30 -0
  29. package/assets/migrations-pg/0126_agent_module_lifecycle.sql +93 -0
  30. package/assets/migrations-pg/0127_agent_tasks.sql +64 -0
  31. package/assets/migrations-pg/0128_agent_task_leases.sql +80 -0
  32. package/assets/migrations-pg/0129_agent_task_plans.sql +66 -0
  33. package/assets/migrations-pg/0130_agent_task_submissions.sql +72 -0
  34. package/assets/migrations-pg/0131_agent_task_completions.sql +93 -0
  35. package/assets/migrations-pg/0132_agent_task_changes.sql +113 -0
  36. package/assets/migrations-pg/0133_agent_imported_source_snapshots.sql +152 -0
  37. package/assets/migrations-pg/0134_agent_analysis_datasets.sql +6 -0
  38. package/assets/migrations-pg/0135_agent_maintenance_tasks.sql +139 -0
  39. package/assets/migrations-pg/0136_agent_task_structures.sql +66 -0
  40. package/assets/migrations-pg/0137_agent_personal_identity.sql +149 -0
  41. package/assets/migrations-pg/0138_agent_work_records.sql +24 -0
  42. package/assets/migrations-pg/0139_shared_files.sql +43 -0
  43. package/assets/migrations-pg/0140_shared_script_runs.sql +36 -0
  44. package/assets/migrations-pg/0141_payment_bank_links.sql +96 -0
  45. package/assets/migrations-pg/0142_consumption_order_types_and_places.sql +287 -0
  46. package/assets/migrations-pg/0143_skill_direct_write.sql +330 -0
  47. package/assets/migrations-pg/0144_skill_schema_archive.sql +73 -0
  48. package/assets/migrations-pg/0145_skill_ingest_wiki.sql +91 -0
  49. package/assets/migrations-pg/0146_skill_load.sql +17 -0
  50. package/assets/migrations-pg/0147_drop_agent_schema.sql +147 -0
  51. package/assets/migrations-pg/0148_ingest_lanes.sql +19 -0
  52. package/assets/migrations-pg/0149_account_ownership.sql +233 -0
  53. package/assets/migrations-pg/0150_bank_card_exact_link.sql +24 -0
  54. package/assets/migrations-pg/0151_account_ownership_enforce.sql +35 -0
  55. package/assets/migrations-pg/0152_account_ownership_views.sql +750 -0
  56. package/assets/migrations-pg/0153_web_frontend.sql +34 -0
  57. package/assets/migrations-pg/0154_audio_record_owners.sql +103 -0
  58. package/assets/migrations-pg/0155_ingest_knowledge_tables.sql +171 -0
  59. package/assets/migrations-pg/0156_batch_playbook_note.sql +17 -0
  60. package/assets/migrations-pg/0157_last_contact.sql +166 -0
  61. package/assets/migrations-pg/0158_refund_match_hash_join.sql +91 -0
  62. package/assets/migrations-pg/0159_fact_occurred_time.sql +88 -0
  63. package/assets/migrations-pg/0160_agent_notes.sql +118 -0
  64. package/assets/migrations-pg/0161_life_history.sql +314 -0
  65. package/assets/migrations-pg/0162_person_card.sql +427 -0
  66. package/assets/migrations-pg/0163_parking_drop_personal_defaults.sql +12 -0
  67. package/assets/native/darwin-arm64.node +0 -0
  68. package/assets/playbooks/audio.md +83 -0
  69. package/assets/playbooks/chat.md +37 -0
  70. package/assets/playbooks/common.md +66 -0
  71. package/assets/playbooks/intimate.md +19 -0
  72. package/assets/playbooks/journal.md +17 -0
  73. package/assets/playbooks/orders.md +15 -0
  74. package/assets/playbooks/payments.md +16 -0
  75. package/assets/playbooks/self.md +29 -0
  76. package/bin/install-codex-skill.mjs +77 -0
  77. package/bin/memoir.mjs +5 -0
  78. package/dist/cli.js +34062 -0
  79. package/package.json +40 -4
  80. package/release-manifest.json +432 -0
  81. package/skill/SKILL.md +120 -0
  82. package/skill/references//345/256/211/350/243/205/344/275/215/347/275/256.md +21 -0
  83. package/skill/references//346/225/260/346/215/256/345/217/243/345/276/204.md +36 -0
  84. package/skill/scripts/memoir.mjs +82 -0
@@ -0,0 +1,87 @@
1
+ -- 工行借记账户历史明细使用专属事实表,既有银行记录、批次和审计不重写。
2
+ -- 只扩展批次来源枚举;时间精度、正负方向、原始十三列与原件批次外键明确保存。
3
+ ALTER TABLE import_batches DROP CONSTRAINT import_batches_source_kind_check;
4
+ ALTER TABLE import_batches ADD CONSTRAINT import_batches_source_kind_check CHECK (source_kind IN (
5
+ 'wechat_chat', 'audio_db', 'alipay', 'wechatpay', 'jd', 'taobao', 'pdd',
6
+ 'meituan', 'taobao_takeout', 'train12306', 'manual_ledger', 'legacy_md',
7
+ 'citic_credit_card', 'citic_debit_card', 'cmb_debit_card', 'cmb_credit_card',
8
+ 'bocom_debit_card', 'bocom_credit_card', 'psbc_debit_card', 'tailong_debit_card', 'ccb_debit_card', 'ccb_credit_card', 'icbc_debit_card'
9
+ ));
10
+
11
+ CREATE TABLE "icbc_bank_statements" (
12
+ statement_key TEXT PRIMARY KEY,
13
+ source_kind TEXT NOT NULL CHECK (source_kind = 'icbc_debit_card'),
14
+ account_key TEXT NOT NULL,
15
+ account_masked TEXT NOT NULL,
16
+ owner_name TEXT NOT NULL,
17
+ account_type TEXT NOT NULL,
18
+ branch TEXT NOT NULL,
19
+ period_from TEXT NOT NULL,
20
+ period_to TEXT NOT NULL CHECK (period_to >= period_from),
21
+ requested_at TEXT NOT NULL,
22
+ verification_code TEXT NOT NULL,
23
+ page_count BIGINT NOT NULL CHECK (page_count > 0),
24
+ source_file TEXT NOT NULL,
25
+ source_sha256 TEXT NOT NULL,
26
+ first_batch_id TEXT NOT NULL REFERENCES import_batches(id),
27
+ last_batch_id TEXT NOT NULL REFERENCES import_batches(id),
28
+ raw_json TEXT NOT NULL CHECK (vault_json_valid(raw_json))
29
+ );
30
+
31
+ CREATE TABLE "icbc_bank_transactions" (
32
+ transaction_key TEXT PRIMARY KEY,
33
+ account_key TEXT NOT NULL,
34
+ account_masked TEXT NOT NULL,
35
+ card_last_four TEXT NOT NULL CHECK (length(card_last_four) = 4),
36
+ currency TEXT NOT NULL,
37
+ occurred_at TEXT NOT NULL,
38
+ direction TEXT NOT NULL CHECK (direction IN ('in', 'out', 'neutral')),
39
+ amount_cents BIGINT NOT NULL CHECK (amount_cents >= 0),
40
+ balance_cents BIGINT NOT NULL,
41
+ counterparty TEXT NOT NULL,
42
+ counterparty_account TEXT NOT NULL,
43
+ institution TEXT NOT NULL,
44
+ description TEXT NOT NULL,
45
+ bank_txn_id TEXT NOT NULL,
46
+ transaction_card TEXT NOT NULL,
47
+ status TEXT NOT NULL,
48
+ source_file TEXT NOT NULL,
49
+ source_sha256 TEXT NOT NULL,
50
+ source_sheet TEXT NOT NULL,
51
+ row_number BIGINT NOT NULL CHECK (row_number > 0),
52
+ first_batch_id TEXT NOT NULL REFERENCES import_batches(id),
53
+ last_batch_id TEXT NOT NULL REFERENCES import_batches(id),
54
+ raw_json TEXT NOT NULL CHECK (vault_json_valid(raw_json)),
55
+ source_kind TEXT NOT NULL DEFAULT 'icbc_debit_card' CHECK (source_kind = 'icbc_debit_card'),
56
+ date_precision TEXT NOT NULL DEFAULT 'second' CHECK (date_precision = 'second'),
57
+ page_number BIGINT NOT NULL CHECK (page_number > 0),
58
+ statement_key TEXT NOT NULL REFERENCES icbc_bank_statements(statement_key),
59
+ CHECK ((direction = 'neutral' AND amount_cents = 0) OR (direction IN ('in', 'out') AND amount_cents > 0))
60
+ );
61
+
62
+
63
+ CREATE INDEX ix_icbc_statement_account_period ON icbc_bank_statements(account_key, period_from, period_to);
64
+ CREATE INDEX ix_icbc_transaction_account_date ON icbc_bank_transactions(account_key, occurred_at);
65
+ CREATE INDEX ix_icbc_transaction_statement ON icbc_bank_transactions(statement_key);
66
+
67
+ -- 新表按原始事实保护,只有 importer/migration 会话可写;每行审计、数据版本和
68
+ -- TRUNCATE 防护与现有银行卡完全一致。增量 SQL 同时用于旧库升级和新库逐步安装。
69
+ DO $$
70
+ DECLARE target_table text; key_column text; grant_row record;
71
+ BEGIN
72
+ FOREACH target_table IN ARRAY ARRAY['icbc_bank_statements', 'icbc_bank_transactions'] LOOP
73
+ key_column := CASE WHEN target_table = 'icbc_bank_statements' THEN 'statement_key' ELSE 'transaction_key' END;
74
+ EXECUTE format('CREATE TRIGGER trg_%s_guard BEFORE INSERT OR UPDATE OR DELETE ON %I FOR EACH ROW EXECUTE FUNCTION vault_guard(''fact'')', target_table, target_table);
75
+ EXECUTE format('CREATE TRIGGER trg_%s_truncate BEFORE TRUNCATE ON %I FOR EACH STATEMENT EXECUTE FUNCTION vault_guard(''fact'')', target_table, target_table);
76
+ EXECUTE format('CREATE TRIGGER trg_%s_version AFTER INSERT OR UPDATE OR DELETE ON %I FOR EACH STATEMENT EXECUTE FUNCTION vault_touch()', target_table, target_table);
77
+ EXECUTE format('CREATE TRIGGER trg_%s_audit AFTER INSERT OR UPDATE OR DELETE ON %I FOR EACH ROW EXECUTE FUNCTION vault_audit(%L)', target_table, target_table, key_column);
78
+ -- 继承同类事实表的现有应用/只读权限,不写死部署角色,也不授予新的管理权限。
79
+ FOR grant_row IN SELECT grantee, privilege_type FROM information_schema.role_table_grants
80
+ WHERE table_schema = 'public' AND role_table_grants.table_name = 'bank_card_transactions'
81
+ AND grantee <> current_user AND privilege_type IN ('SELECT', 'INSERT', 'UPDATE', 'DELETE')
82
+ LOOP
83
+ EXECUTE format('GRANT %s ON TABLE %I TO %s', grant_row.privilege_type, target_table,
84
+ CASE WHEN grant_row.grantee = 'PUBLIC' THEN 'PUBLIC' ELSE quote_ident(grant_row.grantee) END);
85
+ END LOOP;
86
+ END LOOP;
87
+ END $$;
@@ -0,0 +1,66 @@
1
+ -- 工行信用卡历史明细使用专属事实表,既有银行记录、批次和审计不重写。
2
+ -- 只扩展批次来源枚举;时间精度、正负方向、原始十二列与原件批次外键明确保存。
3
+ ALTER TABLE import_batches DROP CONSTRAINT import_batches_source_kind_check;
4
+ ALTER TABLE import_batches ADD CONSTRAINT import_batches_source_kind_check CHECK (source_kind IN (
5
+ 'wechat_chat', 'audio_db', 'alipay', 'wechatpay', 'jd', 'taobao', 'pdd',
6
+ 'meituan', 'taobao_takeout', 'train12306', 'manual_ledger', 'legacy_md',
7
+ 'citic_credit_card', 'citic_debit_card', 'cmb_debit_card', 'cmb_credit_card',
8
+ 'bocom_debit_card', 'bocom_credit_card', 'psbc_debit_card', 'tailong_debit_card', 'ccb_debit_card', 'ccb_credit_card', 'icbc_debit_card', 'icbc_credit_card'
9
+ ));
10
+
11
+ CREATE TABLE "icbc_credit_card_transactions" (
12
+ transaction_key TEXT PRIMARY KEY,
13
+ statement_key TEXT CHECK (statement_key IS NULL),
14
+ transaction_date TEXT,
15
+ posting_date TEXT NOT NULL,
16
+ card_last_four TEXT NOT NULL CHECK (length(card_last_four) = 4),
17
+ description TEXT NOT NULL,
18
+ transaction_currency TEXT,
19
+ transaction_amount_cents BIGINT NOT NULL,
20
+ settlement_currency TEXT NOT NULL,
21
+ settlement_amount_cents BIGINT NOT NULL,
22
+ transaction_kind TEXT NOT NULL CHECK (transaction_kind IN ('charge', 'fee', 'refund', 'repayment', 'credit')),
23
+ occurrence BIGINT NOT NULL CHECK (occurrence > 0),
24
+ page_number BIGINT NOT NULL CHECK (page_number > 0),
25
+ end_page_number BIGINT NOT NULL CHECK (end_page_number >= page_number),
26
+ source_file TEXT NOT NULL,
27
+ source_sha256 TEXT NOT NULL,
28
+ first_batch_id TEXT NOT NULL REFERENCES import_batches(id),
29
+ last_batch_id TEXT NOT NULL REFERENCES import_batches(id),
30
+ raw_json TEXT NOT NULL CHECK (vault_json_valid(raw_json)),
31
+ original_amount_raw TEXT NOT NULL DEFAULT '',
32
+ source_kind TEXT NOT NULL CHECK (source_kind='icbc_credit_card'),
33
+ card_key TEXT NOT NULL,
34
+ account_masked TEXT NOT NULL,
35
+ occurred_at TEXT NOT NULL,
36
+ date_precision TEXT NOT NULL CHECK (date_precision IN ('day','second')),
37
+ transaction_time_raw TEXT NOT NULL,
38
+ bank_type TEXT NOT NULL,
39
+ direction TEXT NOT NULL CHECK (direction IN ('in','out')),
40
+ payment_channel TEXT NOT NULL,
41
+ counterparty TEXT NOT NULL,
42
+ remark TEXT NOT NULL,
43
+ source_sheet TEXT NOT NULL,
44
+ row_number BIGINT NOT NULL CHECK (row_number>0),
45
+ original_sequence BIGINT CHECK (original_sequence IS NULL),
46
+ bank_balance_cents BIGINT NOT NULL,
47
+ transaction_card_masked TEXT NOT NULL,
48
+ counterparty_account TEXT NOT NULL,
49
+ CHECK (transaction_currency IN ('CNY','USD','HKD') AND settlement_currency IN ('CNY','USD','HKD')),
50
+ CHECK (transaction_currency<>settlement_currency OR transaction_amount_cents=settlement_amount_cents),
51
+ CHECK ((direction='out' AND transaction_kind IN ('charge','fee') AND settlement_amount_cents>0) OR (direction='in' AND transaction_kind IN ('refund','credit') AND settlement_amount_cents<0))
52
+ );
53
+
54
+ CREATE INDEX ix_icbc_credit_card_date ON icbc_credit_card_transactions(card_key,transaction_date);
55
+ CREATE INDEX ix_icbc_credit_source ON icbc_credit_card_transactions(source_sha256,row_number);
56
+
57
+ -- 独立交易事实沿用现有导入会话、逐行审计与数据版本保护,不伪造月度账单。
58
+ CREATE TRIGGER trg_icbc_credit_card_transactions_guard BEFORE INSERT OR UPDATE OR DELETE ON icbc_credit_card_transactions FOR EACH ROW EXECUTE FUNCTION vault_guard('fact');
59
+ CREATE TRIGGER trg_icbc_credit_card_transactions_truncate BEFORE TRUNCATE ON icbc_credit_card_transactions FOR EACH STATEMENT EXECUTE FUNCTION vault_guard('fact');
60
+ CREATE TRIGGER trg_icbc_credit_card_transactions_version AFTER INSERT OR UPDATE OR DELETE ON icbc_credit_card_transactions FOR EACH STATEMENT EXECUTE FUNCTION vault_touch();
61
+ CREATE TRIGGER trg_icbc_credit_card_transactions_audit AFTER INSERT OR UPDATE OR DELETE ON icbc_credit_card_transactions FOR EACH ROW EXECUTE FUNCTION vault_audit('transaction_key');
62
+ DO $$ DECLARE grant_row record; BEGIN
63
+ FOR grant_row IN SELECT grantee,privilege_type FROM information_schema.role_table_grants
64
+ WHERE table_schema='public' AND table_name='credit_card_transactions' AND grantee<>current_user AND privilege_type IN ('SELECT','INSERT','UPDATE','DELETE')
65
+ LOOP EXECUTE format('GRANT %s ON TABLE icbc_credit_card_transactions TO %s',grant_row.privilege_type,CASE WHEN grant_row.grantee='PUBLIC' THEN 'PUBLIC' ELSE quote_ident(grant_row.grantee) END); END LOOP;
66
+ END $$;
@@ -0,0 +1,88 @@
1
+ -- 中国银行借记卡交易明细使用专属事实表,既有银行记录、批次和审计不重写。
2
+ -- 只扩展批次来源枚举;秒级时间精度、多币种收支方向、原始十五列与原件批次外键明确保存。
3
+ ALTER TABLE import_batches DROP CONSTRAINT import_batches_source_kind_check;
4
+ ALTER TABLE import_batches ADD CONSTRAINT import_batches_source_kind_check CHECK (source_kind IN (
5
+ 'wechat_chat', 'audio_db', 'alipay', 'wechatpay', 'jd', 'taobao', 'pdd',
6
+ 'meituan', 'taobao_takeout', 'train12306', 'manual_ledger', 'legacy_md',
7
+ 'citic_credit_card', 'citic_debit_card', 'cmb_debit_card', 'cmb_credit_card',
8
+ 'bocom_debit_card', 'bocom_credit_card', 'psbc_debit_card', 'tailong_debit_card',
9
+ 'ccb_debit_card', 'ccb_credit_card', 'icbc_debit_card', 'icbc_credit_card', 'boc_debit_card'
10
+ ));
11
+
12
+ -- 预留账单头表以兼容未来官方账单导出;截图汇总 Excel 无官方账单头时 statement_key 保持 NULL。
13
+ CREATE TABLE "boc_bank_statements" (
14
+ statement_key TEXT PRIMARY KEY,
15
+ source_kind TEXT NOT NULL CHECK (source_kind = 'boc_debit_card'),
16
+ account_key TEXT NOT NULL,
17
+ account_masked TEXT NOT NULL,
18
+ owner_name TEXT NOT NULL,
19
+ account_type TEXT NOT NULL,
20
+ branch TEXT NOT NULL,
21
+ period_from TEXT NOT NULL,
22
+ period_to TEXT NOT NULL CHECK (period_to >= period_from),
23
+ requested_at TEXT NOT NULL,
24
+ verification_code TEXT NOT NULL,
25
+ page_count BIGINT CHECK (page_count IS NULL OR page_count > 0),
26
+ source_file TEXT NOT NULL,
27
+ source_sha256 TEXT NOT NULL,
28
+ first_batch_id TEXT NOT NULL REFERENCES import_batches(id),
29
+ last_batch_id TEXT NOT NULL REFERENCES import_batches(id),
30
+ raw_json TEXT NOT NULL CHECK (vault_json_valid(raw_json))
31
+ );
32
+
33
+ CREATE TABLE "boc_bank_transactions" (
34
+ transaction_key TEXT PRIMARY KEY,
35
+ account_key TEXT NOT NULL,
36
+ account_masked TEXT NOT NULL,
37
+ card_last_four TEXT NOT NULL CHECK (length(card_last_four) = 4),
38
+ currency TEXT NOT NULL,
39
+ occurred_at TEXT NOT NULL,
40
+ direction TEXT NOT NULL CHECK (direction IN ('in', 'out', 'neutral')),
41
+ amount_cents BIGINT NOT NULL CHECK (amount_cents >= 0),
42
+ balance_cents BIGINT NOT NULL,
43
+ counterparty TEXT NOT NULL,
44
+ counterparty_account TEXT NOT NULL,
45
+ institution TEXT NOT NULL,
46
+ description TEXT NOT NULL,
47
+ bank_txn_id TEXT NOT NULL,
48
+ transaction_card TEXT NOT NULL,
49
+ status TEXT NOT NULL,
50
+ source_file TEXT NOT NULL,
51
+ source_sha256 TEXT NOT NULL,
52
+ source_sheet TEXT NOT NULL CHECK (length(source_sheet) > 0),
53
+ row_number BIGINT NOT NULL CHECK (row_number > 0),
54
+ first_batch_id TEXT NOT NULL REFERENCES import_batches(id),
55
+ last_batch_id TEXT NOT NULL REFERENCES import_batches(id),
56
+ raw_json TEXT NOT NULL CHECK (vault_json_valid(raw_json)),
57
+ source_kind TEXT NOT NULL DEFAULT 'boc_debit_card' CHECK (source_kind = 'boc_debit_card'),
58
+ date_precision TEXT NOT NULL DEFAULT 'second' CHECK (date_precision IN ('day', 'second')),
59
+ page_number BIGINT CHECK (page_number IS NULL OR page_number > 0),
60
+ statement_key TEXT REFERENCES boc_bank_statements(statement_key),
61
+ CHECK ((direction = 'neutral' AND amount_cents = 0) OR (direction IN ('in', 'out') AND amount_cents > 0))
62
+ );
63
+
64
+ CREATE INDEX ix_boc_statement_account_period ON boc_bank_statements(account_key, period_from, period_to);
65
+ CREATE INDEX ix_boc_transaction_account_date ON boc_bank_transactions(account_key, occurred_at);
66
+ CREATE INDEX ix_boc_transaction_statement ON boc_bank_transactions(statement_key);
67
+
68
+ -- 新表按原始事实保护,只有 importer/migration 会话可写;每行审计、数据版本和
69
+ -- TRUNCATE 防护与现有银行卡完全一致。增量 SQL 同时用于旧库升级和新库逐步安装。
70
+ DO $$
71
+ DECLARE target_table text; key_column text; grant_row record;
72
+ BEGIN
73
+ FOREACH target_table IN ARRAY ARRAY['boc_bank_statements', 'boc_bank_transactions'] LOOP
74
+ key_column := CASE WHEN target_table = 'boc_bank_statements' THEN 'statement_key' ELSE 'transaction_key' END;
75
+ EXECUTE format('CREATE TRIGGER trg_%s_guard BEFORE INSERT OR UPDATE OR DELETE ON %I FOR EACH ROW EXECUTE FUNCTION vault_guard(''fact'')', target_table, target_table);
76
+ EXECUTE format('CREATE TRIGGER trg_%s_truncate BEFORE TRUNCATE ON %I FOR EACH STATEMENT EXECUTE FUNCTION vault_guard(''fact'')', target_table, target_table);
77
+ EXECUTE format('CREATE TRIGGER trg_%s_version AFTER INSERT OR UPDATE OR DELETE ON %I FOR EACH STATEMENT EXECUTE FUNCTION vault_touch()', target_table, target_table);
78
+ EXECUTE format('CREATE TRIGGER trg_%s_audit AFTER INSERT OR UPDATE OR DELETE ON %I FOR EACH ROW EXECUTE FUNCTION vault_audit(%L)', target_table, target_table, key_column);
79
+ -- 继承同类事实表的现有应用/只读权限,不写死部署角色,也不授予新的管理权限。
80
+ FOR grant_row IN SELECT grantee, privilege_type FROM information_schema.role_table_grants
81
+ WHERE table_schema = 'public' AND role_table_grants.table_name = 'bank_card_transactions'
82
+ AND grantee <> current_user AND privilege_type IN ('SELECT', 'INSERT', 'UPDATE', 'DELETE')
83
+ LOOP
84
+ EXECUTE format('GRANT %s ON TABLE %I TO %s', grant_row.privilege_type, target_table,
85
+ CASE WHEN grant_row.grantee = 'PUBLIC' THEN 'PUBLIC' ELSE quote_ident(grant_row.grantee) END);
86
+ END LOOP;
87
+ END LOOP;
88
+ END $$;
@@ -0,0 +1,88 @@
1
+ -- 江苏银行借记账户交易明细使用专属事实表,既有银行记录、批次和审计不重写。
2
+ -- 只扩展批次来源枚举;按日精度、收支方向、原始九列与原件批次外键明确保存。
3
+ ALTER TABLE import_batches DROP CONSTRAINT import_batches_source_kind_check;
4
+ ALTER TABLE import_batches ADD CONSTRAINT import_batches_source_kind_check CHECK (source_kind IN (
5
+ 'wechat_chat', 'audio_db', 'alipay', 'wechatpay', 'jd', 'taobao', 'pdd',
6
+ 'meituan', 'taobao_takeout', 'train12306', 'manual_ledger', 'legacy_md',
7
+ 'citic_credit_card', 'citic_debit_card', 'cmb_debit_card', 'cmb_credit_card',
8
+ 'bocom_debit_card', 'bocom_credit_card', 'psbc_debit_card', 'tailong_debit_card',
9
+ 'ccb_debit_card', 'ccb_credit_card', 'icbc_debit_card', 'icbc_credit_card', 'boc_debit_card', 'jsb_debit_card'
10
+ ));
11
+
12
+ CREATE TABLE "jsb_bank_statements" (
13
+ statement_key TEXT PRIMARY KEY,
14
+ source_kind TEXT NOT NULL CHECK (source_kind = 'jsb_debit_card'),
15
+ account_key TEXT NOT NULL,
16
+ account_masked TEXT NOT NULL,
17
+ owner_name TEXT NOT NULL,
18
+ account_type TEXT NOT NULL,
19
+ branch TEXT NOT NULL,
20
+ period_from TEXT NOT NULL,
21
+ period_to TEXT NOT NULL CHECK (period_to >= period_from),
22
+ requested_at TEXT NOT NULL,
23
+ verification_code TEXT NOT NULL,
24
+ page_count BIGINT NOT NULL CHECK (page_count > 0),
25
+ source_file TEXT NOT NULL,
26
+ source_sha256 TEXT NOT NULL,
27
+ first_batch_id TEXT NOT NULL REFERENCES import_batches(id),
28
+ last_batch_id TEXT NOT NULL REFERENCES import_batches(id),
29
+ raw_json TEXT NOT NULL CHECK (vault_json_valid(raw_json))
30
+ );
31
+
32
+ CREATE TABLE "jsb_bank_transactions" (
33
+ transaction_key TEXT PRIMARY KEY,
34
+ account_key TEXT NOT NULL,
35
+ account_masked TEXT NOT NULL,
36
+ card_last_four TEXT NOT NULL CHECK (length(card_last_four) = 4),
37
+ currency TEXT NOT NULL,
38
+ occurred_at TEXT NOT NULL,
39
+ direction TEXT NOT NULL CHECK (direction IN ('in', 'out', 'neutral')),
40
+ amount_cents BIGINT NOT NULL CHECK (amount_cents >= 0),
41
+ balance_cents BIGINT NOT NULL,
42
+ counterparty TEXT NOT NULL,
43
+ counterparty_account TEXT NOT NULL,
44
+ institution TEXT NOT NULL,
45
+ description TEXT NOT NULL,
46
+ bank_txn_id TEXT NOT NULL,
47
+ transaction_card TEXT NOT NULL,
48
+ status TEXT NOT NULL,
49
+ source_file TEXT NOT NULL,
50
+ source_sha256 TEXT NOT NULL,
51
+ source_sheet TEXT NOT NULL,
52
+ row_number BIGINT NOT NULL CHECK (row_number > 0),
53
+ first_batch_id TEXT NOT NULL REFERENCES import_batches(id),
54
+ last_batch_id TEXT NOT NULL REFERENCES import_batches(id),
55
+ raw_json TEXT NOT NULL CHECK (vault_json_valid(raw_json)),
56
+ source_kind TEXT NOT NULL DEFAULT 'jsb_debit_card' CHECK (source_kind = 'jsb_debit_card'),
57
+ date_precision TEXT NOT NULL DEFAULT 'day' CHECK (date_precision = 'day'),
58
+ page_number BIGINT NOT NULL CHECK (page_number > 0),
59
+ statement_key TEXT NOT NULL REFERENCES jsb_bank_statements(statement_key),
60
+ CHECK ((direction = 'neutral' AND amount_cents = 0) OR (direction IN ('in', 'out') AND amount_cents > 0))
61
+ );
62
+
63
+
64
+ CREATE INDEX ix_jsb_statement_account_period ON jsb_bank_statements(account_key, period_from, period_to);
65
+ CREATE INDEX ix_jsb_transaction_account_date ON jsb_bank_transactions(account_key, occurred_at);
66
+ CREATE INDEX ix_jsb_transaction_statement ON jsb_bank_transactions(statement_key);
67
+
68
+ -- 新表按原始事实保护,只有 importer/migration 会话可写;每行审计、数据版本和
69
+ -- TRUNCATE 防护与现有银行卡完全一致。增量 SQL 同时用于旧库升级和新库逐步安装。
70
+ DO $$
71
+ DECLARE target_table text; key_column text; grant_row record;
72
+ BEGIN
73
+ FOREACH target_table IN ARRAY ARRAY['jsb_bank_statements', 'jsb_bank_transactions'] LOOP
74
+ key_column := CASE WHEN target_table = 'jsb_bank_statements' THEN 'statement_key' ELSE 'transaction_key' END;
75
+ EXECUTE format('CREATE TRIGGER trg_%s_guard BEFORE INSERT OR UPDATE OR DELETE ON %I FOR EACH ROW EXECUTE FUNCTION vault_guard(''fact'')', target_table, target_table);
76
+ EXECUTE format('CREATE TRIGGER trg_%s_truncate BEFORE TRUNCATE ON %I FOR EACH STATEMENT EXECUTE FUNCTION vault_guard(''fact'')', target_table, target_table);
77
+ EXECUTE format('CREATE TRIGGER trg_%s_version AFTER INSERT OR UPDATE OR DELETE ON %I FOR EACH STATEMENT EXECUTE FUNCTION vault_touch()', target_table, target_table);
78
+ EXECUTE format('CREATE TRIGGER trg_%s_audit AFTER INSERT OR UPDATE OR DELETE ON %I FOR EACH ROW EXECUTE FUNCTION vault_audit(%L)', target_table, target_table, key_column);
79
+ -- 继承同类事实表的现有应用/只读权限,不写死部署角色,也不授予新的管理权限。
80
+ FOR grant_row IN SELECT grantee, privilege_type FROM information_schema.role_table_grants
81
+ WHERE table_schema = 'public' AND role_table_grants.table_name = 'bank_card_transactions'
82
+ AND grantee <> current_user AND privilege_type IN ('SELECT', 'INSERT', 'UPDATE', 'DELETE')
83
+ LOOP
84
+ EXECUTE format('GRANT %s ON TABLE %I TO %s', grant_row.privilege_type, target_table,
85
+ CASE WHEN grant_row.grantee = 'PUBLIC' THEN 'PUBLIC' ELSE quote_ident(grant_row.grantee) END);
86
+ END LOOP;
87
+ END LOOP;
88
+ END $$;
@@ -0,0 +1,88 @@
1
+ -- 民生银行借记账户交易明细使用专属事实表,既有银行记录、批次和审计不重写。
2
+ -- 只扩展批次来源枚举;按秒精度、收支方向、原始十一列与原件批次外键明确保存。
3
+ ALTER TABLE import_batches DROP CONSTRAINT import_batches_source_kind_check;
4
+ ALTER TABLE import_batches ADD CONSTRAINT import_batches_source_kind_check CHECK (source_kind IN (
5
+ 'wechat_chat', 'audio_db', 'alipay', 'wechatpay', 'jd', 'taobao', 'pdd',
6
+ 'meituan', 'taobao_takeout', 'train12306', 'manual_ledger', 'legacy_md',
7
+ 'citic_credit_card', 'citic_debit_card', 'cmb_debit_card', 'cmb_credit_card',
8
+ 'bocom_debit_card', 'bocom_credit_card', 'psbc_debit_card', 'tailong_debit_card',
9
+ 'ccb_debit_card', 'ccb_credit_card', 'icbc_debit_card', 'icbc_credit_card',
10
+ 'boc_debit_card', 'jsb_debit_card', 'cmbc_debit_card'
11
+ ));
12
+
13
+ CREATE TABLE "cmbc_bank_statements" (
14
+ statement_key TEXT PRIMARY KEY,
15
+ source_kind TEXT NOT NULL CHECK (source_kind = 'cmbc_debit_card'),
16
+ account_key TEXT NOT NULL,
17
+ account_masked TEXT NOT NULL,
18
+ owner_name TEXT NOT NULL,
19
+ account_type TEXT NOT NULL,
20
+ branch TEXT NOT NULL,
21
+ period_from TEXT NOT NULL,
22
+ period_to TEXT NOT NULL CHECK (period_to >= period_from),
23
+ requested_at TEXT NOT NULL,
24
+ verification_code TEXT NOT NULL,
25
+ page_count BIGINT NOT NULL CHECK (page_count > 0),
26
+ source_file TEXT NOT NULL,
27
+ source_sha256 TEXT NOT NULL,
28
+ first_batch_id TEXT NOT NULL REFERENCES import_batches(id),
29
+ last_batch_id TEXT NOT NULL REFERENCES import_batches(id),
30
+ raw_json TEXT NOT NULL CHECK (vault_json_valid(raw_json))
31
+ );
32
+
33
+ CREATE TABLE "cmbc_bank_transactions" (
34
+ transaction_key TEXT PRIMARY KEY,
35
+ account_key TEXT NOT NULL,
36
+ account_masked TEXT NOT NULL,
37
+ card_last_four TEXT NOT NULL CHECK (length(card_last_four) = 4),
38
+ currency TEXT NOT NULL,
39
+ occurred_at TEXT NOT NULL,
40
+ direction TEXT NOT NULL CHECK (direction IN ('in', 'out', 'neutral')),
41
+ amount_cents BIGINT NOT NULL CHECK (amount_cents >= 0),
42
+ balance_cents BIGINT NOT NULL,
43
+ counterparty TEXT NOT NULL,
44
+ counterparty_account TEXT NOT NULL,
45
+ institution TEXT NOT NULL,
46
+ description TEXT NOT NULL,
47
+ bank_txn_id TEXT NOT NULL,
48
+ transaction_card TEXT NOT NULL,
49
+ status TEXT NOT NULL,
50
+ source_file TEXT NOT NULL,
51
+ source_sha256 TEXT NOT NULL,
52
+ source_sheet TEXT NOT NULL,
53
+ row_number BIGINT NOT NULL CHECK (row_number > 0),
54
+ first_batch_id TEXT NOT NULL REFERENCES import_batches(id),
55
+ last_batch_id TEXT NOT NULL REFERENCES import_batches(id),
56
+ raw_json TEXT NOT NULL CHECK (vault_json_valid(raw_json)),
57
+ source_kind TEXT NOT NULL DEFAULT 'cmbc_debit_card' CHECK (source_kind = 'cmbc_debit_card'),
58
+ date_precision TEXT NOT NULL DEFAULT 'second' CHECK (date_precision = 'second'),
59
+ page_number BIGINT NOT NULL CHECK (page_number > 0),
60
+ statement_key TEXT NOT NULL REFERENCES cmbc_bank_statements(statement_key),
61
+ CHECK ((direction = 'neutral' AND amount_cents = 0) OR (direction IN ('in', 'out') AND amount_cents > 0))
62
+ );
63
+
64
+ CREATE INDEX ix_cmbc_statement_account_period ON cmbc_bank_statements(account_key, period_from, period_to);
65
+ CREATE INDEX ix_cmbc_transaction_account_date ON cmbc_bank_transactions(account_key, occurred_at);
66
+ CREATE INDEX ix_cmbc_transaction_statement ON cmbc_bank_transactions(statement_key);
67
+
68
+ -- 新表按原始事实保护,只有 importer/migration 会话可写;每行审计、数据版本和
69
+ -- TRUNCATE 防护与现有银行卡完全一致。增量 SQL 同时用于旧库升级和新库逐步安装。
70
+ DO $$
71
+ DECLARE target_table text; key_column text; grant_row record;
72
+ BEGIN
73
+ FOREACH target_table IN ARRAY ARRAY['cmbc_bank_statements', 'cmbc_bank_transactions'] LOOP
74
+ key_column := CASE WHEN target_table = 'cmbc_bank_statements' THEN 'statement_key' ELSE 'transaction_key' END;
75
+ EXECUTE format('CREATE TRIGGER trg_%s_guard BEFORE INSERT OR UPDATE OR DELETE ON %I FOR EACH ROW EXECUTE FUNCTION vault_guard(''fact'')', target_table, target_table);
76
+ EXECUTE format('CREATE TRIGGER trg_%s_truncate BEFORE TRUNCATE ON %I FOR EACH STATEMENT EXECUTE FUNCTION vault_guard(''fact'')', target_table, target_table);
77
+ EXECUTE format('CREATE TRIGGER trg_%s_version AFTER INSERT OR UPDATE OR DELETE ON %I FOR EACH STATEMENT EXECUTE FUNCTION vault_touch()', target_table, target_table);
78
+ EXECUTE format('CREATE TRIGGER trg_%s_audit AFTER INSERT OR UPDATE OR DELETE ON %I FOR EACH ROW EXECUTE FUNCTION vault_audit(%L)', target_table, target_table, key_column);
79
+ -- 继承同类事实表的现有应用/只读权限,不写死部署角色,也不授予新的管理权限。
80
+ FOR grant_row IN SELECT grantee, privilege_type FROM information_schema.role_table_grants
81
+ WHERE table_schema = 'public' AND role_table_grants.table_name = 'bank_card_transactions'
82
+ AND grantee <> current_user AND privilege_type IN ('SELECT', 'INSERT', 'UPDATE', 'DELETE')
83
+ LOOP
84
+ EXECUTE format('GRANT %s ON TABLE %I TO %s', grant_row.privilege_type, target_table,
85
+ CASE WHEN grant_row.grantee = 'PUBLIC' THEN 'PUBLIC' ELSE quote_ident(grant_row.grantee) END);
86
+ END LOOP;
87
+ END LOOP;
88
+ END $$;
@@ -0,0 +1,88 @@
1
+ -- 杭州银行借记账户交易明细使用专属事实表,既有银行记录、批次和审计不重写。
2
+ -- 只扩展批次来源枚举;按日精度、收支方向、原始七列与原件批次外键明确保存。
3
+ ALTER TABLE import_batches DROP CONSTRAINT import_batches_source_kind_check;
4
+ ALTER TABLE import_batches ADD CONSTRAINT import_batches_source_kind_check CHECK (source_kind IN (
5
+ 'wechat_chat', 'audio_db', 'alipay', 'wechatpay', 'jd', 'taobao', 'pdd',
6
+ 'meituan', 'taobao_takeout', 'train12306', 'manual_ledger', 'legacy_md',
7
+ 'citic_credit_card', 'citic_debit_card', 'cmb_debit_card', 'cmb_credit_card',
8
+ 'bocom_debit_card', 'bocom_credit_card', 'psbc_debit_card', 'tailong_debit_card',
9
+ 'ccb_debit_card', 'ccb_credit_card', 'icbc_debit_card', 'icbc_credit_card',
10
+ 'boc_debit_card', 'jsb_debit_card', 'cmbc_debit_card', 'hzbank_debit_card'
11
+ ));
12
+
13
+ CREATE TABLE "hzbank_bank_statements" (
14
+ statement_key TEXT PRIMARY KEY,
15
+ source_kind TEXT NOT NULL CHECK (source_kind = 'hzbank_debit_card'),
16
+ account_key TEXT NOT NULL,
17
+ account_masked TEXT NOT NULL,
18
+ owner_name TEXT NOT NULL,
19
+ account_type TEXT NOT NULL,
20
+ branch TEXT NOT NULL,
21
+ period_from TEXT NOT NULL,
22
+ period_to TEXT NOT NULL CHECK (period_to >= period_from),
23
+ requested_at TEXT NOT NULL,
24
+ verification_code TEXT NOT NULL,
25
+ page_count BIGINT NOT NULL CHECK (page_count > 0),
26
+ source_file TEXT NOT NULL,
27
+ source_sha256 TEXT NOT NULL,
28
+ first_batch_id TEXT NOT NULL REFERENCES import_batches(id),
29
+ last_batch_id TEXT NOT NULL REFERENCES import_batches(id),
30
+ raw_json TEXT NOT NULL CHECK (vault_json_valid(raw_json))
31
+ );
32
+
33
+ CREATE TABLE "hzbank_bank_transactions" (
34
+ transaction_key TEXT PRIMARY KEY,
35
+ account_key TEXT NOT NULL,
36
+ account_masked TEXT NOT NULL,
37
+ card_last_four TEXT NOT NULL CHECK (length(card_last_four) = 4),
38
+ currency TEXT NOT NULL,
39
+ occurred_at TEXT NOT NULL,
40
+ direction TEXT NOT NULL CHECK (direction IN ('in', 'out', 'neutral')),
41
+ amount_cents BIGINT NOT NULL CHECK (amount_cents >= 0),
42
+ balance_cents BIGINT NOT NULL,
43
+ counterparty TEXT NOT NULL,
44
+ counterparty_account TEXT NOT NULL,
45
+ institution TEXT NOT NULL,
46
+ description TEXT NOT NULL,
47
+ bank_txn_id TEXT NOT NULL,
48
+ transaction_card TEXT NOT NULL,
49
+ status TEXT NOT NULL,
50
+ source_file TEXT NOT NULL,
51
+ source_sha256 TEXT NOT NULL,
52
+ source_sheet TEXT NOT NULL,
53
+ row_number BIGINT NOT NULL CHECK (row_number > 0),
54
+ first_batch_id TEXT NOT NULL REFERENCES import_batches(id),
55
+ last_batch_id TEXT NOT NULL REFERENCES import_batches(id),
56
+ raw_json TEXT NOT NULL CHECK (vault_json_valid(raw_json)),
57
+ source_kind TEXT NOT NULL DEFAULT 'hzbank_debit_card' CHECK (source_kind = 'hzbank_debit_card'),
58
+ date_precision TEXT NOT NULL DEFAULT 'day' CHECK (date_precision = 'day'),
59
+ page_number BIGINT NOT NULL CHECK (page_number > 0),
60
+ statement_key TEXT NOT NULL REFERENCES hzbank_bank_statements(statement_key),
61
+ CHECK ((direction = 'neutral' AND amount_cents = 0) OR (direction IN ('in', 'out') AND amount_cents > 0))
62
+ );
63
+
64
+ CREATE INDEX ix_hzbank_statement_account_period ON hzbank_bank_statements(account_key, period_from, period_to);
65
+ CREATE INDEX ix_hzbank_transaction_account_date ON hzbank_bank_transactions(account_key, occurred_at);
66
+ CREATE INDEX ix_hzbank_transaction_statement ON hzbank_bank_transactions(statement_key);
67
+
68
+ -- 新表按原始事实保护,只有 importer/migration 会话可写;每行审计、数据版本和
69
+ -- TRUNCATE 防护与现有银行卡完全一致。增量 SQL 同时用于旧库升级和新库逐步安装。
70
+ DO $$
71
+ DECLARE target_table text; key_column text; grant_row record;
72
+ BEGIN
73
+ FOREACH target_table IN ARRAY ARRAY['hzbank_bank_statements', 'hzbank_bank_transactions'] LOOP
74
+ key_column := CASE WHEN target_table = 'hzbank_bank_statements' THEN 'statement_key' ELSE 'transaction_key' END;
75
+ EXECUTE format('CREATE TRIGGER trg_%s_guard BEFORE INSERT OR UPDATE OR DELETE ON %I FOR EACH ROW EXECUTE FUNCTION vault_guard(''fact'')', target_table, target_table);
76
+ EXECUTE format('CREATE TRIGGER trg_%s_truncate BEFORE TRUNCATE ON %I FOR EACH STATEMENT EXECUTE FUNCTION vault_guard(''fact'')', target_table, target_table);
77
+ EXECUTE format('CREATE TRIGGER trg_%s_version AFTER INSERT OR UPDATE OR DELETE ON %I FOR EACH STATEMENT EXECUTE FUNCTION vault_touch()', target_table, target_table);
78
+ EXECUTE format('CREATE TRIGGER trg_%s_audit AFTER INSERT OR UPDATE OR DELETE ON %I FOR EACH ROW EXECUTE FUNCTION vault_audit(%L)', target_table, target_table, key_column);
79
+ -- 继承同类事实表的现有应用/只读权限,不写死部署角色,也不授予新的管理权限。
80
+ FOR grant_row IN SELECT grantee, privilege_type FROM information_schema.role_table_grants
81
+ WHERE table_schema = 'public' AND role_table_grants.table_name = 'bank_card_transactions'
82
+ AND grantee <> current_user AND privilege_type IN ('SELECT', 'INSERT', 'UPDATE', 'DELETE')
83
+ LOOP
84
+ EXECUTE format('GRANT %s ON TABLE %I TO %s', grant_row.privilege_type, target_table,
85
+ CASE WHEN grant_row.grantee = 'PUBLIC' THEN 'PUBLIC' ELSE quote_ident(grant_row.grantee) END);
86
+ END LOOP;
87
+ END LOOP;
88
+ END $$;