@seasonkoh/webaz 0.1.17 → 0.1.19
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/dist/layer0-foundation/L0-2-state-machine/engine.js +30 -54
- package/dist/layer1-agent/L1-1-mcp-server/server.js +88 -16
- package/dist/layer2-business/L2-8-feedback/build-feedback-engine.js +152 -5
- package/dist/layer2-business/L2-9-contribution/build-reputation-engine.js +106 -0
- package/dist/layer2-business/L2-9-contribution/build-tasks-engine.js +180 -0
- package/dist/pwa/public/app.js +49 -0
- package/dist/pwa/public/i18n.js +23 -0
- package/dist/pwa/routes/build-feedback.js +19 -3
- package/dist/pwa/routes/build-reputation.js +10 -0
- package/dist/pwa/routes/build-tasks.js +73 -0
- package/dist/pwa/routes/orders-create.js +7 -2
- package/dist/pwa/routes/wallet-write.js +17 -31
- package/dist/pwa/server.js +110 -5
- package/package.json +1 -1
package/dist/pwa/server.js
CHANGED
|
@@ -296,6 +296,10 @@ import { registerAuthLoginRoutes } from './routes/auth-login.js';
|
|
|
296
296
|
import { registerAuthRegisterRoutes } from './routes/auth-register.js';
|
|
297
297
|
import { registerBuildFeedbackRoutes } from './routes/build-feedback.js';
|
|
298
298
|
import { initBuildFeedbackSchema } from '../layer2-business/L2-8-feedback/build-feedback-engine.js';
|
|
299
|
+
import { registerBuildTasksRoutes } from './routes/build-tasks.js';
|
|
300
|
+
import { initBuildTasksSchema } from '../layer2-business/L2-9-contribution/build-tasks-engine.js';
|
|
301
|
+
import { registerBuildReputationRoutes } from './routes/build-reputation.js';
|
|
302
|
+
import { initBuildReputationSchema } from '../layer2-business/L2-9-contribution/build-reputation-engine.js';
|
|
299
303
|
const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
|
|
300
304
|
// ─── 链上地址派生 ──────────────────────────────────────────────
|
|
301
305
|
const MASTER_SEED = process.env.WALLET_MASTER_SEED ?? 'webaz-dev-seed-changeme';
|
|
@@ -348,6 +352,8 @@ initSkillMarketSchema(db);
|
|
|
348
352
|
initReputationSchema(db);
|
|
349
353
|
initOrderChainSchema(db);
|
|
350
354
|
initBuildFeedbackSchema(db); // RFC-004 build_feedback
|
|
355
|
+
initBuildTasksSchema(db); // RFC-006 build_tasks(协调层)
|
|
356
|
+
initBuildReputationSchema(db); // RFC-006 build_reputation(独立池 + 贡献者看板)
|
|
351
357
|
initSnfSchema(db);
|
|
352
358
|
initExternalAnchorSchema(db);
|
|
353
359
|
// 启动时检查月衰减(last_decay_at ≥25 天才触发,重启幂等)
|
|
@@ -525,6 +531,9 @@ for (const stmt of [
|
|
|
525
531
|
'ALTER TABLE orders ADD COLUMN gift_message TEXT',
|
|
526
532
|
// C-3: 订单保险 — 已支付保费(默认 1%,争议时若卖家余额不足由保险池补足)
|
|
527
533
|
'ALTER TABLE orders ADD COLUMN insurance_premium REAL DEFAULT 0',
|
|
534
|
+
// RFC-008 stage 1:每单【赔付背书】快照 = 该单实际背书的卖家质押额。
|
|
535
|
+
// 起步免赔付阶段(require_seller_stake=0)= 0;违约结算只按此数没收,绝不扣未背书的钱 → 根治印钱 bug。
|
|
536
|
+
'ALTER TABLE orders ADD COLUMN stake_backing REAL DEFAULT 0',
|
|
528
537
|
]) {
|
|
529
538
|
try {
|
|
530
539
|
db.exec(stmt);
|
|
@@ -761,10 +770,14 @@ try {
|
|
|
761
770
|
catch { }
|
|
762
771
|
// 已注册默认参数(首次启动 seed) — P0-2 加 min/max 边界
|
|
763
772
|
const DEFAULT_PARAMS = [
|
|
764
|
-
|
|
765
|
-
{ key: '
|
|
773
|
+
// RFC-008:平台费硬帽 2%(=当前稳态 → 治理只能在 0–2% 减免、永不涨)。合计封顶 = 平台费2% + fund_base1% = 3%。宪法级合法性见 CHARTER 修订(单独治理步)。
|
|
774
|
+
{ key: 'protocol_fee_rate_shop', value: '0.02', type: 'number', description: '商家订单平台费率(RFC-008 硬帽 2%,只减不涨;前期可减免)', category: 'fee', min: 0, max: 0.02 },
|
|
775
|
+
{ key: 'protocol_fee_rate_secondhand', value: '0.01', type: 'number', description: '二手订单平台费率(RFC-008 硬帽 2%,只减不涨)', category: 'fee', min: 0, max: 0.02 },
|
|
766
776
|
{ key: 'default_commission_rate', value: '0.05', type: 'number', description: '新商品默认分享佣金(对齐小红书 5-10%)', category: 'fee', min: 0, max: 0.50 },
|
|
767
|
-
|
|
777
|
+
// RFC-008:fund_base 硬帽 1%;pre-launch 减免到 0(社区基金按真实 GMV 注入,0 GMV 时是无回报的税)。有真实 GMV 再由治理开启(≤1%)。
|
|
778
|
+
{ key: 'fund_base_rate', value: '0', type: 'number', description: '协议基金池基础费率(RFC-008 硬帽 1%;pre-launch 减免=0,有真实 GMV 再由治理开启 ≤1%)', category: 'fee', min: 0, max: 0.01 },
|
|
779
|
+
// RFC-008:起步免赔付门槛。0 = bootstrap(新商家零质押、违约免赔付只退款+掉信誉,降进入门槛);1 = 要求卖家质押(下单锁 stake、违约真没收)。上轨道后由治理开启。
|
|
780
|
+
{ key: 'require_seller_stake', value: '0', type: 'number', description: 'RFC-008 是否要求卖家质押(0=起步免赔付/零门槛,1=要求质押/真没收)', category: 'fee', min: 0, max: 1 },
|
|
768
781
|
{ key: 'checkin_base_reward', value: '0.5', type: 'number', description: '每日签到基础奖励 WAZ', category: 'reward', min: 0, max: 10 },
|
|
769
782
|
{ key: 'streak_bonus_7', value: '5', type: 'number', description: '7 天里程碑额外奖励', category: 'reward', min: 0, max: 100 },
|
|
770
783
|
{ key: 'streak_bonus_30', value: '20', type: 'number', description: '30 天里程碑额外奖励', category: 'reward', min: 0, max: 500 },
|
|
@@ -797,6 +810,7 @@ const DEFAULT_PARAMS = [
|
|
|
797
810
|
{ key: 'require_human_presence_for_governance_activate', value: '1', type: 'number', description: 'maintainer 激活治理岗位(activate)需 WebAuthn 一次性 token — spec §4.4 Iron-Rule 真人签发', category: 'security', min: 0, max: 1 },
|
|
798
811
|
{ key: 'require_human_presence_for_governance_resign', value: '1', type: 'number', description: '主动卸任治理岗位(resign)需 WebAuthn 一次性 token — spec §6.1 二次验证', category: 'security', min: 0, max: 1 },
|
|
799
812
|
{ key: 'require_human_presence_for_governance_appeal_resolve', value: '1', type: 'number', description: 'maintainer 裁决申诉(resolve appeal)需 WebAuthn 一次性 token — spec §7.2 Iron-Rule', category: 'security', min: 0, max: 1 },
|
|
813
|
+
{ key: 'require_human_presence_for_withdraw', value: '1', type: 'number', description: '提现(资金转出)需 WebAuthn 一次性 token — 资金转出=真人在场铁律,email-OTP 在 agent 威胁模型下不足(agent 可读收件箱);#1115 全额对齐', category: 'security', min: 0, max: 1 },
|
|
800
814
|
{ key: 'governance_resign_cooldown_days', value: '30', type: 'number', description: '主动卸任后冷却期(天)— 防止 farming 切换洗票 / 误操作反复', category: 'governance', min: 7, max: 365 },
|
|
801
815
|
{ key: 'governance_appeal_window_days', value: '14', type: 'number', description: '收到 auto_deactivate 通知后申诉窗口(天)— spec §7.2', category: 'governance', min: 7, max: 90 },
|
|
802
816
|
{ key: 'governance_appeal_min_reason_chars', value: '100', type: 'number', description: '申诉理由最少字符数(防空 appeal)', category: 'governance', min: 30, max: 2000 },
|
|
@@ -894,6 +908,31 @@ try {
|
|
|
894
908
|
catch (e) {
|
|
895
909
|
console.error('[migration #1006]', e);
|
|
896
910
|
}
|
|
911
|
+
// RFC-008 迁移:费帽收紧 + fund_base pre-launch 减免。bounds 是协议护栏 → 无条件强制收窄(幂等)。
|
|
912
|
+
// 平台费帽 → 2%(=稳态,只减不涨);fund_base 帽 → 1%;合计封顶 3%。fund_base 值减免到 0(仅原始 0.01、未被治理改过)。
|
|
913
|
+
try {
|
|
914
|
+
const feeCap = db.prepare(`UPDATE protocol_params SET max_value = 0.02, updated_at = datetime('now')
|
|
915
|
+
WHERE key IN ('protocol_fee_rate_shop','protocol_fee_rate_secondhand') AND max_value > 0.02`).run();
|
|
916
|
+
if (feeCap.changes > 0)
|
|
917
|
+
console.log(`[migration RFC-008] 平台费硬帽收紧 ${feeCap.changes} 项 → max 2%`);
|
|
918
|
+
const fbCap = db.prepare(`UPDATE protocol_params SET max_value = 0.01, updated_at = datetime('now')
|
|
919
|
+
WHERE key = 'fund_base_rate' AND max_value > 0.01`).run();
|
|
920
|
+
if (fbCap.changes > 0)
|
|
921
|
+
console.log(`[migration RFC-008] fund_base 硬帽收紧 → max 1%`);
|
|
922
|
+
const fb = db.prepare(`UPDATE protocol_params SET value = '0', default_value = '0', updated_at = datetime('now')
|
|
923
|
+
WHERE key = 'fund_base_rate' AND value = '0.01' AND updated_by IS NULL`).run();
|
|
924
|
+
if (fb.changes > 0) {
|
|
925
|
+
console.log(`[migration RFC-008] fund_base_rate 0.01 → 0 (pre-launch 减免)`);
|
|
926
|
+
try {
|
|
927
|
+
db.prepare(`INSERT INTO protocol_params_log (id, key, old_value, new_value, changed_by, action)
|
|
928
|
+
VALUES (?,?,?,?,?,'migrate')`).run(generateId('ppl'), 'fund_base_rate', '0.01', '0', 'migration_RFC-008');
|
|
929
|
+
}
|
|
930
|
+
catch { }
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
catch (e) {
|
|
934
|
+
console.error('[migration RFC-008]', e);
|
|
935
|
+
}
|
|
897
936
|
// Wave G-2: USDC ↔ WAZ 转换助手
|
|
898
937
|
function usdcToWaz(usdc) {
|
|
899
938
|
const rate = getProtocolParam('waz_usdc_rate', 1.0);
|
|
@@ -5240,7 +5279,63 @@ function endpointToAction(method, path) {
|
|
|
5240
5279
|
return 'rfq';
|
|
5241
5280
|
if (method === 'POST' && /^\/api\/auctions\/[^/]+\/bid/.test(path))
|
|
5242
5281
|
return 'bid';
|
|
5243
|
-
|
|
5282
|
+
// 权限审计 #1115 P0:花钱/价值写纳入问责门(与 place_order 同档:无 Passkey 须声明 scope)。
|
|
5283
|
+
// 之前这些漏在 default-allow 之外,无声明无 Passkey 的 agent 可花掉账户余额 —— 补齐一致性。
|
|
5284
|
+
if (method === 'POST' && /^\/api\/skill-market\/[^/]+\/purchase/.test(path))
|
|
5285
|
+
return 'purchase';
|
|
5286
|
+
if (method === 'POST' && /^\/api\/secondhand\/[^/]+\/order/.test(path))
|
|
5287
|
+
return 'buy_secondhand';
|
|
5288
|
+
if (method === 'POST' && /^\/api\/group-buys\/[^/]+\/join/.test(path))
|
|
5289
|
+
return 'group_buy_join';
|
|
5290
|
+
// #1115 P1:写 PII(收货地址)也需问责。含 addresses 增删改 + profile 默认地址。
|
|
5291
|
+
if (method !== 'GET' && (/^\/api\/addresses(\/|$)/.test(path) || path === '/api/profile/default-address'))
|
|
5292
|
+
return 'set_address';
|
|
5293
|
+
// #1115 P2:钱包写(转出/充值/白名单/连接)统一纳入 'wallet' 问责门。
|
|
5294
|
+
// 之前 wallet/* 整段在 SAFE 放行 → api_key agent 可直达 withdraw,小额零真人门分批盗刷;
|
|
5295
|
+
// 现要求声明 'wallet' scope(或 '*' / Passkey)。withdraw 另在 handler 内强制 Passkey 真人门(铁律,见 wallet-write.ts)。
|
|
5296
|
+
if (method !== 'GET' && /^\/api\/wallet\//.test(path))
|
|
5297
|
+
return 'wallet';
|
|
5298
|
+
// #1115 P2:profile **PII/身份/接管向量**写纳入 'set_profile' —— 仅这一子集需问责。
|
|
5299
|
+
// 改恢复邮箱(bind/confirm-email)=账户接管;改 handle/name=身份;set/clear-location=地理 PII。
|
|
5300
|
+
// ⚠️ 不一刀切整段 profile/*:role/region/placement/password/verify 是"无 Passkey 也要能用"的
|
|
5301
|
+
// 自助操作(见原则:没身份验证也要解决的问题不要求身份),它们留在下方 SAFE。
|
|
5302
|
+
// default-address 已在上面归 set_address(更具体,优先)。
|
|
5303
|
+
if (method !== 'GET' && /^\/api\/profile\/(bind-email|confirm-email|change-handle|change-name|set-location|clear-location)$/.test(path))
|
|
5304
|
+
return 'set_profile';
|
|
5305
|
+
// ── #1115 B4 结构性:default-deny ──────────────────────────────
|
|
5306
|
+
// 上面是细粒度命名 token;下面 safe-list 放行(返回 null),其余一切写 → 'write'(需 Passkey 或声明 scope)。
|
|
5307
|
+
// 目的:新增的敏感写默认就被门控,不会因"忘了加映射"而裸奔(把 default-allow 翻成 default-deny)。
|
|
5308
|
+
// safe-list 三类必须放行(否则误伤 / 死锁):
|
|
5309
|
+
// (a) 脱困入口:绑 Passkey(webauthn)/ 声明 scope(me/agents)/ 登录注册/找回 —— 若门控则永远无法获得通行资格
|
|
5310
|
+
// (b) 自带门:build-feedback(分级门)/ admin(requireAdmin)。
|
|
5311
|
+
// 注意:wallet / profile 不再 SAFE —— #1115 P2 移到上方命名 token(wallet / set_profile / set_address)。
|
|
5312
|
+
// (c) 公开 + 低值自我状态写(管理自己的 cart/wishlist/通知/关注 等,登录即可)
|
|
5313
|
+
const SAFE = [
|
|
5314
|
+
// (a) 脱困 / 鉴权 / 身份(bootstrap 通行资格所必需 —— wallet 与 profile 的 PII 子集不在此列,见上方命名 token)
|
|
5315
|
+
/^\/api\/(login|register)$/, /^\/api\/recover-key/, /^\/api\/webauthn\//,
|
|
5316
|
+
/^\/api\/me\/agents\//,
|
|
5317
|
+
// profile 自助子集(无 Passkey 真人也要能用:切角色/选地区/PV 配置/改密码/二次确认)。
|
|
5318
|
+
// PII/身份子集(bind-email/change-handle/set-location 等)已在上方归 set_profile,不在此放行。
|
|
5319
|
+
/^\/api\/profile\/(switch-role|add-role|region|placement-pref|bind-placement|feed-visible|verify-password|set-password|remove-password)$/,
|
|
5320
|
+
// (b) 自带门(build-feedback=分级门;build-tasks=协调层登录即可;admin=requireAdmin。wallet/profile 已移到上方命名 token #1115 P2)
|
|
5321
|
+
/^\/api\/build-feedback/, /^\/api\/build-tasks/, /^\/api\/admin\//,
|
|
5322
|
+
// (c) 公开 / 无需登录
|
|
5323
|
+
/^\/api\/(public-ideas|error-report|mcp-telemetry|email-subscriptions|search-by-link|feedback)(\/|$)/,
|
|
5324
|
+
// (c) 低值自我状态
|
|
5325
|
+
/^\/api\/cart$/, /^\/api\/cart\/(?!checkout)[^/]+$/,
|
|
5326
|
+
/^\/api\/wishlist/, /^\/api\/products\/[^/]+\/waitlist$/,
|
|
5327
|
+
/^\/api\/notifications\/read$/, /^\/api\/announcements\/[^/]+\/read$/,
|
|
5328
|
+
/^\/api\/follows\//, /^\/api\/blocklist\//,
|
|
5329
|
+
/^\/api\/checkin$/, /^\/api\/growth\/tasks\//, /^\/api\/tasks\/[^/]+\/claim$/,
|
|
5330
|
+
/^\/api\/push\//, /^\/api\/auth\//,
|
|
5331
|
+
/^\/api\/me\/(delete-cancel|notify-claim-tasks)/,
|
|
5332
|
+
/^\/api\/peers\//, /^\/api\/signaling\//,
|
|
5333
|
+
/^\/api\/product-share\/touch$/, /^\/api\/anchor\/[^/]+\/touch$/,
|
|
5334
|
+
/^\/api\/reviews\//,
|
|
5335
|
+
];
|
|
5336
|
+
if (SAFE.some(r => r.test(path)))
|
|
5337
|
+
return null;
|
|
5338
|
+
return 'write'; // 默认拒绝:其余写需问责
|
|
5244
5339
|
}
|
|
5245
5340
|
// Phase 3b(B1):敏感读 → read-scope token 映射。只挑「跨用户聚合 / 批量扫描」这类剽窃向读取,
|
|
5246
5341
|
// 普通读(自己的 profile / products 列表 / 订单等)一律 null 不约束,避免误伤声明 agent 的日常读。
|
|
@@ -5703,6 +5798,13 @@ registerBuildFeedbackRoutes(app, {
|
|
|
5703
5798
|
db, auth,
|
|
5704
5799
|
requireSupportAdmin: (req, res) => requireAdminPermission(req, res, 'support'),
|
|
5705
5800
|
});
|
|
5801
|
+
// RFC-006 Gap 1:协调层(build_tasks "谁在做什么")
|
|
5802
|
+
registerBuildTasksRoutes(app, {
|
|
5803
|
+
db, auth,
|
|
5804
|
+
requireSupportAdmin: (req, res) => requireAdminPermission(req, res, 'support'),
|
|
5805
|
+
});
|
|
5806
|
+
// RFC-006 Gap 2:贡献者自查看板(build_reputation 独立池)
|
|
5807
|
+
registerBuildReputationRoutes(app, { db, auth });
|
|
5706
5808
|
// #1013 Phase 48: 3 auth/sessions endpoints 已迁出到 routes/auth-sessions.ts
|
|
5707
5809
|
registerAuthSessionsRoutes(app, { db, auth, verifyPassword, recordSession, generateSecureKey });
|
|
5708
5810
|
// 个人资料:查看 API Key + 联系方式
|
|
@@ -8876,8 +8978,11 @@ function settleOrder(orderId) {
|
|
|
8876
8978
|
// 用单语句 UPDATE ... WHERE stake_locked_at IS NULL 原子拿"是否首次"判定,
|
|
8877
8979
|
// 避免读后写竞态(旧实现两条语句,迁 PG / 多 worker 时可能双锁)
|
|
8878
8980
|
// M8: 二手商品无 stake 概念,跳过
|
|
8981
|
+
// RFC-008 stage 1:起步免赔付阶段(require_seller_stake=0)不锁 stake —— 与 settleFault 按 stake_backing(=0)结算一致,
|
|
8982
|
+
// 消除"成功时锁 product.stake_amount 但违约按 backing=0 不没收"的旧三口径不一致。收紧档(=1)由后续阶段统一在下单锁。
|
|
8983
|
+
const requireSellerStake = Number(getProtocolParam('require_seller_stake', 0)) === 1;
|
|
8879
8984
|
let stakeToLock = 0;
|
|
8880
|
-
if (!isSecondhand) {
|
|
8985
|
+
if (!isSecondhand && requireSellerStake) {
|
|
8881
8986
|
const lockResult = db.prepare(`UPDATE products SET stake_locked_at = datetime('now') WHERE id = ? AND stake_locked_at IS NULL`).run(order.product_id);
|
|
8882
8987
|
if (lockResult.changes === 1) {
|
|
8883
8988
|
const sellerTrust = db.prepare(`SELECT level FROM reputation_scores WHERE user_id = ?`).get(order.seller_id);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seasonkoh/webaz",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "[PRE-LAUNCH] Agent-native decentralized commerce protocol. Humans and AI agents trade on the same protocol via MCP tools. ⚠️ Repository currently private until W8 public launch — GitHub links may return 404. See https://webaz.xyz for status.",
|
|
5
5
|
"main": "dist/mcp.js",
|
|
6
6
|
"bin": {
|