@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.
- package/README.md +3 -1
- package/dist/layer0-foundation/L0-2-state-machine/engine.js +1 -1
- package/dist/layer1-agent/L1-1-mcp-server/network-mode.js +4 -0
- package/dist/layer1-agent/L1-1-mcp-server/server.js +202 -19
- package/dist/layer2-business/L2-6-notifications/notification-engine.js +96 -0
- package/dist/layer3-trust/L3-1-dispute-engine/decline-contest-resolve.js +110 -0
- package/dist/layer3-trust/L3-1-dispute-engine/dispute-engine.js +109 -0
- package/dist/pwa/agent-order-minimal-view.js +29 -0
- package/dist/pwa/order-action-exec.js +158 -0
- package/dist/pwa/order-action-request.js +57 -0
- package/dist/pwa/public/app-admin-disputes.js +1 -1
- package/dist/pwa/public/app-agent-approvals-order.js +18 -0
- package/dist/pwa/public/app-agent-approvals.js +6 -7
- package/dist/pwa/public/app-agent-pair.js +2 -2
- package/dist/pwa/public/app-arbitrator-admin.js +1 -1
- package/dist/pwa/public/app-decline-contest-ruling.js +53 -0
- package/dist/pwa/public/app-decline-contest-ui.js +44 -0
- package/dist/pwa/public/app-grant-duration.js +20 -0
- package/dist/pwa/public/app.js +9 -9
- package/dist/pwa/public/i18n.js +24 -1
- package/dist/pwa/public/index.html +4 -0
- package/dist/pwa/public/openapi.json +78 -23
- package/dist/pwa/routes/admin-reports.js +40 -3
- package/dist/pwa/routes/agent-grants.js +147 -14
- package/dist/pwa/routes/disputes-read.js +17 -1
- package/dist/pwa/routes/disputes-write.js +42 -73
- package/dist/pwa/routes/orders-action.js +46 -3
- package/dist/pwa/routes/products-create.js +33 -13
- package/dist/pwa/routes/webauthn.js +1 -1
- package/dist/pwa/server.js +7 -7
- package/dist/runtime/agent-grant-scopes.js +26 -8
- package/dist/runtime/webaz-schema-helpers.js +28 -0
- 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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
}
|
package/dist/pwa/server.js
CHANGED
|
@@ -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
|
|
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 → []
|
|
163
|
-
* - risk (high) → [
|
|
164
|
-
* - safe (low/medium) →
|
|
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 [
|
|
172
|
-
return ['
|
|
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
|
|
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] ?? '
|
|
197
|
+
return a.includes('7d') ? '7d' : (a[0] ?? '7d');
|
|
181
198
|
}
|
|
182
|
-
/** Grant lifetime in seconds
|
|
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.
|
|
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",
|