@seasonkoh/webaz 0.1.28 → 0.1.30
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.
- package/README.md +3 -2
- package/README.zh-CN.md +7 -6
- package/dist/bond-refund-blockers.js +50 -0
- package/dist/bond-slash.js +100 -0
- package/dist/bond-terms.js +31 -0
- package/dist/currency.js +16 -0
- package/dist/deposit-rails.js +52 -0
- package/dist/direct-pay-aml-monitor.js +67 -0
- package/dist/direct-pay-aml-review.js +40 -0
- package/dist/direct-pay-base-bond-entry.js +5 -0
- package/dist/direct-pay-bond-rail-clearance.js +99 -0
- package/dist/direct-pay-cancel-refund.js +160 -0
- package/dist/direct-pay-compliance-ingress.js +145 -0
- package/dist/direct-pay-controls.js +136 -0
- package/dist/direct-pay-create.js +231 -0
- package/dist/direct-pay-deferral-quota.js +43 -0
- package/dist/direct-pay-disclosures.js +50 -0
- package/dist/direct-pay-eligibility.js +46 -0
- package/dist/direct-pay-fee-ar.js +241 -0
- package/dist/direct-pay-fee-prepay-request.js +80 -0
- package/dist/direct-pay-launch-readiness.js +108 -0
- package/dist/direct-pay-launch-summary.js +68 -0
- package/dist/direct-pay-ledger.js +94 -0
- package/dist/direct-pay-returns.js +104 -0
- package/dist/direct-pay-stock.js +9 -0
- package/dist/direct-receive-account-qr.js +77 -0
- package/dist/direct-receive-accounts.js +82 -0
- package/dist/direct-receive-deferral.js +171 -0
- package/dist/direct-receive-deposits.js +365 -0
- package/dist/direct-receive-payment-instruction.js +26 -0
- package/dist/free-shipping.js +37 -0
- package/dist/fx-rates.js +78 -0
- package/dist/layer0-foundation/L0-1-database/schema.js +777 -1
- package/dist/layer0-foundation/L0-2-state-machine/engine.js +1 -0
- package/dist/layer0-foundation/L0-2-state-machine/genuine-sale.js +15 -5
- package/dist/layer0-foundation/L0-2-state-machine/transitions.js +114 -0
- package/dist/layer0-foundation/L0-5-manifest/manifest.js +1 -1
- package/dist/layer1-agent/L1-1-mcp-server/cli.js +64 -0
- package/dist/layer1-agent/L1-1-mcp-server/network-mode.js +11 -0
- package/dist/layer1-agent/L1-1-mcp-server/server.js +99 -32
- package/dist/layer2-business/L2-6-notifications/notification-engine.js +110 -41
- package/dist/layer3-trust/L3-1-dispute-engine/dispute-engine.js +133 -31
- package/dist/layer3-trust/L3-1-dispute-engine/evidence-storage.js +16 -4
- package/dist/layer3-trust/L3-1-dispute-engine/mutual-cancel.js +156 -0
- package/dist/layer4-economics/L4-4-skill-market/skill-engine.js +4 -4
- package/dist/ledger.js +12 -3
- package/dist/mcp.js +23 -4
- package/dist/merchant-bond-domain.js +64 -0
- package/dist/merchant-bond-exposure.js +78 -0
- package/dist/merchant-bond-watcher.js +26 -0
- package/dist/payment-rails.js +29 -0
- package/dist/platform-receive-accounts.js +94 -0
- package/dist/product-verification.js +93 -0
- package/dist/pwa/acp-feed.js +3 -2
- package/dist/pwa/arbitration-read-admin.js +37 -0
- package/dist/pwa/arbitrator-lifecycle.js +100 -0
- package/dist/pwa/contract-fingerprint.js +18 -0
- package/dist/pwa/direct-pay-guards.js +20 -0
- package/dist/pwa/direct-pay-order-redaction.js +42 -0
- package/dist/pwa/endpoint-actions.js +3 -0
- package/dist/pwa/human-presence.js +2 -6
- package/dist/pwa/public/app-account.js +9 -9
- package/dist/pwa/public/app-admin-disputes.js +55 -0
- package/dist/pwa/public/app-agent-appeal.js +90 -0
- package/dist/pwa/public/app-agent-approvals.js +93 -0
- package/dist/pwa/public/app-agent-pair.js +127 -0
- package/dist/pwa/public/app-ai.js +10 -10
- package/dist/pwa/public/app-arbitrator-admin.js +87 -0
- package/dist/pwa/public/app-arbitrator-entry.js +9 -0
- package/dist/pwa/public/app-bond-deferral-ui.js +9 -0
- package/dist/pwa/public/app-bond-refund-ui.js +66 -0
- package/dist/pwa/public/app-bond-slash-ui.js +74 -0
- package/dist/pwa/public/app-bond-terms-ui.js +23 -0
- package/dist/pwa/public/app-bond-ui.js +108 -0
- package/dist/pwa/public/app-chat-poll.js +29 -0
- package/dist/pwa/public/app-contribution-hub.js +23 -0
- package/dist/pwa/public/app-create-kinds.js +17 -0
- package/dist/pwa/public/app-direct-pay-accounts.js +141 -0
- package/dist/pwa/public/app-direct-pay-buyer.js +72 -0
- package/dist/pwa/public/app-direct-pay-cancel-refund.js +72 -0
- package/dist/pwa/public/app-direct-pay-compliance.js +67 -0
- package/dist/pwa/public/app-direct-pay-copy.js +12 -0
- package/dist/pwa/public/app-direct-pay-deferral-admin.js +72 -0
- package/dist/pwa/public/app-direct-pay-deferral.js +61 -0
- package/dist/pwa/public/app-direct-pay-fee-center.js +33 -0
- package/dist/pwa/public/app-direct-pay-fee-history.js +39 -0
- package/dist/pwa/public/app-direct-pay-fee-ops.js +112 -0
- package/dist/pwa/public/app-direct-pay-fee-request.js +81 -0
- package/dist/pwa/public/app-direct-pay-fee-requests-admin.js +70 -0
- package/dist/pwa/public/app-direct-pay-memo.js +14 -0
- package/dist/pwa/public/app-direct-pay-negotiation.js +35 -0
- package/dist/pwa/public/app-direct-pay-pay.js +15 -0
- package/dist/pwa/public/app-direct-pay-paymodal.js +32 -0
- package/dist/pwa/public/app-direct-pay-product-verify.js +103 -0
- package/dist/pwa/public/app-direct-pay-readiness.js +38 -0
- package/dist/pwa/public/app-direct-pay-reconcile.js +19 -0
- package/dist/pwa/public/app-direct-pay-returns.js +56 -0
- package/dist/pwa/public/app-direct-pay-reveal.js +82 -0
- package/dist/pwa/public/app-direct-pay-sales-report.js +70 -0
- package/dist/pwa/public/app-direct-pay-store-verify.js +100 -0
- package/dist/pwa/public/app-direct-pay.js +226 -0
- package/dist/pwa/public/app-discover.js +20 -20
- package/dist/pwa/public/app-dispute-close-ui.js +38 -0
- package/dist/pwa/public/app-external-links.js +32 -0
- package/dist/pwa/public/app-free-shipping-ui.js +29 -0
- package/dist/pwa/public/app-gmv-rail-split.js +12 -0
- package/dist/pwa/public/app-listing-commerce-ui.js +72 -0
- package/dist/pwa/public/app-listings.js +4 -4
- package/dist/pwa/public/app-mutual-cancel.js +54 -0
- package/dist/pwa/public/app-notif-templates-orders.js +43 -0
- package/dist/pwa/public/app-notif-templates.js +22 -0
- package/dist/pwa/public/app-order-accept-ui.js +158 -0
- package/dist/pwa/public/app-order-errors.js +50 -0
- package/dist/pwa/public/app-order-labels.js +19 -0
- package/dist/pwa/public/app-order-rail-filter.js +26 -0
- package/dist/pwa/public/app-platform-receive-accounts.js +140 -0
- package/dist/pwa/public/app-poll-governor.js +22 -0
- package/dist/pwa/public/app-prelaunch-waz.js +39 -0
- package/dist/pwa/public/app-price.js +55 -0
- package/dist/pwa/public/app-product-media.js +15 -0
- package/dist/pwa/public/app-profile.js +10 -10
- package/dist/pwa/public/app-purchase-terms-ui.js +68 -0
- package/dist/pwa/public/app-sale-regions-ui.js +38 -0
- package/dist/pwa/public/app-seller.js +5 -5
- package/dist/pwa/public/app-shop.js +19 -19
- package/dist/pwa/public/app-trade-tax-ui.js +33 -0
- package/dist/pwa/public/app.js +264 -295
- package/dist/pwa/public/i18n.js +1068 -197
- package/dist/pwa/public/index.html +58 -0
- package/dist/pwa/public/openapi.json +1845 -653
- package/dist/pwa/public/style.css +3 -0
- package/dist/pwa/routes/admin-analytics.js +4 -2
- package/dist/pwa/routes/admin-direct-receive-deposits.js +533 -0
- package/dist/pwa/routes/admin-protocol-params.js +16 -0
- package/dist/pwa/routes/admin-reports.js +31 -5
- package/dist/pwa/routes/agent-governance.js +1 -1
- package/dist/pwa/routes/agent-grants.js +253 -32
- package/dist/pwa/routes/analytics.js +2 -0
- package/dist/pwa/routes/arbitrator.js +67 -14
- package/dist/pwa/routes/bond-seller.js +162 -0
- package/dist/pwa/routes/buyer-feeds.js +2 -1
- package/dist/pwa/routes/chat.js +6 -1
- package/dist/pwa/routes/dashboards.js +2 -1
- package/dist/pwa/routes/direct-pay-availability.js +196 -0
- package/dist/pwa/routes/direct-pay-cancel-refund.js +111 -0
- package/dist/pwa/routes/direct-pay-disclosure-acks.js +79 -0
- package/dist/pwa/routes/direct-pay-pending-accept.js +222 -0
- package/dist/pwa/routes/direct-pay-returns.js +74 -0
- package/dist/pwa/routes/direct-pay-timeouts.js +248 -0
- package/dist/pwa/routes/direct-receive-accounts.js +155 -0
- package/dist/pwa/routes/direct-receive-payment-instructions.js +45 -0
- package/dist/pwa/routes/disputes-read.js +20 -6
- package/dist/pwa/routes/disputes-write.js +91 -33
- package/dist/pwa/routes/external-anchors.js +4 -2
- package/dist/pwa/routes/fee-prepay-requests.js +66 -0
- package/dist/pwa/routes/fx.js +12 -0
- package/dist/pwa/routes/governance-onboarding.js +46 -8
- package/dist/pwa/routes/leaderboard.js +47 -9
- package/dist/pwa/routes/listings.js +2 -2
- package/dist/pwa/routes/logistics.js +6 -2
- package/dist/pwa/routes/manifests.js +38 -0
- package/dist/pwa/routes/me-data.js +5 -2
- package/dist/pwa/routes/mutual-cancel.js +62 -0
- package/dist/pwa/routes/orders-action.js +297 -16
- package/dist/pwa/routes/orders-create.js +21 -6
- package/dist/pwa/routes/orders-read.js +106 -8
- package/dist/pwa/routes/p2p-products.js +2 -2
- package/dist/pwa/routes/platform-receive-accounts.js +111 -0
- package/dist/pwa/routes/products-create.js +15 -4
- package/dist/pwa/routes/products-links.js +34 -0
- package/dist/pwa/routes/products-list.js +2 -1
- package/dist/pwa/routes/products-update.js +37 -3
- package/dist/pwa/routes/profile-identity.js +4 -2
- package/dist/pwa/routes/promoter.js +3 -0
- package/dist/pwa/routes/referral.js +4 -0
- package/dist/pwa/routes/returns.js +60 -4
- package/dist/pwa/routes/rewards-apply.js +10 -5
- package/dist/pwa/routes/rewards-clearing-mature.js +96 -0
- package/dist/pwa/routes/rewards-escrow-expire.js +6 -2
- package/dist/pwa/routes/seller-directpay-report.js +110 -0
- package/dist/pwa/routes/seller-quota.js +5 -1
- package/dist/pwa/routes/shipping-templates.js +219 -0
- package/dist/pwa/routes/shops.js +2 -1
- package/dist/pwa/routes/snf.js +4 -1
- package/dist/pwa/routes/url-claim.js +2 -2
- package/dist/pwa/routes/users-public.js +8 -0
- package/dist/pwa/routes/wallet-read.js +3 -0
- package/dist/pwa/routes/webauthn.js +3 -3
- package/dist/pwa/server.js +112 -132
- package/dist/runtime/agent-grant-scopes.js +69 -1
- package/dist/runtime/webaz-schema-helpers.js +161 -3
- package/dist/sale-regions.js +116 -0
- package/dist/shipping-templates.js +119 -0
- package/dist/store-verification.js +77 -0
- package/dist/trade-tax.js +99 -0
- package/dist/trade-terms.js +76 -0
- package/dist/version.js +1 -1
- package/package.json +128 -2
|
@@ -41,7 +41,7 @@ export function initDatabase() {
|
|
|
41
41
|
title TEXT NOT NULL,
|
|
42
42
|
description TEXT NOT NULL,
|
|
43
43
|
price REAL NOT NULL,
|
|
44
|
-
currency TEXT DEFAULT '
|
|
44
|
+
currency TEXT DEFAULT 'WAZ', -- 协议内部模拟单位(WAZ);旧默认 'DCP' 已翻转 + 存量回填(见迁移段),existing-DB 建单路径亦显式写 WAZ
|
|
45
45
|
stock INTEGER DEFAULT 1,
|
|
46
46
|
category TEXT,
|
|
47
47
|
images TEXT DEFAULT '[]', -- JSON 数组,存图片路径
|
|
@@ -93,6 +93,15 @@ export function initDatabase() {
|
|
|
93
93
|
shipping_address TEXT, -- 收货地址(JSON)
|
|
94
94
|
notes TEXT, -- 买家备注
|
|
95
95
|
|
|
96
|
+
-- PR-5b-0: direct_p2p 建单时的【入口控制 policy 快照】(冻结当时的 cfg + 判定码;5b wiring 才写入,本 PR 仅建列)。
|
|
97
|
+
-- 全部 additive nullable;布尔以 0/1 存,cap 以整数 base-units 存。仅 direct_p2p 单写,其它 rail 恒 NULL。
|
|
98
|
+
direct_pay_enabled_snapshot INTEGER, -- 建单时 direct_pay.enabled 快照(0/1)
|
|
99
|
+
direct_pay_rail_breaker_snapshot INTEGER, -- 建单时 rail_breaker_tripped 快照(0/1)
|
|
100
|
+
direct_pay_region_snapshot TEXT, -- 建单时 region 快照
|
|
101
|
+
direct_pay_region_allowlist_snapshot TEXT, -- 建单时 region_allowlist 快照(CSV/JSON 文本)
|
|
102
|
+
direct_pay_per_tx_cap_units_snapshot INTEGER, -- 建单时单笔上限快照(整数 policy base-units;WebAZ 记录订单总额天花板,非场外实付控制)
|
|
103
|
+
direct_pay_seller_breaker_snapshot INTEGER, -- 建单时 sellerBreakerTripped 快照(0/1)
|
|
104
|
+
direct_pay_decision_code TEXT, -- 建单时控制面判定码快照(成功通常 NULL / 'OK';拒绝码见 DirectPayControlReason)
|
|
96
105
|
created_at TEXT DEFAULT (datetime('now')),
|
|
97
106
|
updated_at TEXT DEFAULT (datetime('now'))
|
|
98
107
|
);
|
|
@@ -172,6 +181,471 @@ export function initDatabase() {
|
|
|
172
181
|
created_at TEXT DEFAULT (datetime('now'))
|
|
173
182
|
);
|
|
174
183
|
|
|
184
|
+
/* ──────────────────────────────────────────
|
|
185
|
+
直接支付(Direct Pay)Rail 1 · 非托管撮合 + 信誉轨
|
|
186
|
+
本金(货款)不经协议;以下表仅记录【资格/担保物/费用质押/风控/AML/披露】元数据。
|
|
187
|
+
设计稿: docs/modules/DIRECT-PAYMENT-MODULE-DESIGN.INTERNAL.md (Rev 2026-06-27e)
|
|
188
|
+
────────────────────────────────────────── */
|
|
189
|
+
|
|
190
|
+
-- 卖家"直接收款"资格(一真人一资格;档位 T0/T1/T2 决定配额)
|
|
191
|
+
CREATE TABLE IF NOT EXISTS direct_receive_privileges (
|
|
192
|
+
user_id TEXT PRIMARY KEY REFERENCES users(id),
|
|
193
|
+
status TEXT NOT NULL DEFAULT 'none', -- none | active | suspended
|
|
194
|
+
tier TEXT NOT NULL DEFAULT 'T0', -- T0 | T1 | T2
|
|
195
|
+
suspended_reason TEXT,
|
|
196
|
+
granted_at TEXT,
|
|
197
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
-- base bond = 履约担保物(merchant performance security deposit);法律/会计上独立于买家货款。
|
|
201
|
+
-- currency 必须【显式传入】,只允许 usdc | fiat(外部真实资产,生产收款经 deposit-rail 网关 legal-review gated;本 PR/4b 仅非生产确认)。
|
|
202
|
+
-- WAZ【未启用】为 base-bond currency —— 无默认值 + CHECK 双重拦截;domain helper openDeposit 亦拒(4c 前路由不得 raw-insert 绕过)。
|
|
203
|
+
CREATE TABLE IF NOT EXISTS direct_receive_deposits (
|
|
204
|
+
id TEXT PRIMARY KEY,
|
|
205
|
+
user_id TEXT NOT NULL REFERENCES users(id),
|
|
206
|
+
tier TEXT NOT NULL DEFAULT 'T0',
|
|
207
|
+
required_amount REAL NOT NULL, -- 该档要求的 bond
|
|
208
|
+
amount REAL NOT NULL DEFAULT 0, -- 实际到位
|
|
209
|
+
currency TEXT NOT NULL CHECK (currency IN ('usdc','fiat')), -- 显式传入,无默认;只允许 usdc|fiat;WAZ 未启用(生产收款 legal-review gated)
|
|
210
|
+
deposit_rail TEXT NOT NULL DEFAULT 'manual', -- manual(仅 test/非生产) | usdc_onchain | fiat_psp (后两者 GATED)
|
|
211
|
+
external_ref TEXT, -- 链上 tx / PSP 凭证引用
|
|
212
|
+
status TEXT NOT NULL DEFAULT 'pending',-- pending|confirmed|locked|insufficient|expired|refunding|refunded|slashed
|
|
213
|
+
confirmed_at TEXT,
|
|
214
|
+
locked_at TEXT,
|
|
215
|
+
released_at TEXT,
|
|
216
|
+
production_receipt_confirmed_at TEXT, -- 仅【真实生产收款】(USDC 链上 / 法币 PSP)确认时置;manual/非生产恒 NULL。生产 go-live 必须要求非 NULL,杜绝 manual rail 冒充 base bond 到位。
|
|
217
|
+
-- PR-4b-1 生产收款 provenance 快照(仅在 production_receipt_confirmed_at 一并写;manual/非生产恒 NULL)。
|
|
218
|
+
-- 刻意 production_ 前缀以区别于运营列 currency/deposit_rail/external_ref(后三者 manual 轨也用)。本 PR 只加列,无写入方。
|
|
219
|
+
production_receipt_ref TEXT, -- 生产收款凭证引用(链上 tx / PSP receipt id);独立于 external_ref(manual 也写)
|
|
220
|
+
production_rail_id TEXT, -- 确认时的 legal-cleared 生产轨 id 快照(usdc_onchain / fiat_psp)
|
|
221
|
+
production_jurisdiction TEXT, -- 法务管辖区快照(担保物定性所适用法域)
|
|
222
|
+
production_policy_version TEXT, -- 确认时生效的 base-bond/合规 policy 版本快照(审计可追溯)
|
|
223
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
224
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
-- 卖家自填【收款说明】(展示给买家的纯文本/handle/label)。这【不是】payment rail / escrow / PSP / 币种路由:
|
|
228
|
+
-- WebAZ 只存储 + 下单时快照,绝不验证/路由/托管/判断币种/做 allowlist。下单读取卖家当前 active 一条,快照进 order。
|
|
229
|
+
CREATE TABLE IF NOT EXISTS direct_receive_payment_instructions (
|
|
230
|
+
id TEXT PRIMARY KEY,
|
|
231
|
+
seller_id TEXT NOT NULL REFERENCES users(id),
|
|
232
|
+
instruction TEXT NOT NULL, -- 卖家自填、展示给买家的收款说明(场外结算用;WebAZ 不解析)
|
|
233
|
+
label TEXT, -- 可选短标签(如 "PayNow" / "Bank")
|
|
234
|
+
status TEXT NOT NULL DEFAULT 'active',-- active | inactive
|
|
235
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
236
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
-- 直付多收款账号(direct_receive_accounts,Phase B):卖家可维护【多个】收款方式,每个自带币种 + 可选二维码图。
|
|
240
|
+
-- ⚠️ 与单条 payment_instruction 同性质:WebAZ 只【存储 + 展示】卖家自填内容,【绝不】验证/路由/托管/判断币种,
|
|
241
|
+
-- 也不解析二维码。currency 仅供买家侧换算展示(FX 支持才显 ≈本地);qr_image_ref 指向硬化图片端点(Phase C)。
|
|
242
|
+
-- 多行模型:一个 seller 可有【多个】active(买家下单自选其一),与单 instruction 的"至多一条 active"不同。
|
|
243
|
+
CREATE TABLE IF NOT EXISTS direct_receive_accounts (
|
|
244
|
+
id TEXT PRIMARY KEY,
|
|
245
|
+
seller_id TEXT NOT NULL REFERENCES users(id),
|
|
246
|
+
method TEXT, -- 收款方式名(卖家自填,如 PayNow / GCash / PromptPay / Bank)
|
|
247
|
+
currency TEXT, -- 该账号结算币种(卖家声明;买家侧按此换算,FX 支持则显 ≈本地)
|
|
248
|
+
instruction TEXT NOT NULL, -- 展示给买家的收款明细(账号 / 钱包 ID / 链接;WebAZ 不解析)
|
|
249
|
+
label TEXT, -- 可选短标签
|
|
250
|
+
qr_image_ref TEXT, -- 可选收款二维码图片引用(Phase C 填;硬化端点服务,绝不解析)
|
|
251
|
+
status TEXT NOT NULL DEFAULT 'active',-- active | inactive
|
|
252
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
253
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
-- 平台(WebAZ)收款方式(admin 管理,可多个 active):卖家申请充值【平台服务费】时看到、据此线下付款。
|
|
257
|
+
-- ⚠️ 这是【平台侧】收款配置,不是卖家账号。改它 = 改平台收款流向 → 端点 root + Passkey 门。
|
|
258
|
+
-- instruction 是平台公开收款明细,给卖家看(非披露门)。qr 内联存(admin 精选、少量;写时 validateQrDataUri 校验 png/webp≤64KB)。
|
|
259
|
+
CREATE TABLE IF NOT EXISTS platform_receive_accounts (
|
|
260
|
+
id TEXT PRIMARY KEY,
|
|
261
|
+
label TEXT, -- 短标签(如 "PayNow-主" / "USDC-Base")
|
|
262
|
+
method TEXT, -- 收款方式(PayNow / Bank / USDC…)
|
|
263
|
+
currency TEXT, -- 币种(卖家据此付)
|
|
264
|
+
instruction TEXT NOT NULL, -- 平台收款明细(账号 / 钱包地址 / 链接),展示给卖家
|
|
265
|
+
qr_data_uri TEXT, -- 可选收款码,内联 data:image/(png|webp);base64(写时校验;≤64KB)
|
|
266
|
+
status TEXT NOT NULL DEFAULT 'active',-- active | inactive
|
|
267
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
268
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
-- 直付收款二维码图(Phase C):卖家收款码原始字节。【不可变、按内容寻址(per-seller)】—— ref = sha256(bytes),
|
|
272
|
+
-- replace = 插新行,旧行永不改/删(触发器强制),这样订单可在建单时快照 (ref, seller_id) 并在 D1/D2 ack 后取回【当时那一版】QR。
|
|
273
|
+
-- ⚠️ 主键 = (ref, seller_id):内容寻址【按卖家隔离】。两个卖家上传【相同】字节时各得一行(否则 INSERT OR IGNORE
|
|
274
|
+
-- 只留首个卖家的行,第二个卖家 owner-scoped 读 = 命中不到 → "上传成功但预览 404")。dedup 只在同一卖家内发生。
|
|
275
|
+
-- WebAZ 只存字节、经硬化端点转发,绝不解析二维码含义 / 不验证收款方 / 不路由资金。仅 png|webp、解码 ≤64KB。
|
|
276
|
+
CREATE TABLE IF NOT EXISTS direct_receive_account_qr_images (
|
|
277
|
+
ref TEXT NOT NULL, -- = sha256(decoded bytes),内容寻址、不可变
|
|
278
|
+
account_id TEXT NOT NULL REFERENCES direct_receive_accounts(id),
|
|
279
|
+
seller_id TEXT NOT NULL REFERENCES users(id),
|
|
280
|
+
mime TEXT NOT NULL, -- 'image/png' | 'image/webp'(仅此二者)
|
|
281
|
+
data_b64 TEXT NOT NULL, -- base64 原始字节(硬化端点 forced content-type + nosniff + no-store 转发)
|
|
282
|
+
byte_len INTEGER NOT NULL, -- 解码后字节数(≤ 65536)
|
|
283
|
+
sha256 TEXT NOT NULL, -- = ref(冗余留证)
|
|
284
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
285
|
+
PRIMARY KEY (ref, seller_id) -- per-seller 内容寻址:同字节跨卖家各存一行
|
|
286
|
+
);
|
|
287
|
+
CREATE INDEX IF NOT EXISTS idx_dr_qr_account ON direct_receive_account_qr_images(account_id);
|
|
288
|
+
CREATE TRIGGER IF NOT EXISTS trg_dr_qr_no_update BEFORE UPDATE ON direct_receive_account_qr_images BEGIN SELECT RAISE(ABORT, 'direct_receive_account_qr_images is content-addressed & immutable (UPDATE forbidden)'); END;
|
|
289
|
+
CREATE TRIGGER IF NOT EXISTS trg_dr_qr_no_delete BEFORE DELETE ON direct_receive_account_qr_images BEGIN SELECT RAISE(ABORT, 'direct_receive_account_qr_images is immutable (DELETE forbidden — keep for order snapshots)'); END;
|
|
290
|
+
|
|
291
|
+
-- 直付收款账号审计(Phase C):append-only,记事件+account/qr ref,【绝不】写 raw instruction / raw QR。
|
|
292
|
+
CREATE TABLE IF NOT EXISTS direct_receive_account_events (
|
|
293
|
+
id TEXT PRIMARY KEY,
|
|
294
|
+
account_id TEXT NOT NULL,
|
|
295
|
+
seller_id TEXT NOT NULL,
|
|
296
|
+
event_type TEXT NOT NULL, -- account_added | account_updated | account_deactivated | qr_uploaded
|
|
297
|
+
qr_ref TEXT, -- qr 事件时的 ref(= sha256);非 qr 事件为 NULL。绝无 raw 内容
|
|
298
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
299
|
+
);
|
|
300
|
+
CREATE INDEX IF NOT EXISTS idx_dr_acct_events_account ON direct_receive_account_events(account_id);
|
|
301
|
+
CREATE TRIGGER IF NOT EXISTS trg_dr_acct_events_no_update BEFORE UPDATE ON direct_receive_account_events BEGIN SELECT RAISE(ABORT, 'direct_receive_account_events is append-only (UPDATE forbidden)'); END;
|
|
302
|
+
CREATE TRIGGER IF NOT EXISTS trg_dr_acct_events_no_delete BEFORE DELETE ON direct_receive_account_events BEGIN SELECT RAISE(ABORT, 'direct_receive_account_events is append-only (DELETE forbidden)'); END;
|
|
303
|
+
|
|
304
|
+
-- 缓交(deferred-deposit)申请;审批=真人(RISK),绝不自动;缓交期配额压低,绝不零威慑。
|
|
305
|
+
CREATE TABLE IF NOT EXISTS direct_receive_deferrals (
|
|
306
|
+
id TEXT PRIMARY KEY,
|
|
307
|
+
user_id TEXT NOT NULL REFERENCES users(id),
|
|
308
|
+
reason TEXT,
|
|
309
|
+
period_days INTEGER NOT NULL,
|
|
310
|
+
reduced_quota_factor REAL NOT NULL DEFAULT 0.5, -- 缓交期配额压低系数(<1,带下限)
|
|
311
|
+
status TEXT NOT NULL DEFAULT 'pending', -- pending|granted|rejected|expired
|
|
312
|
+
approved_by TEXT REFERENCES users(id), -- 真人 admin
|
|
313
|
+
approved_at TEXT,
|
|
314
|
+
expires_at TEXT,
|
|
315
|
+
grace_until TEXT,
|
|
316
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
-- 【按产品】外部平台商品认证(per-product verification)。降低作弊:一次验证【绝不】默认放行该卖家所有产品 ——
|
|
320
|
+
-- 每个要走直付收款的产品都必须【单独】被真人 admin 手动核验通过(硬门:未验证产品 direct-pay 不可用,退回托管)。
|
|
321
|
+
-- 诚实边界:WebAZ【绝不】抓取 external_url(无 SSRF、无"WebAZ 已核验该商品/店铺真实性"超claim)。机制 = 卖家为【该产品】
|
|
322
|
+
-- 申领 code → 展示在其外部平台商品页 → 提交该产品链接 → 真人 admin 手动打开核对 → attest。记录的最弱准确事实 =
|
|
323
|
+
-- "admin <id> 于 <时间> 手动确认产品 <product_id> 在 <url> 展示了验证码 <code>"。状态:issued→submitted→verified|rejected。
|
|
324
|
+
CREATE TABLE IF NOT EXISTS product_verifications (
|
|
325
|
+
id TEXT PRIMARY KEY,
|
|
326
|
+
product_id TEXT NOT NULL REFERENCES products(id),
|
|
327
|
+
seller_id TEXT NOT NULL REFERENCES users(id),
|
|
328
|
+
code TEXT NOT NULL, -- WebAZ 签发、卖家需展示在【该产品】外部页的验证码
|
|
329
|
+
platform TEXT, -- 卖家自填的平台名(展示用,不校验)
|
|
330
|
+
external_url TEXT, -- 卖家提交的该产品外部链接(仅存,WebAZ 不抓取)
|
|
331
|
+
status TEXT NOT NULL DEFAULT 'issued', -- issued|submitted|verified|rejected
|
|
332
|
+
reviewed_by TEXT REFERENCES users(id), -- 真人 admin(手动核对者)
|
|
333
|
+
reviewed_at TEXT,
|
|
334
|
+
notes TEXT,
|
|
335
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
336
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
337
|
+
);
|
|
338
|
+
CREATE INDEX IF NOT EXISTS idx_product_verifications_product ON product_verifications(product_id, status);
|
|
339
|
+
CREATE INDEX IF NOT EXISTS idx_product_verifications_seller ON product_verifications(seller_id, status);
|
|
340
|
+
|
|
341
|
+
-- 【按卖家】店铺认证(store verification)= 逐品验证的【豁免】路径。卖家申请一次店铺(发码→贴外部店铺页→提交店铺链接),
|
|
342
|
+
-- 真人 admin 手动核对时【勾选 per_product_exempt】:置 1 = 该卖家所有商品免逐品验证、可直付;置 0(默认)= 仍需逐品验证。
|
|
343
|
+
-- 诚实边界同 product_verifications:WebAZ 绝不抓取 external_url(无 SSRF/无超claim),只存链接+码+真人 attest。单一活跃 per seller。
|
|
344
|
+
CREATE TABLE IF NOT EXISTS store_verifications (
|
|
345
|
+
id TEXT PRIMARY KEY,
|
|
346
|
+
user_id TEXT NOT NULL REFERENCES users(id),
|
|
347
|
+
code TEXT NOT NULL,
|
|
348
|
+
platform TEXT,
|
|
349
|
+
external_url TEXT,
|
|
350
|
+
status TEXT NOT NULL DEFAULT 'issued', -- issued|submitted|verified|rejected
|
|
351
|
+
per_product_exempt INTEGER NOT NULL DEFAULT 0, -- 1 = 该卖家免逐品验证(admin 核店铺时勾选);0 = 仍需逐品
|
|
352
|
+
reviewed_by TEXT REFERENCES users(id),
|
|
353
|
+
reviewed_at TEXT,
|
|
354
|
+
notes TEXT,
|
|
355
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
356
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
357
|
+
);
|
|
358
|
+
CREATE INDEX IF NOT EXISTS idx_store_verifications_user ON store_verifications(user_id, status);
|
|
359
|
+
|
|
360
|
+
-- 逐单费用质押(fee-stake = 平台应收费用,非买家保障)。锁在现有 WAZ 账本。
|
|
361
|
+
CREATE TABLE IF NOT EXISTS direct_pay_fee_stakes (
|
|
362
|
+
id TEXT PRIMARY KEY,
|
|
363
|
+
order_id TEXT NOT NULL REFERENCES orders(id),
|
|
364
|
+
seller_id TEXT NOT NULL REFERENCES users(id),
|
|
365
|
+
amount REAL NOT NULL, -- 锁定额(= 该单平台费)
|
|
366
|
+
status TEXT NOT NULL DEFAULT 'locked', -- locked|fee_taken|released|slashed
|
|
367
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
368
|
+
settled_at TEXT,
|
|
369
|
+
UNIQUE(order_id)
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
373
|
+
-- Direct Pay 平台费【链下应收(AR)】(设计稿 DIRECT-PAY-FEE-RECEIVABLE-DESIGN.INTERNAL.md)
|
|
374
|
+
-- 替代逐单 WAZ 质押:完成时记真实 USDC 应收,月结开票/人工收/欠费暂停资格。
|
|
375
|
+
-- v1 单一计价币 = USDC。append-only:原始事实行不改,变更走 adjustments / events。
|
|
376
|
+
-- PR-1 = 纯建表 + 读 helper,零行为接线(建单门/accrue/cron/UI 在 PR-2+)。
|
|
377
|
+
-- ─────────────────────────────────────────────────────────────────────────
|
|
378
|
+
|
|
379
|
+
-- 月结发票(有 status;每次状态变更必写 invoice_events)。【先于 receivables 建:后者 invoice_id 引用它】。
|
|
380
|
+
CREATE TABLE IF NOT EXISTS direct_pay_fee_invoices (
|
|
381
|
+
id TEXT PRIMARY KEY,
|
|
382
|
+
seller_id TEXT NOT NULL REFERENCES users(id),
|
|
383
|
+
period_start TEXT NOT NULL,
|
|
384
|
+
period_end TEXT NOT NULL,
|
|
385
|
+
total_amount REAL NOT NULL CHECK (total_amount >= 0),
|
|
386
|
+
currency TEXT NOT NULL DEFAULT 'usdc' CHECK (currency = 'usdc'),
|
|
387
|
+
due_date TEXT NOT NULL, -- = period_end + net 15d(D9)
|
|
388
|
+
status TEXT NOT NULL DEFAULT 'open' CHECK (status IN ('open','paid','overdue','void')),
|
|
389
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
390
|
+
created_by TEXT, -- 'cron' 或 admin user_id
|
|
391
|
+
paid_at TEXT
|
|
392
|
+
);
|
|
393
|
+
CREATE INDEX IF NOT EXISTS idx_dp_fee_invoices_seller ON direct_pay_fee_invoices(seller_id, status);
|
|
394
|
+
|
|
395
|
+
-- 逐单应收 = 完成时赚的一笔平台费(原始 accrual 事实行,IMMUTABLE:行一旦写入永不改)。
|
|
396
|
+
-- ⚠️ 不含 invoice_id:入票关联走独立 append-only 表 direct_pay_fee_invoice_items(避免回填 UPDATE 破坏不可变)。
|
|
397
|
+
CREATE TABLE IF NOT EXISTS direct_pay_fee_receivables (
|
|
398
|
+
id TEXT PRIMARY KEY,
|
|
399
|
+
order_id TEXT NOT NULL REFERENCES orders(id),
|
|
400
|
+
seller_id TEXT NOT NULL REFERENCES users(id),
|
|
401
|
+
amount REAL NOT NULL CHECK (amount >= 0), -- 该单平台费(USDC 计价小数;units 经 money.ts 边界)
|
|
402
|
+
currency TEXT NOT NULL DEFAULT 'usdc' CHECK (currency = 'usdc'), -- v1 单币;v2 放开
|
|
403
|
+
accrued_at TEXT DEFAULT (datetime('now')),
|
|
404
|
+
UNIQUE(order_id)
|
|
405
|
+
);
|
|
406
|
+
CREATE INDEX IF NOT EXISTS idx_dp_fee_receivables_seller ON direct_pay_fee_receivables(seller_id);
|
|
407
|
+
|
|
408
|
+
-- 应收 ↔ 发票分摊(append-only 关联行;月结开票时写,不回填/不改 receivables)。UNIQUE(receivable_id) 防重复入票。
|
|
409
|
+
CREATE TABLE IF NOT EXISTS direct_pay_fee_invoice_items (
|
|
410
|
+
id TEXT PRIMARY KEY,
|
|
411
|
+
invoice_id TEXT NOT NULL REFERENCES direct_pay_fee_invoices(id),
|
|
412
|
+
receivable_id TEXT NOT NULL REFERENCES direct_pay_fee_receivables(id),
|
|
413
|
+
amount REAL NOT NULL CHECK (amount >= 0), -- 入票金额(= 该 receivable 计入本发票的额)
|
|
414
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
415
|
+
UNIQUE(receivable_id)
|
|
416
|
+
);
|
|
417
|
+
CREATE INDEX IF NOT EXISTS idx_dp_fee_invoice_items_invoice ON direct_pay_fee_invoice_items(invoice_id);
|
|
418
|
+
|
|
419
|
+
-- 冲销 / 坏账核销 / 手工冲正(独立 append-only 行;原始 accrual 行不动)。
|
|
420
|
+
CREATE TABLE IF NOT EXISTS direct_pay_fee_adjustments (
|
|
421
|
+
id TEXT PRIMARY KEY,
|
|
422
|
+
receivable_id TEXT REFERENCES direct_pay_fee_receivables(id), -- nullable(整体冲正可不挂单)
|
|
423
|
+
seller_id TEXT NOT NULL REFERENCES users(id),
|
|
424
|
+
delta_amount REAL NOT NULL, -- 带符号(退货冲销=负)
|
|
425
|
+
currency TEXT NOT NULL DEFAULT 'usdc' CHECK (currency = 'usdc'),
|
|
426
|
+
kind TEXT NOT NULL CHECK (kind IN ('reversal','write_off','correction')),
|
|
427
|
+
reason TEXT,
|
|
428
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
429
|
+
created_by TEXT REFERENCES users(id) -- admin(人工铁律)
|
|
430
|
+
);
|
|
431
|
+
CREATE INDEX IF NOT EXISTS idx_dp_fee_adjustments_seller ON direct_pay_fee_adjustments(seller_id);
|
|
432
|
+
|
|
433
|
+
-- 发票状态变更审计(append-only)。
|
|
434
|
+
CREATE TABLE IF NOT EXISTS direct_pay_fee_invoice_events (
|
|
435
|
+
id TEXT PRIMARY KEY,
|
|
436
|
+
invoice_id TEXT NOT NULL REFERENCES direct_pay_fee_invoices(id),
|
|
437
|
+
from_status TEXT,
|
|
438
|
+
to_status TEXT NOT NULL,
|
|
439
|
+
actor TEXT, -- 'cron' 或 admin user_id
|
|
440
|
+
reason TEXT,
|
|
441
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
442
|
+
);
|
|
443
|
+
CREATE INDEX IF NOT EXISTS idx_dp_fee_invoice_events_invoice ON direct_pay_fee_invoice_events(invoice_id);
|
|
444
|
+
|
|
445
|
+
-- 商家平台服务费【收款/预付款】事实行(append-only,IMMUTABLE)。当前模型 = 首单宽限 + 预充值续用:
|
|
446
|
+
-- 每行 = admin 记录的一笔商家平台服务费预付款(USDC/法币);invoice_id IS NULL = 【未分配预充值】=
|
|
447
|
+
-- 计入 available_prepay。(invoice_id 非空属早先月结模型预留,本模型不生成发票,故恒 NULL。)
|
|
448
|
+
-- ⚠️ 是【商家平台服务费预付款】,非买家 escrow / 非保证金 / 非 penalty。本轮无"余额退款"实功能。
|
|
449
|
+
CREATE TABLE IF NOT EXISTS direct_pay_fee_payments (
|
|
450
|
+
id TEXT PRIMARY KEY,
|
|
451
|
+
seller_id TEXT NOT NULL REFERENCES users(id),
|
|
452
|
+
invoice_id TEXT REFERENCES direct_pay_fee_invoices(id),
|
|
453
|
+
amount REAL NOT NULL CHECK (amount >= 0),
|
|
454
|
+
currency TEXT NOT NULL DEFAULT 'usdc' CHECK (currency = 'usdc'),
|
|
455
|
+
method TEXT NOT NULL CHECK (method IN ('usdc','fiat')),
|
|
456
|
+
received_at TEXT DEFAULT (datetime('now')),
|
|
457
|
+
recorded_by TEXT REFERENCES users(id), -- admin(Passkey + purpose-bound)
|
|
458
|
+
evidence_ref TEXT,
|
|
459
|
+
note TEXT
|
|
460
|
+
);
|
|
461
|
+
CREATE INDEX IF NOT EXISTS idx_dp_fee_payments_seller ON direct_pay_fee_payments(seller_id);
|
|
462
|
+
|
|
463
|
+
-- 平台服务费【预充值申请】(卖家发起 → admin 核实真实到账后确认入账)。留痕:凭据必填、状态流转、关联入账 payment。
|
|
464
|
+
-- ⚠️ 申请【不动钱】—— 只有 admin 确认(PR3)才调 recordFeePrepay 记入余额。amount_units = base units(1 WAZ=1e6)。
|
|
465
|
+
-- platform_account_id = 付给哪个平台收款方式(见 platform_receive_accounts)。杜绝"场外直接付、无据可查"。
|
|
466
|
+
CREATE TABLE IF NOT EXISTS direct_pay_fee_prepay_requests (
|
|
467
|
+
id TEXT PRIMARY KEY,
|
|
468
|
+
seller_id TEXT NOT NULL REFERENCES users(id),
|
|
469
|
+
amount_units INTEGER NOT NULL, -- 申请充值额(base units)
|
|
470
|
+
currency TEXT, -- 卖家声明的付款币种(展示;以实际到账为准)
|
|
471
|
+
platform_account_id TEXT NOT NULL REFERENCES platform_receive_accounts(id), -- 付给哪个平台收款方式(必选;admin 据此核对到账来源)
|
|
472
|
+
evidence_ref TEXT NOT NULL, -- 付款凭证号/流水(必填 —— 不能无据)
|
|
473
|
+
evidence_note TEXT,
|
|
474
|
+
status TEXT NOT NULL DEFAULT 'pending', -- pending | approved | rejected | cancelled
|
|
475
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
476
|
+
reviewed_by TEXT REFERENCES users(id), -- admin(PR3 approve/reject 时填,Passkey)
|
|
477
|
+
reviewed_at TEXT,
|
|
478
|
+
review_note TEXT,
|
|
479
|
+
resulting_payment_id TEXT REFERENCES direct_pay_fee_payments(id) -- approve 时关联的入账记录
|
|
480
|
+
);
|
|
481
|
+
CREATE INDEX IF NOT EXISTS idx_dp_fee_prepay_req_seller ON direct_pay_fee_prepay_requests(seller_id, status);
|
|
482
|
+
|
|
483
|
+
-- ⏸ DORMANT(早先"AR 信用上限"模型预留;当前 = 首单宽限 + 预充值续用,额度即商家实际预付余额,无固定上限)。
|
|
484
|
+
-- 本表与 ceiling_requests/invoices/invoice_items/invoice_events 当前【不写不读】;保留待将来需要时复用或清理。
|
|
485
|
+
CREATE TABLE IF NOT EXISTS direct_pay_fee_ar_seller_overrides (
|
|
486
|
+
seller_id TEXT PRIMARY KEY REFERENCES users(id),
|
|
487
|
+
ceiling_units INTEGER NOT NULL CHECK (ceiling_units >= 0), -- 该商家未付 AR 上限(整数 base-units;0=封锁)
|
|
488
|
+
updated_by TEXT REFERENCES users(id), -- admin
|
|
489
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
490
|
+
);
|
|
491
|
+
|
|
492
|
+
-- 商家【申请】调高未付 AR 上限 → ROOT/admin 真人 Passkey 审批(approve 即写 override)。
|
|
493
|
+
-- 商家不能自调,只能申请;append-only 审计。模式同仓内 build-task 配额申请。
|
|
494
|
+
CREATE TABLE IF NOT EXISTS direct_pay_fee_ceiling_requests (
|
|
495
|
+
id TEXT PRIMARY KEY,
|
|
496
|
+
seller_id TEXT NOT NULL REFERENCES users(id),
|
|
497
|
+
requested_units INTEGER NOT NULL CHECK (requested_units >= 0), -- 申请目标上限(整数 base-units)
|
|
498
|
+
effective_units_at_request INTEGER CHECK (effective_units_at_request >= 0), -- 申请时生效上限快照(审计用)
|
|
499
|
+
reason TEXT,
|
|
500
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending','approved','rejected')),
|
|
501
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
502
|
+
reviewed_by TEXT REFERENCES users(id), -- admin
|
|
503
|
+
reviewed_at TEXT,
|
|
504
|
+
decision_note TEXT
|
|
505
|
+
);
|
|
506
|
+
CREATE INDEX IF NOT EXISTS idx_dp_fee_ceiling_requests_seller ON direct_pay_fee_ceiling_requests(seller_id, status);
|
|
507
|
+
|
|
508
|
+
-- 商家平台服务费【预充值余额退款】事实行(append-only,IMMUTABLE)。= WebAZ 把已预付未消耗的平台服务费余额
|
|
509
|
+
-- 退还给商家(链下真实退款,记 evidence_ref)。available_prepay 减去 Σ refunds。amount>0(退款额,正)。
|
|
510
|
+
-- ⚠️ 退的是【商家平台服务费预付款】,非买家货款/escrow/保证金/penalty。与 adjustments.correction(账务更正)区分:
|
|
511
|
+
-- refund = 真实退钱;correction = 记账更正(不一定动真钱)。退款额 ≤ 当前 available(不可退已被费用消耗的部分,由 helper 校验)。
|
|
512
|
+
CREATE TABLE IF NOT EXISTS direct_pay_fee_prepay_refunds (
|
|
513
|
+
id TEXT PRIMARY KEY,
|
|
514
|
+
seller_id TEXT NOT NULL REFERENCES users(id),
|
|
515
|
+
amount REAL NOT NULL CHECK (amount >= 0),
|
|
516
|
+
currency TEXT NOT NULL DEFAULT 'usdc' CHECK (currency = 'usdc'),
|
|
517
|
+
method TEXT NOT NULL CHECK (method IN ('usdc','fiat')),
|
|
518
|
+
evidence_ref TEXT,
|
|
519
|
+
reason TEXT,
|
|
520
|
+
recorded_by TEXT REFERENCES users(id), -- admin(Passkey + purpose-bound)
|
|
521
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
522
|
+
);
|
|
523
|
+
CREATE INDEX IF NOT EXISTS idx_dp_fee_prepay_refunds_seller ON direct_pay_fee_prepay_refunds(seller_id);
|
|
524
|
+
|
|
525
|
+
-- ── APPEND-ONLY 硬强制(DB 级,非仅注释)── money-adjacent fee 账本的事实/事件行不可改/删。
|
|
526
|
+
-- 6 张:receivables(immutable accrual)/ invoice_items(写一次)/ adjustments / invoice_events / payments(immutable)/ prepay_refunds(immutable)。
|
|
527
|
+
-- invoices/overrides/ceiling_requests 刻意【不】锁(有合法状态/值变更)。PG 等价 plpgsql guard 由 gen-pg-schema 的 APPEND_ONLY_TABLES 生成。
|
|
528
|
+
CREATE TRIGGER IF NOT EXISTS trg_dp_fee_receivables_no_update BEFORE UPDATE ON direct_pay_fee_receivables BEGIN SELECT RAISE(ABORT, 'direct_pay_fee_receivables is append-only (UPDATE forbidden)'); END;
|
|
529
|
+
CREATE TRIGGER IF NOT EXISTS trg_dp_fee_receivables_no_delete BEFORE DELETE ON direct_pay_fee_receivables BEGIN SELECT RAISE(ABORT, 'direct_pay_fee_receivables is append-only (DELETE forbidden)'); END;
|
|
530
|
+
CREATE TRIGGER IF NOT EXISTS trg_dp_fee_invoice_items_no_update BEFORE UPDATE ON direct_pay_fee_invoice_items BEGIN SELECT RAISE(ABORT, 'direct_pay_fee_invoice_items is append-only (UPDATE forbidden)'); END;
|
|
531
|
+
CREATE TRIGGER IF NOT EXISTS trg_dp_fee_invoice_items_no_delete BEFORE DELETE ON direct_pay_fee_invoice_items BEGIN SELECT RAISE(ABORT, 'direct_pay_fee_invoice_items is append-only (DELETE forbidden)'); END;
|
|
532
|
+
CREATE TRIGGER IF NOT EXISTS trg_dp_fee_adjustments_no_update BEFORE UPDATE ON direct_pay_fee_adjustments BEGIN SELECT RAISE(ABORT, 'direct_pay_fee_adjustments is append-only (UPDATE forbidden)'); END;
|
|
533
|
+
CREATE TRIGGER IF NOT EXISTS trg_dp_fee_adjustments_no_delete BEFORE DELETE ON direct_pay_fee_adjustments BEGIN SELECT RAISE(ABORT, 'direct_pay_fee_adjustments is append-only (DELETE forbidden)'); END;
|
|
534
|
+
CREATE TRIGGER IF NOT EXISTS trg_dp_fee_invoice_events_no_update BEFORE UPDATE ON direct_pay_fee_invoice_events BEGIN SELECT RAISE(ABORT, 'direct_pay_fee_invoice_events is append-only (UPDATE forbidden)'); END;
|
|
535
|
+
CREATE TRIGGER IF NOT EXISTS trg_dp_fee_invoice_events_no_delete BEFORE DELETE ON direct_pay_fee_invoice_events BEGIN SELECT RAISE(ABORT, 'direct_pay_fee_invoice_events is append-only (DELETE forbidden)'); END;
|
|
536
|
+
CREATE TRIGGER IF NOT EXISTS trg_dp_fee_payments_no_update BEFORE UPDATE ON direct_pay_fee_payments BEGIN SELECT RAISE(ABORT, 'direct_pay_fee_payments is append-only (UPDATE forbidden)'); END;
|
|
537
|
+
CREATE TRIGGER IF NOT EXISTS trg_dp_fee_payments_no_delete BEFORE DELETE ON direct_pay_fee_payments BEGIN SELECT RAISE(ABORT, 'direct_pay_fee_payments is append-only (DELETE forbidden)'); END;
|
|
538
|
+
CREATE TRIGGER IF NOT EXISTS trg_dp_fee_prepay_refunds_no_update BEFORE UPDATE ON direct_pay_fee_prepay_refunds BEGIN SELECT RAISE(ABORT, 'direct_pay_fee_prepay_refunds is append-only (UPDATE forbidden)'); END;
|
|
539
|
+
CREATE TRIGGER IF NOT EXISTS trg_dp_fee_prepay_refunds_no_delete BEFORE DELETE ON direct_pay_fee_prepay_refunds BEGIN SELECT RAISE(ABORT, 'direct_pay_fee_prepay_refunds is append-only (DELETE forbidden)'); END;
|
|
540
|
+
|
|
541
|
+
-- penalty 科目(独立、物理隔离、只进不出)。出账【无代码路径】= append-only 硬保证。
|
|
542
|
+
-- 三条出账红线(永不可破):①不退买家 ②不计 WebAZ 利润 ③不按个案裁决结果流向裁决者。
|
|
543
|
+
CREATE TABLE IF NOT EXISTS penalty_fund (
|
|
544
|
+
id TEXT PRIMARY KEY, -- 恒为 'main'
|
|
545
|
+
balance REAL DEFAULT 0,
|
|
546
|
+
total_fee_stake_slash REAL DEFAULT 0,
|
|
547
|
+
total_base_bond_slash REAL DEFAULT 0,
|
|
548
|
+
updated_at TEXT
|
|
549
|
+
);
|
|
550
|
+
CREATE TABLE IF NOT EXISTS penalty_fund_txns (
|
|
551
|
+
id TEXT PRIMARY KEY,
|
|
552
|
+
kind TEXT NOT NULL, -- fee_stake_slash | base_bond_slash
|
|
553
|
+
source TEXT NOT NULL, -- fee_stake | base_bond (provenance)
|
|
554
|
+
from_user_id TEXT,
|
|
555
|
+
amount REAL NOT NULL,
|
|
556
|
+
related_order_id TEXT,
|
|
557
|
+
reason TEXT,
|
|
558
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
559
|
+
);
|
|
560
|
+
|
|
561
|
+
-- 制裁/合规筛查(本仓原无;direct-pay 含加密=最重洗钱形态,硬要求)
|
|
562
|
+
CREATE TABLE IF NOT EXISTS sanctions_screening (
|
|
563
|
+
id TEXT PRIMARY KEY,
|
|
564
|
+
user_id TEXT NOT NULL REFERENCES users(id),
|
|
565
|
+
status TEXT NOT NULL DEFAULT 'clear', -- clear | flagged | blocked
|
|
566
|
+
source TEXT,
|
|
567
|
+
reason TEXT,
|
|
568
|
+
screened_at TEXT DEFAULT (datetime('now')),
|
|
569
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
570
|
+
-- PR-6A: expires_at 由 ALTER 补(见迁移段);制裁结论有有效期,过期视作未通过(fail-closed)。
|
|
571
|
+
);
|
|
572
|
+
|
|
573
|
+
-- PR-6A: Direct Pay KYB(商户尽调)复核台账。Direct Pay AML/KYB fail-closed runtime —— 无第三方 vendor、无真实
|
|
574
|
+
-- API 调用,仅记录【真人/合规复核结论】。fail-closed:missing/pending/rejected/revoked/expired 一律不通过,
|
|
575
|
+
-- 只有 approved 且未过期(且无 rejected/revoked)才算 KYB 通过。本表无生产写入方 → 真实卖家天然 fail-closed。
|
|
576
|
+
CREATE TABLE IF NOT EXISTS direct_receive_kyb_reviews (
|
|
577
|
+
id TEXT PRIMARY KEY,
|
|
578
|
+
user_id TEXT NOT NULL REFERENCES users(id),
|
|
579
|
+
status TEXT NOT NULL DEFAULT 'pending', -- pending | approved | rejected | revoked
|
|
580
|
+
reviewed_by TEXT, -- 复核人(真人/合规);无第三方集成
|
|
581
|
+
reviewed_at TEXT,
|
|
582
|
+
expires_at TEXT, -- 复核有效期;过期视作未通过
|
|
583
|
+
reason TEXT,
|
|
584
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
585
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
586
|
+
);
|
|
587
|
+
|
|
588
|
+
-- AML 监控 flag(进【独立复核队列】,与配额节流分开);AML 能力 = INVARIANT。
|
|
589
|
+
CREATE TABLE IF NOT EXISTS aml_flags (
|
|
590
|
+
id TEXT PRIMARY KEY,
|
|
591
|
+
subject_user_id TEXT NOT NULL REFERENCES users(id),
|
|
592
|
+
related_order_id TEXT,
|
|
593
|
+
rule TEXT NOT NULL, -- structuring|concentration|cumulative|crypto|velocity
|
|
594
|
+
severity TEXT NOT NULL DEFAULT 'low',-- low|medium|high
|
|
595
|
+
detail TEXT, -- JSON
|
|
596
|
+
status TEXT NOT NULL DEFAULT 'open',-- open|reviewing|cleared|escalated|str_filed
|
|
597
|
+
disposition TEXT, -- review_queue|downgrade|suspend (非资金手段)
|
|
598
|
+
reviewed_by TEXT REFERENCES users(id),
|
|
599
|
+
reviewed_at TEXT,
|
|
600
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
601
|
+
);
|
|
602
|
+
-- STR 申报(具名 compliance 责任人);留存默认 5 年(legal 可调)。
|
|
603
|
+
CREATE TABLE IF NOT EXISTS aml_str_filings (
|
|
604
|
+
id TEXT PRIMARY KEY,
|
|
605
|
+
flag_id TEXT REFERENCES aml_flags(id),
|
|
606
|
+
filed_by TEXT NOT NULL, -- 具名 compliance officer
|
|
607
|
+
filing_ref TEXT,
|
|
608
|
+
narrative TEXT,
|
|
609
|
+
filed_at TEXT DEFAULT (datetime('now')),
|
|
610
|
+
retention_until TEXT NOT NULL -- filed_at + 留存年限
|
|
611
|
+
);
|
|
612
|
+
|
|
613
|
+
-- 披露契约层凭证(append-only 事件):两次风险提醒各一行 —— stage='pre_select'(展示/选择直付前)
|
|
614
|
+
-- 与 stage='pre_confirm'(最终下单/确认付款前)。每行记 notice_version + acked_at,可证两次【分别】发生、
|
|
615
|
+
-- 第二次在最终确认前。最终确认逻辑只在【两 stage 都 ack】时放行(见 direct-pay-disclosures.ts)。
|
|
616
|
+
-- 这是 Direct Pay「无经济保障、风险自担」边界的证据层 —— 不可压成单次 ack。
|
|
617
|
+
CREATE TABLE IF NOT EXISTS direct_pay_disclosure_acks (
|
|
618
|
+
id TEXT PRIMARY KEY,
|
|
619
|
+
order_id TEXT NOT NULL REFERENCES orders(id),
|
|
620
|
+
buyer_id TEXT NOT NULL REFERENCES users(id),
|
|
621
|
+
stage TEXT NOT NULL, -- pre_select | pre_confirm
|
|
622
|
+
notice_version TEXT NOT NULL, -- 该次提醒的披露文案版本
|
|
623
|
+
acked_at TEXT DEFAULT (datetime('now')),
|
|
624
|
+
UNIQUE(order_id, stage) -- 每单每阶段一次;两阶段=两行
|
|
625
|
+
);
|
|
626
|
+
|
|
627
|
+
-- ── Merchant Base-Bond (v1 collateral-only) — PR1 testnet/dev scaffold。链上为真相,这两张表只是【DB 镜像/缓存】(见 docs/modules/MERCHANT-BASE-BOND-DESIGN.INTERNAL.md §4.1)。
|
|
628
|
+
-- v1 默认关闭、不接 mainnet、不收真钱、live 路径不读写 → 对现有 Direct Pay 零影响。
|
|
629
|
+
CREATE TABLE IF NOT EXISTS merchant_bond_wallets (
|
|
630
|
+
seller_id TEXT PRIMARY KEY REFERENCES users(id),
|
|
631
|
+
wallet TEXT NOT NULL, -- registeredBondWallet(链上地址);seller_id ↔ wallet 唯一
|
|
632
|
+
chain_id INTEGER NOT NULL, -- v1 = Base
|
|
633
|
+
rotated_at TEXT,
|
|
634
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
635
|
+
UNIQUE(wallet)
|
|
636
|
+
);
|
|
637
|
+
CREATE TABLE IF NOT EXISTS merchant_bond_deposits (
|
|
638
|
+
id TEXT PRIMARY KEY,
|
|
639
|
+
seller_id TEXT NOT NULL REFERENCES users(id),
|
|
640
|
+
wallet TEXT NOT NULL,
|
|
641
|
+
tx_hash TEXT,
|
|
642
|
+
collateral_units TEXT NOT NULL DEFAULT '0', -- USDC integer units(字符串,big-int 安全)
|
|
643
|
+
status TEXT NOT NULL DEFAULT 'pending_confirmations', -- none|pending_confirmations|active|cooling|withdrawable|withdrawn|slashed_below_min(§4 状态机)
|
|
644
|
+
confirmations INTEGER NOT NULL DEFAULT 0,
|
|
645
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
646
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
647
|
+
);
|
|
648
|
+
|
|
175
649
|
`);
|
|
176
650
|
// 迁移:为已有数据库添加 roles 列
|
|
177
651
|
try {
|
|
@@ -179,6 +653,308 @@ export function initDatabase() {
|
|
|
179
653
|
}
|
|
180
654
|
catch { /* 列已存在 */ }
|
|
181
655
|
db.exec(`UPDATE users SET roles = json_array(role) WHERE roles = '[]' OR roles IS NULL`);
|
|
656
|
+
// 迁移(Direct Pay Rail 1): 既有库补列。ADD COLUMN(非 rebuild),fresh-DB 与 existing-DB 两路均生效。
|
|
657
|
+
try {
|
|
658
|
+
db.exec(`ALTER TABLE orders ADD COLUMN payment_rail TEXT DEFAULT 'escrow'`);
|
|
659
|
+
}
|
|
660
|
+
catch { /* 已存在 */ }
|
|
661
|
+
try {
|
|
662
|
+
db.exec(`ALTER TABLE orders ADD COLUMN direct_pay_window_deadline TEXT`);
|
|
663
|
+
}
|
|
664
|
+
catch { /* 已存在 */ }
|
|
665
|
+
try {
|
|
666
|
+
db.exec(`ALTER TABLE orders ADD COLUMN direct_grace_deadline TEXT`);
|
|
667
|
+
}
|
|
668
|
+
catch { /* 已存在 */ } // Rail1 paid-but-timeout 宽限期:系统在此之前绝不关单(买家 →disputed 窗口)
|
|
669
|
+
try {
|
|
670
|
+
db.exec(`ALTER TABLE orders ADD COLUMN payment_query_deadline TEXT`);
|
|
671
|
+
}
|
|
672
|
+
catch { /* 已存在 */ } // Rail1 货款协商:卖家报未收款后买家响应宽限(过期→卖家可请求取消)
|
|
673
|
+
try {
|
|
674
|
+
db.exec(`ALTER TABLE orders ADD COLUMN payment_query_cancel_deadline TEXT`);
|
|
675
|
+
}
|
|
676
|
+
catch { /* 已存在 */ } // Rail1 货款协商:卖家请求取消后买家 7 天申诉窗(过期→cron 关单;窗内买家可升举证仲裁)
|
|
677
|
+
try {
|
|
678
|
+
db.exec(`ALTER TABLE orders ADD COLUMN direct_pay_instruction_snapshot TEXT`);
|
|
679
|
+
}
|
|
680
|
+
catch { /* 已存在 */ } // Rail1 4c:下单时快照卖家收款说明(冻结买家所见;卖家事后改/停用不影响)
|
|
681
|
+
try {
|
|
682
|
+
db.exec(`ALTER TABLE orders ADD COLUMN direct_pay_account_snapshot TEXT`);
|
|
683
|
+
}
|
|
684
|
+
catch { /* 已存在 */ } // Rail1 D2:买家所选收款账号快照 JSON {account_id,method,currency,label,qr_ref}(非敏感元数据;instruction 原文仍在 direct_pay_instruction_snapshot 受披露门;qr_ref 的图字节走 ack 门端点)
|
|
685
|
+
// PR-5b-0: direct_p2p 入口控制 policy 快照列(既有库补列;additive nullable,本 PR 无写入方,5b wiring 才写)。
|
|
686
|
+
try {
|
|
687
|
+
db.exec(`ALTER TABLE orders ADD COLUMN direct_pay_enabled_snapshot INTEGER`);
|
|
688
|
+
}
|
|
689
|
+
catch { /* 已存在 */ }
|
|
690
|
+
try {
|
|
691
|
+
db.exec(`ALTER TABLE orders ADD COLUMN direct_pay_rail_breaker_snapshot INTEGER`);
|
|
692
|
+
}
|
|
693
|
+
catch { /* 已存在 */ }
|
|
694
|
+
try {
|
|
695
|
+
db.exec(`ALTER TABLE orders ADD COLUMN direct_pay_region_snapshot TEXT`);
|
|
696
|
+
}
|
|
697
|
+
catch { /* 已存在 */ }
|
|
698
|
+
try {
|
|
699
|
+
db.exec(`ALTER TABLE orders ADD COLUMN direct_pay_region_allowlist_snapshot TEXT`);
|
|
700
|
+
}
|
|
701
|
+
catch { /* 已存在 */ }
|
|
702
|
+
try {
|
|
703
|
+
db.exec(`ALTER TABLE orders ADD COLUMN direct_pay_per_tx_cap_units_snapshot INTEGER`);
|
|
704
|
+
}
|
|
705
|
+
catch { /* 已存在 */ }
|
|
706
|
+
try {
|
|
707
|
+
db.exec(`ALTER TABLE orders ADD COLUMN direct_pay_seller_breaker_snapshot INTEGER`);
|
|
708
|
+
}
|
|
709
|
+
catch { /* 已存在 */ }
|
|
710
|
+
try {
|
|
711
|
+
db.exec(`ALTER TABLE orders ADD COLUMN direct_pay_decision_code TEXT`);
|
|
712
|
+
}
|
|
713
|
+
catch { /* 已存在 */ }
|
|
714
|
+
// 手动接单模式(v16):卖家可选 auto/manual(单品覆盖 ?? 店铺默认 ?? auto);manual 直付单先进 pending_accept。
|
|
715
|
+
try {
|
|
716
|
+
db.exec(`ALTER TABLE products ADD COLUMN accept_mode TEXT`);
|
|
717
|
+
}
|
|
718
|
+
catch { /* 已存在 */ } // 'auto'|'manual'|NULL(=继承店铺默认)
|
|
719
|
+
try {
|
|
720
|
+
db.exec(`ALTER TABLE users ADD COLUMN store_accept_mode TEXT`);
|
|
721
|
+
}
|
|
722
|
+
catch { /* 已存在 */ } // 店铺级默认 'auto'|'manual'|NULL(=auto)
|
|
723
|
+
try {
|
|
724
|
+
db.exec(`ALTER TABLE orders ADD COLUMN accept_mode_snapshot TEXT`);
|
|
725
|
+
}
|
|
726
|
+
catch { /* 已存在 */ } // 下单时快照(卖家事后改不影响在途单)
|
|
727
|
+
try {
|
|
728
|
+
db.exec(`ALTER TABLE orders ADD COLUMN pending_accept_deadline TEXT`);
|
|
729
|
+
}
|
|
730
|
+
catch { /* 已存在 */ } // 接单窗(专属 cron 读;超时无责取消+回补库存)
|
|
731
|
+
// 运费模板(PR-2):按收货地区预设运费/时效;下单命中 → 运费并入总额并快照(卖家改模板不影响在途单)。
|
|
732
|
+
try {
|
|
733
|
+
db.exec(`ALTER TABLE products ADD COLUMN shipping_template TEXT`);
|
|
734
|
+
}
|
|
735
|
+
catch { /* 已存在 */ } // JSON [{region,fee,est_days}];NULL=继承店铺默认
|
|
736
|
+
try {
|
|
737
|
+
db.exec(`ALTER TABLE users ADD COLUMN store_shipping_template TEXT`);
|
|
738
|
+
}
|
|
739
|
+
catch { /* 已存在 */ } // 店铺级默认模板
|
|
740
|
+
try {
|
|
741
|
+
db.exec(`ALTER TABLE orders ADD COLUMN ship_to_region TEXT`);
|
|
742
|
+
}
|
|
743
|
+
catch { /* 已存在 */ } // 买家下单所选收货地区(结构化,非自由文本地址)
|
|
744
|
+
try {
|
|
745
|
+
db.exec(`ALTER TABLE orders ADD COLUMN shipping_fee DECIMAL(18,2)`);
|
|
746
|
+
}
|
|
747
|
+
catch { /* 已存在 */ } // 下单快照运费(已并入 total_amount;NULL=无模板旧单)
|
|
748
|
+
try {
|
|
749
|
+
db.exec(`ALTER TABLE orders ADD COLUMN shipping_est_days TEXT`);
|
|
750
|
+
}
|
|
751
|
+
catch { /* 已存在 */ } // 下单快照预计时效(展示;不接判责钟)
|
|
752
|
+
// 询价握手(PR-3,直付轨):模板外地区先报价后接单。quote_ok=卖家 opt-in(单品??店铺,默认关)。
|
|
753
|
+
try {
|
|
754
|
+
db.exec(`ALTER TABLE products ADD COLUMN shipping_quote_ok INTEGER`);
|
|
755
|
+
}
|
|
756
|
+
catch { /* 已存在 */ } // 1|0|NULL(=继承店铺)
|
|
757
|
+
try {
|
|
758
|
+
db.exec(`ALTER TABLE users ADD COLUMN store_shipping_quote_ok INTEGER`);
|
|
759
|
+
}
|
|
760
|
+
catch { /* 已存在 */ } // 店铺级默认(NULL=关)
|
|
761
|
+
try {
|
|
762
|
+
db.exec(`ALTER TABLE orders ADD COLUMN shipping_quote_required INTEGER`);
|
|
763
|
+
}
|
|
764
|
+
catch { /* 已存在 */ } // 1=本单须先报价(pending_accept 内子流)
|
|
765
|
+
try {
|
|
766
|
+
db.exec(`ALTER TABLE orders ADD COLUMN shipping_quote_fee DECIMAL(18,2)`);
|
|
767
|
+
}
|
|
768
|
+
catch { /* 已存在 */ } // 卖家报价运费(买家确认后并入 total_amount)
|
|
769
|
+
try {
|
|
770
|
+
db.exec(`ALTER TABLE orders ADD COLUMN shipping_quote_est_days TEXT`);
|
|
771
|
+
}
|
|
772
|
+
catch { /* 已存在 */ }
|
|
773
|
+
try {
|
|
774
|
+
db.exec(`ALTER TABLE orders ADD COLUMN shipping_quote_note TEXT`);
|
|
775
|
+
}
|
|
776
|
+
catch { /* 已存在 */ }
|
|
777
|
+
try {
|
|
778
|
+
db.exec(`ALTER TABLE orders ADD COLUMN shipping_quote_at TEXT`);
|
|
779
|
+
}
|
|
780
|
+
catch { /* 已存在 */ }
|
|
781
|
+
// 跨境交易条款骨架(S0):清关/物流证据字段(即时开放,展示+快照证据,零计费逻辑=守 ERP 边界)+
|
|
782
|
+
// 结构化规则列(sale_regions/tax_lines/import_duty_terms 先建列【不开 API】—— 不上假开关:S1 带可售 gate、
|
|
783
|
+
// S3 带税费明细进 total 时才各自开放;既有 ship_regions 是自由文本仅展示,真相源=这些结构化列)。
|
|
784
|
+
try {
|
|
785
|
+
db.exec(`ALTER TABLE products ADD COLUMN weight_kg REAL`);
|
|
786
|
+
}
|
|
787
|
+
catch { /* 已存在 */ } // 重量(S0 起 products-update 也写此列 → 收进 base schema,不再只靠 server.ts 迁移;裸 init 路径一致有列)
|
|
788
|
+
try {
|
|
789
|
+
db.exec(`ALTER TABLE products ADD COLUMN package_size TEXT`);
|
|
790
|
+
}
|
|
791
|
+
catch { /* 已存在 */ } // 长x宽x高 cm 文本(证据/报价参考)
|
|
792
|
+
try {
|
|
793
|
+
db.exec(`ALTER TABLE products ADD COLUMN origin_country TEXT`);
|
|
794
|
+
}
|
|
795
|
+
catch { /* 已存在 */ } // 发货国(ISO 区码)
|
|
796
|
+
try {
|
|
797
|
+
db.exec(`ALTER TABLE products ADD COLUMN country_of_origin TEXT`);
|
|
798
|
+
}
|
|
799
|
+
catch { /* 已存在 */ } // 原产国(清关申报)
|
|
800
|
+
try {
|
|
801
|
+
db.exec(`ALTER TABLE products ADD COLUMN customs_description TEXT`);
|
|
802
|
+
}
|
|
803
|
+
catch { /* 已存在 */ } // 报关品名(英文)
|
|
804
|
+
try {
|
|
805
|
+
db.exec(`ALTER TABLE products ADD COLUMN hs_code TEXT`);
|
|
806
|
+
}
|
|
807
|
+
catch { /* 已存在 */ } // HS 编码(可选)
|
|
808
|
+
try {
|
|
809
|
+
db.exec(`ALTER TABLE products ADD COLUMN sale_regions TEXT`);
|
|
810
|
+
}
|
|
811
|
+
catch { /* 已存在 */ } // S1 gate 消费:{mode,include,exclude} JSON(NULL=继承店铺)
|
|
812
|
+
try {
|
|
813
|
+
db.exec(`ALTER TABLE products ADD COLUMN tax_lines TEXT`);
|
|
814
|
+
}
|
|
815
|
+
catch { /* 已存在 */ } // S3 消费:按目的区税费科目 JSON(NULL=继承店铺)
|
|
816
|
+
try {
|
|
817
|
+
db.exec(`ALTER TABLE products ADD COLUMN import_duty_terms TEXT`);
|
|
818
|
+
}
|
|
819
|
+
catch { /* 已存在 */ } // 'ddu'|'ddp'|NULL(=继承店铺;跨境进口税责声明)
|
|
820
|
+
try {
|
|
821
|
+
db.exec(`ALTER TABLE users ADD COLUMN store_sale_regions TEXT`);
|
|
822
|
+
}
|
|
823
|
+
catch { /* 已存在 */ }
|
|
824
|
+
try {
|
|
825
|
+
db.exec(`ALTER TABLE users ADD COLUMN store_tax_lines TEXT`);
|
|
826
|
+
}
|
|
827
|
+
catch { /* 已存在 */ }
|
|
828
|
+
try {
|
|
829
|
+
db.exec(`ALTER TABLE users ADD COLUMN store_import_duty_terms TEXT`);
|
|
830
|
+
}
|
|
831
|
+
catch { /* 已存在 */ }
|
|
832
|
+
try {
|
|
833
|
+
db.exec(`ALTER TABLE orders ADD COLUMN trade_terms_snapshot TEXT`);
|
|
834
|
+
}
|
|
835
|
+
catch { /* 已存在 */ } // 下单冻结的交易条款 JSON(运费来源/时效/退货/清关字段/税责声明;商家事后改设置不影响旧订单,争议依据)
|
|
836
|
+
// 营销域满额免邮(S2 返工:从运费模板移出 —— 模板=成本结构,免邮=促销;供应商报价期规则不搬家)
|
|
837
|
+
try {
|
|
838
|
+
db.exec(`ALTER TABLE products ADD COLUMN free_shipping_threshold DECIMAL(18,2)`);
|
|
839
|
+
}
|
|
840
|
+
catch { /* 已存在 */ }
|
|
841
|
+
try {
|
|
842
|
+
db.exec(`ALTER TABLE users ADD COLUMN store_free_shipping_threshold DECIMAL(18,2)`);
|
|
843
|
+
}
|
|
844
|
+
catch { /* 已存在 */ }
|
|
845
|
+
// ── 商品【非钱路】扩展列收敛到 base(测试 schema 初始化单一来源;与 weight_kg S4 同法)──
|
|
846
|
+
// products-create/update/read 写这些属性/溯源/物流/退货/i18n/库存/信誉计数列;历史上只在 server.ts 迁移段(或 MCP register-list-search 助手),
|
|
847
|
+
// 裸 initDatabase / bridge / 测试缺列 → 各测试各自手动补 ALTER(band-aid)。收进 base 后每条 init 路径一致有列,band-aid 可删。
|
|
848
|
+
// server.ts 内联迁移【保留不动】(byte-identical guarded ALTER,生产迁移序不变;非 wholesale 抽取,不碰钱/单/状态迁移)。
|
|
849
|
+
// 刻意排除:commission_rate(佣金=钱路,不进);stake_amount / images 已在 CREATE TABLE products。
|
|
850
|
+
for (const col of [
|
|
851
|
+
'specs TEXT', 'brand TEXT', 'model TEXT', 'source_price REAL', 'ship_regions TEXT DEFAULT "全国"', // 属性 + 溯源参考 + 既有自由文本运费地区
|
|
852
|
+
'handling_hours INTEGER DEFAULT 24', 'estimated_days TEXT', 'fragile INTEGER DEFAULT 0', // 履约:处理时长/预计时效/易碎
|
|
853
|
+
'return_days INTEGER DEFAULT 7', 'return_condition TEXT', 'warranty_days INTEGER DEFAULT 0', // 退货/保修承诺
|
|
854
|
+
'source_url TEXT', 'source_price_at TEXT', // 溯源链接 + 采价时间
|
|
855
|
+
'commitment_hash TEXT', 'description_hash TEXT', 'price_hash TEXT', 'hashed_at TEXT', // 承诺哈希(内容/描述/价格),非价格数值本身
|
|
856
|
+
'origin_claims TEXT', 'i18n_titles TEXT', 'i18n_descs TEXT', `product_type TEXT DEFAULT 'retail'`, 'has_variants INTEGER DEFAULT 0', // 声明/多语言/分型
|
|
857
|
+
'last_sold_at TEXT', 'first_sold_at TEXT', // 销售生命周期时间戳(展示/排序)
|
|
858
|
+
'completion_count INTEGER DEFAULT 0', 'dispute_loss_count INTEGER DEFAULT 0', 'claim_loss_count INTEGER DEFAULT 0', 'value_badge INTEGER DEFAULT 0', // 信誉/价值计数(纯列,不含状态机/结算逻辑)
|
|
859
|
+
'low_stock_threshold INTEGER DEFAULT 3', 'auto_delist_on_zero INTEGER DEFAULT 1', 'low_stock_alerted_at TEXT', // 低库存提醒/自动下架(库存运营)
|
|
860
|
+
]) {
|
|
861
|
+
try {
|
|
862
|
+
db.exec(`ALTER TABLE products ADD COLUMN ${col}`);
|
|
863
|
+
}
|
|
864
|
+
catch { /* 已存在 */ }
|
|
865
|
+
}
|
|
866
|
+
try {
|
|
867
|
+
db.exec(`ALTER TABLE wallets ADD COLUMN fee_staked REAL DEFAULT 0`);
|
|
868
|
+
}
|
|
869
|
+
catch { /* 已存在 */ }
|
|
870
|
+
// PR-4b-1: direct_receive_deposits 生产收款 provenance 快照列(既有库补列;additive nullable,无写入方,无 flow 启用)。
|
|
871
|
+
try {
|
|
872
|
+
db.exec(`ALTER TABLE direct_receive_deposits ADD COLUMN production_receipt_ref TEXT`);
|
|
873
|
+
}
|
|
874
|
+
catch { /* 已存在 */ }
|
|
875
|
+
try {
|
|
876
|
+
db.exec(`ALTER TABLE direct_receive_deposits ADD COLUMN production_rail_id TEXT`);
|
|
877
|
+
}
|
|
878
|
+
catch { /* 已存在 */ }
|
|
879
|
+
try {
|
|
880
|
+
db.exec(`ALTER TABLE direct_receive_deposits ADD COLUMN production_jurisdiction TEXT`);
|
|
881
|
+
}
|
|
882
|
+
catch { /* 已存在 */ }
|
|
883
|
+
try {
|
|
884
|
+
db.exec(`ALTER TABLE direct_receive_deposits ADD COLUMN production_policy_version TEXT`);
|
|
885
|
+
}
|
|
886
|
+
catch { /* 已存在 */ }
|
|
887
|
+
try {
|
|
888
|
+
db.exec(`ALTER TABLE direct_receive_deposits ADD COLUMN reject_note TEXT`);
|
|
889
|
+
}
|
|
890
|
+
catch { /* 已存在 */ } // B1:admin 驳回申报说明(卖家可见)
|
|
891
|
+
try {
|
|
892
|
+
db.exec(`ALTER TABLE direct_receive_deposits ADD COLUMN refund_requested_at TEXT`);
|
|
893
|
+
}
|
|
894
|
+
catch { /* 已存在 */ } // B2:退出申请时间(冷静期锚点)
|
|
895
|
+
try {
|
|
896
|
+
db.exec(`ALTER TABLE direct_receive_deposits ADD COLUMN refund_evidence_ref TEXT`);
|
|
897
|
+
}
|
|
898
|
+
catch { /* 已存在 */ } // B2:场外退还凭据(admin 执行时记录)
|
|
899
|
+
try {
|
|
900
|
+
db.exec(`ALTER TABLE direct_receive_deposits ADD COLUMN terms_version TEXT`);
|
|
901
|
+
}
|
|
902
|
+
catch { /* 已存在 */ } // 条款同意版本快照(缴纳前强制同意;罚没/退还的合同依据)
|
|
903
|
+
try {
|
|
904
|
+
db.exec(`ALTER TABLE direct_receive_deposits ADD COLUMN platform_account_id TEXT`);
|
|
905
|
+
}
|
|
906
|
+
catch { /* 已存在 */ } // 缴到哪个平台收款账户(多币种;币种由账户推导)
|
|
907
|
+
// B3:保证金罚没提案(人工铁律:仲裁裁定卖家责的直付争议 → admin 提案 → 冷静期 → ROOT+Passkey 执行;绝不自动)。
|
|
908
|
+
db.exec(`
|
|
909
|
+
CREATE TABLE IF NOT EXISTS bond_slash_proposals (
|
|
910
|
+
id TEXT PRIMARY KEY,
|
|
911
|
+
deposit_id TEXT NOT NULL,
|
|
912
|
+
seller_id TEXT NOT NULL,
|
|
913
|
+
dispute_id TEXT NOT NULL, -- 依据争议(须 resolved 且 ruling ∈ 卖家责;direct_p2p 单)
|
|
914
|
+
reason TEXT,
|
|
915
|
+
status TEXT NOT NULL DEFAULT 'proposed' CHECK (status IN ('proposed','executed','cancelled')),
|
|
916
|
+
cooling_until TEXT NOT NULL, -- 绝对截止(propose 时按 param 计算;执行须晚于此)
|
|
917
|
+
proposed_by TEXT NOT NULL,
|
|
918
|
+
proposed_at TEXT DEFAULT (datetime('now')),
|
|
919
|
+
executed_at TEXT,
|
|
920
|
+
executed_txn_id TEXT,
|
|
921
|
+
cancelled_at TEXT,
|
|
922
|
+
cancel_note TEXT
|
|
923
|
+
);
|
|
924
|
+
`);
|
|
925
|
+
try {
|
|
926
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_bond_slash_seller ON bond_slash_proposals(seller_id, status)');
|
|
927
|
+
}
|
|
928
|
+
catch { /* 已存在 */ }
|
|
929
|
+
// B4:缓交收口 —— 到期前提醒去重锚点 + 缴清转正式时间戳(ALTER after CREATE 铁律)。
|
|
930
|
+
try {
|
|
931
|
+
db.exec(`ALTER TABLE direct_receive_deferrals ADD COLUMN reminder_sent_at TEXT`);
|
|
932
|
+
}
|
|
933
|
+
catch { /* 已存在 */ }
|
|
934
|
+
try {
|
|
935
|
+
db.exec(`ALTER TABLE direct_receive_deferrals ADD COLUMN satisfied_at TEXT`);
|
|
936
|
+
}
|
|
937
|
+
catch { /* 已存在 */ }
|
|
938
|
+
// PR-6A: sanctions 结论有有效期(过期 → fail-closed)。additive nullable;NULL = 无期限(不过期)。
|
|
939
|
+
try {
|
|
940
|
+
db.exec(`ALTER TABLE sanctions_screening ADD COLUMN expires_at TEXT`);
|
|
941
|
+
}
|
|
942
|
+
catch { /* 已存在 */ }
|
|
943
|
+
// PR-6D: 支撑 #108 AML 监控的窗口查询(seller_id + payment_rail='direct_p2p' + created_at 范围)。
|
|
944
|
+
// 纯只读索引;不改行为、不打开任何规则。命名随既有 idx_orders_* 风格。
|
|
945
|
+
try {
|
|
946
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_orders_direct_pay_seller_window ON orders(seller_id, payment_rail, created_at)`);
|
|
947
|
+
}
|
|
948
|
+
catch { /* 已存在 */ }
|
|
949
|
+
// 币种回填(Claim 5 gated):把存量遗留内部代号 'DCP' 一次性刷成 'WAZ'。幂等、可重跑(每次 init 都跑,已是 WAZ 则 0 行);
|
|
950
|
+
// DCP 与 WAZ 是【同一模拟单位纯改名】,金额不变、无汇率换算;且全仓无 `currency='DCP'` 的筛选逻辑,不破坏任何查询。
|
|
951
|
+
// fresh-DB 默认已是 WAZ;existing-DB 新建单路径亦显式写 WAZ(见 products-create / MCP list_product / RFQ·auction fulfillment)。
|
|
952
|
+
try {
|
|
953
|
+
db.exec(`UPDATE products SET currency = 'WAZ' WHERE currency = 'DCP'`);
|
|
954
|
+
}
|
|
955
|
+
catch { /* products 表尚未建则跳过 */ }
|
|
956
|
+
// penalty 科目单行种子(只进不出;无出账代码路径)
|
|
957
|
+
db.exec(`INSERT OR IGNORE INTO penalty_fund (id, balance, total_fee_stake_slash, total_base_bond_slash, updated_at) VALUES ('main', 0, 0, 0, datetime('now'))`);
|
|
182
958
|
console.error('✅ L0-1 数据库初始化完成:', DB_PATH);
|
|
183
959
|
return db;
|
|
184
960
|
}
|