@seasonkoh/webaz 0.1.30 → 0.1.32

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 (33) hide show
  1. package/README.md +3 -1
  2. package/dist/layer0-foundation/L0-2-state-machine/engine.js +1 -1
  3. package/dist/layer1-agent/L1-1-mcp-server/network-mode.js +4 -0
  4. package/dist/layer1-agent/L1-1-mcp-server/server.js +202 -19
  5. package/dist/layer2-business/L2-6-notifications/notification-engine.js +96 -0
  6. package/dist/layer3-trust/L3-1-dispute-engine/decline-contest-resolve.js +110 -0
  7. package/dist/layer3-trust/L3-1-dispute-engine/dispute-engine.js +109 -0
  8. package/dist/pwa/agent-order-minimal-view.js +29 -0
  9. package/dist/pwa/order-action-exec.js +158 -0
  10. package/dist/pwa/order-action-request.js +57 -0
  11. package/dist/pwa/public/app-admin-disputes.js +1 -1
  12. package/dist/pwa/public/app-agent-approvals-order.js +18 -0
  13. package/dist/pwa/public/app-agent-approvals.js +6 -7
  14. package/dist/pwa/public/app-agent-pair.js +2 -2
  15. package/dist/pwa/public/app-arbitrator-admin.js +1 -1
  16. package/dist/pwa/public/app-decline-contest-ruling.js +53 -0
  17. package/dist/pwa/public/app-decline-contest-ui.js +44 -0
  18. package/dist/pwa/public/app-grant-duration.js +20 -0
  19. package/dist/pwa/public/app.js +9 -9
  20. package/dist/pwa/public/i18n.js +24 -1
  21. package/dist/pwa/public/index.html +4 -0
  22. package/dist/pwa/public/openapi.json +78 -23
  23. package/dist/pwa/routes/admin-reports.js +40 -3
  24. package/dist/pwa/routes/agent-grants.js +147 -14
  25. package/dist/pwa/routes/disputes-read.js +17 -1
  26. package/dist/pwa/routes/disputes-write.js +42 -73
  27. package/dist/pwa/routes/orders-action.js +46 -3
  28. package/dist/pwa/routes/products-create.js +33 -13
  29. package/dist/pwa/routes/webauthn.js +1 -1
  30. package/dist/pwa/server.js +7 -7
  31. package/dist/runtime/agent-grant-scopes.js +26 -8
  32. package/dist/runtime/webaz-schema-helpers.js +28 -0
  33. package/package.json +15 -2
@@ -1,12 +1,12 @@
1
1
  import { dbOne, dbRun } from '../../layer0-foundation/L0-1-database/db.js'; // RFC-016 异步 DB seam
2
- export function registerProductsCreateRoutes(app, deps) {
3
- const { db, auth, generateId, checkSellerCanList, getStakeDiscount, VALID_PRODUCT_TYPES, parsePlatformUrl, makeCommitmentHash, makeDescriptionHash, makePriceHash } = deps;
4
- app.post('/api/products', async (req, res) => {
5
- const user = auth(req, res);
6
- if (!user)
7
- return;
8
- if (user.role !== 'seller')
9
- return void res.json({ error: '仅卖家可上架商品' });
2
+ /**
3
+ * The SINGLE source of product-create validation + insert. res-coupled but auth-agnostic: the caller resolves
4
+ * `user` (the human api_key route, OR the delegation-grant draft route) and may force `warehouse` status. Both
5
+ * the human `POST /api/products` and the grant-gated draft route MUST go through this — no parallel copy.
6
+ */
7
+ export function makeCreateProductHandler(deps) {
8
+ const { db, generateId, checkSellerCanList, getStakeDiscount, VALID_PRODUCT_TYPES, parsePlatformUrl, makeCommitmentHash, makeDescriptionHash, makePriceHash } = deps;
9
+ return async function createProductHandler(req, res, user, opts = {}) {
10
10
  // 里程碑 3-D:1h 上架限速(防 spam 批量上架)
11
11
  const LISTING_RATE_LIMIT = 5;
12
12
  const recentListings = (await dbOne(`
@@ -55,7 +55,7 @@ export function registerProductsCreateRoutes(app, deps) {
55
55
  return void res.json({ error: 'commission_rate 必须在 1% - 50% 之间(小数 0.01-0.50)' });
56
56
  }
57
57
  // 上架前检查:同一卖家不能重复关联相同外部链接
58
- if (source_url) {
58
+ if (source_url && !opts.skipExternalLinkEffects) {
59
59
  const sameSellerDupe = (await dbOne(`
60
60
  SELECT COUNT(*) as n FROM product_external_links pel
61
61
  JOIN products p ON pel.product_id = p.id
@@ -94,14 +94,14 @@ export function registerProductsCreateRoutes(app, deps) {
94
94
  ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,'WAZ',?,?,?,?,?,?)`, [
95
95
  id, user.id, title, description, priceNum, Number(stock), category, stakeAmount,
96
96
  specsJson, brand ?? null, model ?? null,
97
- source_url ?? null, source_price ? Number(source_price) : null, source_price ? now : null,
97
+ opts.skipExternalLinkEffects ? null : (source_url ?? null), opts.skipExternalLinkEffects ? null : (source_price ? Number(source_price) : null), opts.skipExternalLinkEffects ? null : (source_price ? now : null),
98
98
  weight_kg ? Number(weight_kg) : null, ship_regions, Number(handling_hours), estJson, fragile ? 1 : 0,
99
99
  Number(return_days), return_condition, Number(warranty_days),
100
100
  Math.max(0, Math.floor(Number(low_stock_threshold) || 0)), auto_delist_on_zero ? 1 : 0,
101
101
  makeCommitmentHash(pFields), makeDescriptionHash({ title, description, specs: specsJson }),
102
102
  makePriceHash(priceNum, now), now,
103
103
  commissionRateNum, product_type, imagesJsonForInsert,
104
- _tx(package_size, 40), _cc(origin_country), _cc(country_of_origin), _tx(customs_description, 120), _hs, create_status === 'warehouse' ? 'warehouse' : 'active'
104
+ _tx(package_size, 40), _cc(origin_country), _cc(country_of_origin), _tx(customs_description, 120), _hs, (opts.forceStatus === 'warehouse' || create_status === 'warehouse') ? 'warehouse' : 'active'
105
105
  ]);
106
106
  // M7.2.6:免质押上架 — 不再扣 stake;首单成交时 settleOrder 自动从订单 escrow 锁定
107
107
  // M7.2-6: 上架时同步入 aliases(卖家已勾选的 candidates)
@@ -128,7 +128,7 @@ export function registerProductsCreateRoutes(app, deps) {
128
128
  }
129
129
  // 来源链接:冲突检测
130
130
  let linkConflict = null;
131
- if (source_url) {
131
+ if (source_url && !opts.skipExternalLinkEffects) {
132
132
  // 另一家卖家已认领此链接(verified=1)
133
133
  const otherClaim = await dbOne(`
134
134
  SELECT pel.product_id FROM product_external_links pel
@@ -183,7 +183,7 @@ export function registerProductsCreateRoutes(app, deps) {
183
183
  // 额外链接:同步冲突检查(最多 5 个)
184
184
  const additionalLinks = req.body.additional_links;
185
185
  const blockedLinks = [];
186
- if (Array.isArray(additionalLinks) && additionalLinks.length > 0) {
186
+ if (!opts.skipExternalLinkEffects && Array.isArray(additionalLinks) && additionalLinks.length > 0) {
187
187
  for (const extraUrl of additionalLinks.slice(0, 5)) {
188
188
  if (typeof extraUrl !== 'string' || !extraUrl.startsWith('http'))
189
189
  continue;
@@ -220,13 +220,33 @@ export function registerProductsCreateRoutes(app, deps) {
220
220
  catch { }
221
221
  }
222
222
  }
223
+ if (opts.onCreated) {
224
+ try {
225
+ await opts.onCreated(id);
226
+ }
227
+ catch (e) {
228
+ console.error('[products-create onCreated]', e.message);
229
+ }
230
+ }
223
231
  res.json({
224
232
  success: true,
225
233
  product_id: id,
234
+ status: (opts.forceStatus === 'warehouse' || create_status === 'warehouse') ? 'warehouse' : 'active',
226
235
  stake_locked: 0, // 免质押上架(M7.2.6 方案 3)
227
236
  stake_deferred: stakeAmount, // 首单成交时自动锁定(trusted+ 跳过)
228
237
  ...(linkConflict ? { link_conflict: linkConflict } : {}),
229
238
  ...(blockedLinks.length > 0 ? { blocked_links: blockedLinks } : {}),
230
239
  });
240
+ };
241
+ }
242
+ export function registerProductsCreateRoutes(app, deps) {
243
+ const createProductHandler = makeCreateProductHandler(deps);
244
+ app.post('/api/products', async (req, res) => {
245
+ const user = deps.auth(req, res);
246
+ if (!user)
247
+ return;
248
+ if (user.role !== 'seller')
249
+ return void res.json({ error: '仅卖家可上架商品' });
250
+ await createProductHandler(req, res, user);
231
251
  });
232
252
  }
@@ -196,5 +196,5 @@ export function registerWebauthnRoutes(app, deps) {
196
196
  // RFC-020 PR-B — agent delegation grants (issue/read/revoke). Co-registered with the
197
197
  // Passkey security routes so the money-dense server.ts stays untouched. Safe scopes
198
198
  // only; risk scopes default-hard-reject. Reuses db/auth/generateId from WebauthnDeps.
199
- registerAgentGrantsRoutes(app, { db, auth, generateId, rateLimitOk, requireHumanPresence });
199
+ registerAgentGrantsRoutes(app, { db, auth, generateId, rateLimitOk, requireHumanPresence, createProductDraftHandler: deps.createProductDraftHandler });
200
200
  }
@@ -40,7 +40,7 @@ import { initExternalAnchorSchema } from '../layer1-agent/L1-2-external-anchor/a
40
40
  import { ensureEvidenceColumns, uploadEvidence, listEvidence as listEvidenceFiles, markEvidenceExpiry, cleanupExpiredEvidence, EVIDENCE_MAX_BYTES, EVIDENCE_ALLOWED_MIME, } from '../layer3-trust/L3-1-dispute-engine/evidence-storage.js';
41
41
  import { cleanupOrphanNotePhotos, } from '../layer2-business/L2-notes/note-photo-storage.js';
42
42
  import { initAnchorRegistrySchema, retireAnchorsByTarget, reclaimRetiredAnchors, retireIdleAnchors, userReferralVolume, computeTierLetter, } from '../layer2-business/L2-anchor-registry/anchor-registry.js';
43
- import { initDisputeSchema, createDispute, respondToDispute, arbitrateDispute, getOrderDispute, getDisputeDetails, getOpenDisputes, checkDisputeTimeouts, initEvidenceRequestSchema, requestEvidence, getEvidenceRequests, addPartyEvidence, } from '../layer3-trust/L3-1-dispute-engine/dispute-engine.js';
43
+ import { initDisputeSchema, createDispute, createDeclineContestDispute, respondToDispute, arbitrateDispute, getOrderDispute, getDisputeDetails, getOpenDisputes, checkDisputeTimeouts, initEvidenceRequestSchema, requestEvidence, getEvidenceRequests, addPartyEvidence, } from '../layer3-trust/L3-1-dispute-engine/dispute-engine.js';
44
44
  import { initMutualCancelSchema } from '../layer3-trust/L3-1-dispute-engine/mutual-cancel.js';
45
45
  import { registerMutualCancelRoutes } from './routes/mutual-cancel.js';
46
46
  import { initDirectPayCancelRefundSchema } from '../direct-pay-cancel-refund.js';
@@ -283,7 +283,7 @@ import { registerProductsCrudRoutes } from './routes/products-crud.js';
283
283
  // Products PUT update (#1013 Phase 93) — 1 endpoint (123 行)
284
284
  import { registerProductsUpdateRoutes } from './routes/products-update.js';
285
285
  // Products POST create (#1013 Phase 94) — 1 endpoint (232 行)
286
- import { registerProductsCreateRoutes } from './routes/products-create.js';
286
+ import { registerProductsCreateRoutes, makeCreateProductHandler } from './routes/products-create.js';
287
287
  // Products GET list (#1013 Phase 95) — 1 endpoint (399 行)
288
288
  import { registerProductsListRoutes } from './routes/products-list.js';
289
289
  // P2P 商品 (#1013 Phase 96) — 5 endpoints
@@ -4091,8 +4091,8 @@ app.use((req, res, next) => {
4091
4091
  if (req.method === 'GET' && /^\/api\/(info|leaderboard|payment-methods|governance|openapi)/.test(req.path))
4092
4092
  return next();
4093
4093
  const apiKey = req.headers.authorization?.replace('Bearer ', '');
4094
- if (!apiKey)
4095
- return next(); // 无 key 走原 IP 速率
4094
+ if (!apiKey || apiKey.startsWith('gtk_'))
4095
+ return next(); // 无 key→IP 速率;gtk_* 委托凭证(RFC-020)是独立自守 auth 通道(requireAgentGrantScope/resolveActiveGrantByBearer 管 safe-scope+active/expiry/revoked+audit),非 api_key,不进下面 agent 声明/风控/strike;否则合法 safe-scope grant 写(如 POST /api/agent-grants/permission-requests)被误判 AGENT_SCOPE_UNDECLARED。gtk_* 只命中 grant-aware 路由,别处 auth() 自然 401。
4096
4096
  // 2026-05-23 P1 fix:被封禁用户仍可走以下路径(看自己 agent 状态 + 申诉)
4097
4097
  // - GET /api/me/agents 系列(看强 / 申诉前必查)
4098
4098
  // - POST /api/me/agents/strikes/:id/appeal(申诉权不能被封禁阻断)
@@ -5401,7 +5401,7 @@ function computeLightTags(user, mod, vWhite, vAppPending) {
5401
5401
  }
5402
5402
  // #1013 Phase 101: admin/orders + admin/disputes + admin/verify-tasks + admin/audit-log 已迁出
5403
5403
  registerAdminReportsRoutes(app, {
5404
- db,
5404
+ db, requireHumanPresence,
5405
5405
  requireContentAdmin: (req, res) => requireAdminPermission(req, res, 'content'),
5406
5406
  requireArbitrationAdmin: (req, res) => requireAdminPermission(req, res, 'arbitration'),
5407
5407
  requireProtocolAdmin: (req, res) => requireAdminPermission(req, res, 'protocol'),
@@ -6053,7 +6053,7 @@ registerOrdersReadRoutes(app, { db, auth, getOrderStatus, getOrderChain, verifyO
6053
6053
  // 注意:settleOrder 是函数声明(hoisted)但绑了 db 闭包,无需注入 db
6054
6054
  registerOrdersActionRoutes(app, {
6055
6055
  db, auth, isTrustedRole, generateId, transition, notifyTransition,
6056
- settleOrder, settleFault, detectFraud, createDispute, checkTimeouts, recordViolationReputation,
6056
+ settleOrder, settleFault, detectFraud, createDispute, createDeclineContestDispute, checkTimeouts, recordViolationReputation,
6057
6057
  broadcastSystemEvent, consumeGateToken,
6058
6058
  });
6059
6059
  // #1013 Phase 85: POST /api/orders 巨型事务已迁出
@@ -7870,7 +7870,7 @@ registerWebauthnRoutes(app, {
7870
7870
  origin: WEBAUTHN_ORIGIN,
7871
7871
  challengeTtlMs: WEBAUTHN_CHALLENGE_TTL_MS,
7872
7872
  gateTtlMs: WEBAUTHN_GATE_TTL_MS,
7873
- invalidateAgentRiskCacheForUser,
7873
+ invalidateAgentRiskCacheForUser, createProductDraftHandler: makeCreateProductHandler({ db, auth, generateId, checkSellerCanList, getStakeDiscount, VALID_PRODUCT_TYPES, parsePlatformUrl, makeCommitmentHash, makeDescriptionHash, makePriceHash }), // RFC-020 PR-4: grant-gated warehouse draft reuses the human create logic
7874
7874
  requireHumanPresence, // #1044 — DELETE passkey 自身需 token
7875
7875
  });
7876
7876
  // consumeGateToken / requireHumanPresence 已抽出到 ./human-presence.ts(PR-F0,behavior-zero,
@@ -34,6 +34,12 @@ export const SAFE_SCOPES = [
34
34
  'seller_inventory_read',
35
35
  'seller_product_draft',
36
36
  'seller_pricing_suggestion',
37
+ // RFC-021 Fulfillment Agent (order 侧 申请→人工 Passkey 批准). BOTH safe:
38
+ // seller_orders_read_minimal = 最小化订单读(无买家地址/联系);
39
+ // order_action_request = SUBMIT-only —— 只能把 {accept|ship} 请求塞进人的审批队列,【绝不执行】;
40
+ // 执行始终由人 Passkey 逐笔批准后服务端跑(RFC-021 §5/§6b)。RISK 档 order_accept/order_ship 不动、仍硬拒。
41
+ 'seller_orders_read_minimal',
42
+ 'order_action_request',
37
43
  ];
38
44
  /**
39
45
  * Real actions that WILL require a live Passkey each time — but are NOT yet gated
@@ -141,6 +147,14 @@ export const PERMISSION_BUNDLES = {
141
147
  human_summary: '选品、商品草稿、库存字段检查、价格建议、上架请求。它不能发布商品、不能接单、不能发货、不能动用资金。',
142
148
  human_summary_en: 'Sourcing, product drafts, inventory-field checks, pricing suggestions, and publish REQUESTS. It cannot publish products, accept orders, ship, or move funds.',
143
149
  },
150
+ // RFC-021:独立于 catalog_agent 授予/撤销/TTL(§15.1)。仅含两个 SAFE scope,均不直接执行订单动作。
151
+ fulfillment_agent: {
152
+ key: 'fulfillment_agent',
153
+ label: 'Fulfillment Agent',
154
+ scopes: ['seller_orders_read_minimal', 'order_action_request'],
155
+ human_summary: '读你订单的最小信息(订单号/状态/下一步责任方/截止/金额/商品),再把"接单/发货"请求提交到你的审批队列等你逐笔 Passkey 批准。它【不能】直接接单或发货、看不到买家收货地址与联系方式(接单获批前)、不动任何资金。',
156
+ human_summary_en: 'Reads a minimal view of your orders (id / status / next actor / deadline / amount / item) and SUBMITS "accept / ship" requests into your approval queue for you to approve one-by-one with Passkey. It CANNOT accept or ship directly, cannot see the buyer\'s shipping address or contact (before an accept is approved), and moves no funds.',
157
+ },
144
158
  };
145
159
  /** Resolve a bundle key → its safe scopes + human summary, or null if unknown. */
146
160
  export function resolveBundle(key) {
@@ -159,27 +173,31 @@ for (const b of Object.values(PERMISSION_BUNDLES)) {
159
173
  export const DURATION_SECONDS = { '1h': 3600, '24h': 86400, '7d': 604800, '30d': 2592000 };
160
174
  /**
161
175
  * Which durations a set of scopes may be granted for, capped by the HIGHEST risk tier present:
162
- * - never-delegable / unknown → [] (cannot be granted at all)
163
- * - risk (high) → ['once'] (single Passkey each time; NEVER long-term)
164
- * - safe (low/medium) → once…30d (long-term ok)
176
+ * - never-delegable / unknown → [] (cannot be granted at all)
177
+ * - risk (high) → [] (not delegable to a persistent grant)
178
+ * - safe (low/medium) → 1h / 24h / 7d / 30d (long-term ok)
179
+ * NOTE: 'once' is intentionally NOT offered. It's a real single-use concept, but no single-use grant
180
+ * CONSUMPTION mechanism exists yet — durationToSeconds('once') would fall back to a 1h *reusable* bearer,
181
+ * which misleads. Until a true single-use grant is built, 'once' stays out of the allowed set / UI / i18n.
165
182
  */
166
183
  export function allowedDurationsForScopes(scopes) {
167
184
  const tiers = scopes.map(classifyScope);
168
185
  if (tiers.some(t => t === 'never_delegable' || t === 'unknown'))
169
186
  return [];
170
187
  if (tiers.some(t => t === 'risk'))
171
- return ['once'];
172
- return ['once', '1h', '24h', '7d', '30d'];
188
+ return [];
189
+ return ['1h', '24h', '7d', '30d'];
173
190
  }
174
191
  export function durationAllowedForScopes(scopes, duration) {
175
192
  return typeof duration === 'string' && allowedDurationsForScopes(scopes).includes(duration);
176
193
  }
177
- /** Suggested default: 7d for long-term-eligible safe scopes; else the safest available (once). */
194
+ /** Suggested default: 7d for long-term-eligible safe scopes; else the safest available. */
178
195
  export function suggestedDurationForScopes(scopes) {
179
196
  const a = allowedDurationsForScopes(scopes);
180
- return a.includes('7d') ? '7d' : (a[0] ?? 'once');
197
+ return a.includes('7d') ? '7d' : (a[0] ?? '7d');
181
198
  }
182
- /** Grant lifetime in seconds for an approved (non-'once') duration. 'once' handled separately (single-use). */
199
+ /** Grant lifetime in seconds. 'once' is RESERVED for a future single-use grant (no consumption path yet) and
200
+ * is never offered; if it somehow arrives it maps to 0 → callers fall back to a short window. */
183
201
  export function durationToSeconds(duration) {
184
202
  return duration === 'once' ? 0 : DURATION_SECONDS[duration];
185
203
  }
@@ -1844,6 +1844,28 @@ export function initAgentPermissionRequestsSchema(db) {
1844
1844
  `);
1845
1845
  db.exec(`CREATE INDEX IF NOT EXISTS idx_apr_human ON agent_permission_requests(human_id, status)`);
1846
1846
  db.exec(`CREATE INDEX IF NOT EXISTS idx_apr_status ON agent_permission_requests(status, expires_at)`);
1847
+ // RFC-021 PR2:order-action 请求复用本队列(I9)。新列均可空;kind 默认 'scope_grant' → 旧行行为不变,零迁移。
1848
+ // executed_at / execution_result 本 PR 只建列【永不写】(PR3 才写);ALTER-AFTER-CREATE 幂等。
1849
+ for (const stmt of [
1850
+ "ALTER TABLE agent_permission_requests ADD COLUMN kind TEXT DEFAULT 'scope_grant'", // scope_grant | order_action
1851
+ "ALTER TABLE agent_permission_requests ADD COLUMN order_id TEXT",
1852
+ "ALTER TABLE agent_permission_requests ADD COLUMN order_action TEXT", // accept | ship(v1)
1853
+ "ALTER TABLE agent_permission_requests ADD COLUMN params_hash TEXT", // I2 绑定键 SHA-256(order_id,action,params)
1854
+ "ALTER TABLE agent_permission_requests ADD COLUMN action_params TEXT", // JSON:ship 的 {tracking,evidence_ref};accept '{}'
1855
+ "ALTER TABLE agent_permission_requests ADD COLUMN executed_at TEXT", // I5 幂等 CAS 键 —— PR3 写,PR2 恒 NULL
1856
+ "ALTER TABLE agent_permission_requests ADD COLUMN execution_result TEXT", // I7 执行结果 —— PR3 写
1857
+ ]) {
1858
+ try {
1859
+ db.exec(stmt);
1860
+ }
1861
+ catch { /* 列已存在 */ }
1862
+ }
1863
+ // 防双 pending + I5 幂等根基:同一 (order_id, order_action) 至多一条未终结(pending/approved)的 order_action 请求。
1864
+ // rejected/expired/executed 为终态,不占索引 → 允许事后重新提交。
1865
+ try {
1866
+ db.exec("CREATE UNIQUE INDEX IF NOT EXISTS ux_apr_order_action_active ON agent_permission_requests(order_id, order_action) WHERE kind='order_action' AND status IN ('pending','approved')");
1867
+ }
1868
+ catch { /* */ }
1847
1869
  }
1848
1870
  /**
1849
1871
  * RFC-020 PR-C1 — agent pairing sessions (OAuth device-flow + PKCE shape).
@@ -1877,6 +1899,12 @@ export function initAgentPairingSchema(db) {
1877
1899
  `);
1878
1900
  db.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_aps_user_code ON agent_pairing_sessions(user_code)`);
1879
1901
  db.exec(`CREATE INDEX IF NOT EXISTS idx_aps_status ON agent_pairing_sessions(status, expires_at)`);
1902
+ // RFC-020 duration-choice: the agent's SUGGESTED grant lifetime (once/1h/24h/7d/30d) shown in consent so the
1903
+ // human can accept or override it at approve. Safe-scope only; the human's choice wins. ALTER after CREATE.
1904
+ try {
1905
+ db.exec("ALTER TABLE agent_pairing_sessions ADD COLUMN grant_duration TEXT");
1906
+ }
1907
+ catch { /* 已有 */ }
1880
1908
  }
1881
1909
  /**
1882
1910
  * RFC-020 PR-C2a — per-request audit of delegation-grant authorizations (RFC-020 §3.7).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seasonkoh/webaz",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
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": {
@@ -88,6 +88,19 @@
88
88
  "test:agent-permission-requests": "tsx scripts/test-agent-permission-requests.ts",
89
89
  "test:agent-permission-consume": "tsx scripts/test-agent-permission-consume.ts",
90
90
  "test:agent-approvals-ui": "tsx scripts/test-agent-approvals-ui.ts",
91
+ "test:mcp-place-order-rail": "tsx scripts/test-mcp-place-order-rail.ts",
92
+ "test:mcp-agent-order-tools": "tsx scripts/test-mcp-agent-order-tools.ts",
93
+ "test:agent-product-draft": "tsx scripts/test-agent-product-draft.ts",
94
+ "test:decline-contest-unify-p1": "tsx scripts/test-decline-contest-unify-pr1.ts",
95
+ "test:decline-contest-unify-p2": "tsx scripts/test-decline-contest-unify-pr2.ts",
96
+ "test:decline-contest-unify-p3": "tsx scripts/test-decline-contest-unify-pr3.ts",
97
+ "test:arb-resolved-history": "tsx scripts/test-arb-resolved-history.ts",
98
+ "test:order-action-request-p1": "tsx scripts/test-order-action-request-pr1.ts",
99
+ "test:order-action-request-p2": "tsx scripts/test-order-action-request-pr2.ts",
100
+ "test:order-action-request-p3": "tsx scripts/test-order-action-request-pr3.ts",
101
+ "backfill:decline-contest": "tsx scripts/backfill-decline-contest-disputes.ts",
102
+ "backfill:direct-pay-ship-deadline": "tsx scripts/backfill-direct-pay-ship-deadline.ts",
103
+ "test:mcp-version-nudge": "tsx scripts/test-mcp-version-nudge.ts",
91
104
  "test:agent-grant-verify": "tsx scripts/test-agent-grant-verify.ts",
92
105
  "test:agent-grant-mcp-consume": "tsx scripts/test-agent-grant-mcp-consume.ts",
93
106
  "test:connected-agents-read": "tsx scripts/test-connected-agents-read.ts",
@@ -105,7 +118,7 @@
105
118
  "test:currency-display": "tsx scripts/test-currency-display.ts",
106
119
  "test:currency-schema-flip": "tsx scripts/test-currency-schema-flip.ts",
107
120
  "test:proposal-admin-ui": "tsx scripts/test-proposal-admin-ui.ts",
108
- "check:pwa-syntax": "node --check src/pwa/public/app-notif-templates.js && node --check src/pwa/public/app-notif-templates-orders.js && node --check src/pwa/public/app.js && node --check src/pwa/public/app-admin.js && node --check src/pwa/public/app-admin-disputes.js && node --check src/pwa/public/app-contribution.js && node --check src/pwa/public/app-ai.js && node --check src/pwa/public/app-discover.js && node --check src/pwa/public/app-profile.js && node --check src/pwa/public/app-account.js && node --check src/pwa/public/app-shop.js && node --check src/pwa/public/app-listings.js && node --check src/pwa/public/app-external-links.js && node --check src/pwa/public/app-product-media.js && node --check src/pwa/public/app-create-kinds.js && node --check src/pwa/public/app-price.js && node --check src/pwa/public/app-order-labels.js && node --check src/pwa/public/app-seller.js && node --check src/pwa/public/app-agents.js && node --check src/pwa/public/app-agent-pair.js && node --check src/pwa/public/app-agent-approvals.js && node --check src/pwa/public/app-agent-appeal.js && node --check src/pwa/public/app-direct-pay.js && node --check src/pwa/public/app-direct-pay-readiness.js && node --check src/pwa/public/app-direct-pay-deferral.js && node --check src/pwa/public/app-direct-pay-deferral-admin.js && node --check src/pwa/public/app-direct-pay-product-verify.js && node --check src/pwa/public/app-direct-pay-store-verify.js && node --check src/pwa/public/app-direct-pay-compliance.js && node --check src/pwa/public/app-direct-pay-fee-ops.js && node --check src/pwa/public/app-direct-pay-fee-center.js && node --check src/pwa/public/app-direct-pay-sales-report.js && node --check src/pwa/public/app-gmv-rail-split.js && node --check src/pwa/public/app-direct-pay-accounts.js && node --check src/pwa/public/app-direct-pay-buyer.js && node --check src/pwa/public/app-direct-pay-pay.js && node --check src/pwa/public/app-direct-pay-reveal.js && node --check src/pwa/public/app-direct-pay-copy.js && node --check src/pwa/public/app-direct-pay-paymodal.js && node --check src/pwa/public/app-direct-pay-memo.js && node --check src/pwa/public/app-direct-pay-negotiation.js && node --check src/pwa/public/app-direct-pay-cancel-refund.js && node --check src/pwa/public/app-direct-pay-returns.js && node --check src/pwa/public/app-order-accept-ui.js && node --check src/pwa/public/app-order-rail-filter.js && node --check src/pwa/public/app-sale-regions-ui.js && node --check src/pwa/public/app-free-shipping-ui.js && node --check src/pwa/public/app-trade-tax-ui.js && node --check src/pwa/public/app-purchase-terms-ui.js && node --check src/pwa/public/app-listing-commerce-ui.js && node --check src/pwa/public/app-bond-terms-ui.js && node --check src/pwa/public/app-bond-ui.js && node --check src/pwa/public/app-bond-refund-ui.js && node --check src/pwa/public/app-bond-slash-ui.js && node --check src/pwa/public/app-bond-deferral-ui.js && node --check src/pwa/public/app-direct-pay-reconcile.js && node --check src/pwa/public/app-mutual-cancel.js && node --check src/pwa/public/app-dispute-close-ui.js && node --check src/pwa/public/app-order-errors.js && node --check src/pwa/public/app-arbitrator-entry.js && node --check src/pwa/public/app-arbitrator-admin.js && node --check src/pwa/public/app-contribution-hub.js && node --check src/pwa/public/app-platform-receive-accounts.js && node --check src/pwa/public/app-direct-pay-fee-request.js && node --check src/pwa/public/app-direct-pay-fee-requests-admin.js && node --check src/pwa/public/app-direct-pay-fee-history.js && node --check src/pwa/public/app-prelaunch-waz.js && node --check src/pwa/public/app-chat-poll.js && node --check src/pwa/public/app-poll-governor.js && node --check src/pwa/public/i18n.js && node --check src/pwa/public/sw.js",
121
+ "check:pwa-syntax": "node --check src/pwa/public/app-notif-templates.js && node --check src/pwa/public/app-notif-templates-orders.js && node --check src/pwa/public/app.js && node --check src/pwa/public/app-admin.js && node --check src/pwa/public/app-admin-disputes.js && node --check src/pwa/public/app-contribution.js && node --check src/pwa/public/app-ai.js && node --check src/pwa/public/app-discover.js && node --check src/pwa/public/app-profile.js && node --check src/pwa/public/app-account.js && node --check src/pwa/public/app-shop.js && node --check src/pwa/public/app-listings.js && node --check src/pwa/public/app-external-links.js && node --check src/pwa/public/app-product-media.js && node --check src/pwa/public/app-create-kinds.js && node --check src/pwa/public/app-price.js && node --check src/pwa/public/app-order-labels.js && node --check src/pwa/public/app-seller.js && node --check src/pwa/public/app-grant-duration.js && node --check src/pwa/public/app-agents.js && node --check src/pwa/public/app-agent-pair.js && node --check src/pwa/public/app-agent-approvals.js && node --check src/pwa/public/app-agent-approvals-order.js && node --check src/pwa/public/app-agent-appeal.js && node --check src/pwa/public/app-direct-pay.js && node --check src/pwa/public/app-direct-pay-readiness.js && node --check src/pwa/public/app-direct-pay-deferral.js && node --check src/pwa/public/app-direct-pay-deferral-admin.js && node --check src/pwa/public/app-direct-pay-product-verify.js && node --check src/pwa/public/app-direct-pay-store-verify.js && node --check src/pwa/public/app-direct-pay-compliance.js && node --check src/pwa/public/app-direct-pay-fee-ops.js && node --check src/pwa/public/app-direct-pay-fee-center.js && node --check src/pwa/public/app-direct-pay-sales-report.js && node --check src/pwa/public/app-gmv-rail-split.js && node --check src/pwa/public/app-direct-pay-accounts.js && node --check src/pwa/public/app-direct-pay-buyer.js && node --check src/pwa/public/app-direct-pay-pay.js && node --check src/pwa/public/app-direct-pay-reveal.js && node --check src/pwa/public/app-direct-pay-copy.js && node --check src/pwa/public/app-direct-pay-paymodal.js && node --check src/pwa/public/app-direct-pay-memo.js && node --check src/pwa/public/app-direct-pay-negotiation.js && node --check src/pwa/public/app-direct-pay-cancel-refund.js && node --check src/pwa/public/app-direct-pay-returns.js && node --check src/pwa/public/app-order-accept-ui.js && node --check src/pwa/public/app-order-rail-filter.js && node --check src/pwa/public/app-sale-regions-ui.js && node --check src/pwa/public/app-free-shipping-ui.js && node --check src/pwa/public/app-trade-tax-ui.js && node --check src/pwa/public/app-purchase-terms-ui.js && node --check src/pwa/public/app-listing-commerce-ui.js && node --check src/pwa/public/app-bond-terms-ui.js && node --check src/pwa/public/app-bond-ui.js && node --check src/pwa/public/app-bond-refund-ui.js && node --check src/pwa/public/app-bond-slash-ui.js && node --check src/pwa/public/app-bond-deferral-ui.js && node --check src/pwa/public/app-direct-pay-reconcile.js && node --check src/pwa/public/app-mutual-cancel.js && node --check src/pwa/public/app-dispute-close-ui.js && node --check src/pwa/public/app-order-errors.js && node --check src/pwa/public/app-arbitrator-entry.js && node --check src/pwa/public/app-arbitrator-admin.js && node --check src/pwa/public/app-decline-contest-ui.js && node --check src/pwa/public/app-decline-contest-ruling.js && node --check src/pwa/public/app-contribution-hub.js && node --check src/pwa/public/app-platform-receive-accounts.js && node --check src/pwa/public/app-direct-pay-fee-request.js && node --check src/pwa/public/app-direct-pay-fee-requests-admin.js && node --check src/pwa/public/app-direct-pay-fee-history.js && node --check src/pwa/public/app-prelaunch-waz.js && node --check src/pwa/public/app-chat-poll.js && node --check src/pwa/public/app-poll-governor.js && node --check src/pwa/public/i18n.js && node --check src/pwa/public/sw.js",
109
122
  "test:create-kinds": "tsx scripts/test-create-kinds.ts",
110
123
  "test:secondhand-photo-authenticity": "tsx scripts/test-secondhand-photo-authenticity.ts",
111
124
  "test:secondhand-detail-alignment": "tsx scripts/test-secondhand-detail-alignment.ts",