@harrylabsj/kiwi 0.7.8 → 0.7.10
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/contracts/commerce-intent/1.0/schema.json +124 -0
- package/contracts/delegation-policy/1.0/schema.json +143 -0
- package/contracts/effective-authorization/1.0/schema.json +167 -0
- package/contracts/kiwi-contracts.lock.json +1 -1
- package/contracts/manifest.json +25 -1
- package/contracts/persistent-task/1.0/schema.json +191 -0
- package/contracts/vectors/commerce-intent.invalid-no-items.json +7 -0
- package/contracts/vectors/commerce-intent.valid.json +32 -0
- package/contracts/vectors/delegation-policy.invalid-payment-auto.json +15 -0
- package/contracts/vectors/delegation-policy.valid.json +25 -0
- package/contracts/vectors/effective-authorization.invalid-deny-wins.json +20 -0
- package/contracts/vectors/effective-authorization.valid.json +23 -0
- package/contracts/vectors/persistent-task.invalid-no-idempotency.json +7 -0
- package/contracts/vectors/persistent-task.valid.json +45 -0
- package/dist/a2a/client/url-policy.js +52 -14
- package/dist/a2a/client/url-policy.js.map +1 -1
- package/dist/a2a/node.js +4 -1
- package/dist/a2a/node.js.map +1 -1
- package/dist/a2a/signing-key.js +18 -0
- package/dist/a2a/signing-key.js.map +1 -1
- package/dist/buyer-core/build-service.d.ts +28 -0
- package/dist/buyer-core/build-service.js +58 -0
- package/dist/buyer-core/build-service.js.map +1 -0
- package/dist/buyer-core/errors.d.ts +31 -0
- package/dist/buyer-core/errors.js +52 -0
- package/dist/buyer-core/errors.js.map +1 -0
- package/dist/buyer-core/merchant-index.d.ts +53 -0
- package/dist/buyer-core/merchant-index.js +138 -0
- package/dist/buyer-core/merchant-index.js.map +1 -0
- package/dist/buyer-core/negotiator.d.ts +51 -0
- package/dist/buyer-core/negotiator.js +181 -0
- package/dist/buyer-core/negotiator.js.map +1 -0
- package/dist/buyer-core/quote-fetcher.d.ts +46 -0
- package/dist/buyer-core/quote-fetcher.js +166 -0
- package/dist/buyer-core/quote-fetcher.js.map +1 -0
- package/dist/buyer-core/service.d.ts +192 -0
- package/dist/buyer-core/service.js +510 -0
- package/dist/buyer-core/service.js.map +1 -0
- package/dist/buyer-core/store.d.ts +84 -0
- package/dist/buyer-core/store.js +256 -0
- package/dist/buyer-core/store.js.map +1 -0
- package/dist/cli.js +25 -0
- package/dist/cli.js.map +1 -1
- package/dist/contracts/northbound-schema.d.ts +27 -0
- package/dist/contracts/northbound-schema.js +102 -0
- package/dist/contracts/northbound-schema.js.map +1 -0
- package/dist/handoff/destination.js +16 -5
- package/dist/handoff/destination.js.map +1 -1
- package/dist/http/cli.d.ts +16 -0
- package/dist/http/cli.js +111 -0
- package/dist/http/cli.js.map +1 -0
- package/dist/http/server.d.ts +39 -0
- package/dist/http/server.js +297 -0
- package/dist/http/server.js.map +1 -0
- package/dist/mcp/cli.d.ts +61 -0
- package/dist/mcp/cli.js +125 -0
- package/dist/mcp/cli.js.map +1 -0
- package/dist/mcp/server.d.ts +41 -0
- package/dist/mcp/server.js +141 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +28 -0
- package/dist/mcp/tools.js +230 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/mcp/types.d.ts +107 -0
- package/dist/mcp/types.js +50 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/merchant/ops.d.ts +80 -0
- package/dist/merchant/ops.js +75 -0
- package/dist/merchant/ops.js.map +1 -0
- package/dist/merchant/ucp-profile.d.ts +39 -0
- package/dist/merchant/ucp-profile.js +55 -0
- package/dist/merchant/ucp-profile.js.map +1 -0
- package/dist/product-cli.d.ts +1 -1
- package/dist/product-cli.js +1 -1
- package/dist/product-cli.js.map +1 -1
- package/dist/trust/identity/auth-verifier.d.ts +2 -0
- package/dist/trust/identity/auth-verifier.js +30 -2
- package/dist/trust/identity/auth-verifier.js.map +1 -1
- package/dist/trust/identity/message-signature.js +14 -8
- package/dist/trust/identity/message-signature.js.map +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 harrylabsj
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* kiwi-buyer-mcp 薄 facade 的 MCP 协议类型(战略 v2.5 §6.1 / §6.2)。
|
|
18
|
+
*
|
|
19
|
+
* 手写 stdio JSON-RPC 2.0 最小 MCP 实现(零新运行时依赖):只实现 initialize
|
|
20
|
+
* 握手、notifications/initialized、tools/list、tools/call 与 JSON-RPC 错误面。
|
|
21
|
+
* 其余 MCP 能力(resources/prompts/sampling/roots)不在 v0.1 范围内——严格
|
|
22
|
+
* fail-closed,遇到未实现方法返回 METHOD_NOT_FOUND。
|
|
23
|
+
*
|
|
24
|
+
* 对外只暴露 5—7 个高层 Sourcing Tools,不暴露 KNP 底层消息、不复制 UCP 的
|
|
25
|
+
* Catalog/Checkout primitives(§6.1)。每个写 tool 绑定 idempotency_key 并返回
|
|
26
|
+
* 稳定 task_id / candidate_id / approval_id / agreement_id(§6.2)。
|
|
27
|
+
*/
|
|
28
|
+
/** MCP 协议版本:本 server 接受并回显的标准版本(v0.1)。Hermes v0.20.1 协商 2025-11-25。 */
|
|
29
|
+
export declare const MCP_PROTOCOL_VERSIONS: readonly ["2024-11-05", "2025-06-18", "2025-11-25"];
|
|
30
|
+
/** MCP 错误码(JSON-RPC 标准 + MCP 扩展)。 */
|
|
31
|
+
export declare const MCP_ERROR: {
|
|
32
|
+
readonly PARSE_ERROR: -32700;
|
|
33
|
+
readonly INVALID_REQUEST: -32600;
|
|
34
|
+
readonly METHOD_NOT_FOUND: -32601;
|
|
35
|
+
readonly INVALID_PARAMS: -32602;
|
|
36
|
+
readonly INTERNAL_ERROR: -32603;
|
|
37
|
+
readonly SERVER_NOT_INITIALIZED: -32002;
|
|
38
|
+
readonly TOOL_NOT_FOUND: -32002;
|
|
39
|
+
};
|
|
40
|
+
export type McpJsonRpcVersion = "2.0";
|
|
41
|
+
export interface JsonRpcRequest {
|
|
42
|
+
jsonrpc: McpJsonRpcVersion;
|
|
43
|
+
id: number | string | null;
|
|
44
|
+
method: string;
|
|
45
|
+
params?: unknown;
|
|
46
|
+
}
|
|
47
|
+
export interface JsonRpcResponse {
|
|
48
|
+
jsonrpc: McpJsonRpcVersion;
|
|
49
|
+
id: number | string | null;
|
|
50
|
+
result?: unknown;
|
|
51
|
+
error?: {
|
|
52
|
+
code: number;
|
|
53
|
+
message: string;
|
|
54
|
+
data?: unknown;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/** MCP initialize 请求参数(§6.1 version negotiation)。 */
|
|
58
|
+
export interface McpInitializeParams {
|
|
59
|
+
protocolVersion: string;
|
|
60
|
+
capabilities?: Record<string, unknown>;
|
|
61
|
+
clientInfo?: {
|
|
62
|
+
name: string;
|
|
63
|
+
version?: string;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export interface McpInitializeResult {
|
|
67
|
+
protocolVersion: string;
|
|
68
|
+
capabilities: {
|
|
69
|
+
tools: {
|
|
70
|
+
listChanged: boolean;
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
serverInfo: {
|
|
74
|
+
name: string;
|
|
75
|
+
version: string;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
export interface McpListToolsResult {
|
|
79
|
+
tools: McpTool[];
|
|
80
|
+
}
|
|
81
|
+
export interface McpTool {
|
|
82
|
+
name: string;
|
|
83
|
+
description: string;
|
|
84
|
+
inputSchema: Record<string, unknown>;
|
|
85
|
+
}
|
|
86
|
+
export interface McpCallToolParams {
|
|
87
|
+
name: string;
|
|
88
|
+
arguments?: Record<string, unknown>;
|
|
89
|
+
}
|
|
90
|
+
export interface McpCallToolResult {
|
|
91
|
+
content: Array<{
|
|
92
|
+
type: "text";
|
|
93
|
+
text: string;
|
|
94
|
+
}>;
|
|
95
|
+
isError?: boolean;
|
|
96
|
+
}
|
|
97
|
+
/** 一个高层 Kiwi Sourcing Tool 的声明(§6.1 词表)。 */
|
|
98
|
+
export interface KiwiToolDefinition {
|
|
99
|
+
name: string;
|
|
100
|
+
description: string;
|
|
101
|
+
/** 输入 JSON Schema(2020-12,自包含)。 */
|
|
102
|
+
inputSchema: Record<string, unknown>;
|
|
103
|
+
handle(args: Record<string, unknown>): Promise<McpCallToolResult>;
|
|
104
|
+
}
|
|
105
|
+
/** 顶层 Kiwi Sourcing Tool 词表(单一来源,§6.1)。 */
|
|
106
|
+
export declare const KIWI_SOURCING_TOOLS: readonly ["kiwi_search", "kiwi_request_quotes", "kiwi_get_task", "kiwi_negotiate", "kiwi_accept_agreement", "kiwi_get_agreement", "kiwi_handoff"];
|
|
107
|
+
export type KiwiSourcingToolName = (typeof KIWI_SOURCING_TOOLS)[number];
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 harrylabsj
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* kiwi-buyer-mcp 薄 facade 的 MCP 协议类型(战略 v2.5 §6.1 / §6.2)。
|
|
18
|
+
*
|
|
19
|
+
* 手写 stdio JSON-RPC 2.0 最小 MCP 实现(零新运行时依赖):只实现 initialize
|
|
20
|
+
* 握手、notifications/initialized、tools/list、tools/call 与 JSON-RPC 错误面。
|
|
21
|
+
* 其余 MCP 能力(resources/prompts/sampling/roots)不在 v0.1 范围内——严格
|
|
22
|
+
* fail-closed,遇到未实现方法返回 METHOD_NOT_FOUND。
|
|
23
|
+
*
|
|
24
|
+
* 对外只暴露 5—7 个高层 Sourcing Tools,不暴露 KNP 底层消息、不复制 UCP 的
|
|
25
|
+
* Catalog/Checkout primitives(§6.1)。每个写 tool 绑定 idempotency_key 并返回
|
|
26
|
+
* 稳定 task_id / candidate_id / approval_id / agreement_id(§6.2)。
|
|
27
|
+
*/
|
|
28
|
+
/** MCP 协议版本:本 server 接受并回显的标准版本(v0.1)。Hermes v0.20.1 协商 2025-11-25。 */
|
|
29
|
+
export const MCP_PROTOCOL_VERSIONS = ["2024-11-05", "2025-06-18", "2025-11-25"];
|
|
30
|
+
/** MCP 错误码(JSON-RPC 标准 + MCP 扩展)。 */
|
|
31
|
+
export const MCP_ERROR = {
|
|
32
|
+
PARSE_ERROR: -32700,
|
|
33
|
+
INVALID_REQUEST: -32600,
|
|
34
|
+
METHOD_NOT_FOUND: -32601,
|
|
35
|
+
INVALID_PARAMS: -32602,
|
|
36
|
+
INTERNAL_ERROR: -32603,
|
|
37
|
+
SERVER_NOT_INITIALIZED: -32002,
|
|
38
|
+
TOOL_NOT_FOUND: -32002,
|
|
39
|
+
};
|
|
40
|
+
/** 顶层 Kiwi Sourcing Tool 词表(单一来源,§6.1)。 */
|
|
41
|
+
export const KIWI_SOURCING_TOOLS = [
|
|
42
|
+
"kiwi_search",
|
|
43
|
+
"kiwi_request_quotes",
|
|
44
|
+
"kiwi_get_task",
|
|
45
|
+
"kiwi_negotiate",
|
|
46
|
+
"kiwi_accept_agreement",
|
|
47
|
+
"kiwi_get_agreement",
|
|
48
|
+
"kiwi_handoff",
|
|
49
|
+
];
|
|
50
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/mcp/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;;;GAWG;AAEH,uEAAuE;AACvE,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,YAAY,EAAE,YAAY,EAAE,YAAY,CAAU,CAAC;AAEzF,qCAAqC;AACrC,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,WAAW,EAAE,CAAC,KAAK;IACnB,eAAe,EAAE,CAAC,KAAK;IACvB,gBAAgB,EAAE,CAAC,KAAK;IACxB,cAAc,EAAE,CAAC,KAAK;IACtB,cAAc,EAAE,CAAC,KAAK;IACtB,sBAAsB,EAAE,CAAC,KAAK;IAC9B,cAAc,EAAE,CAAC,KAAK;CACd,CAAC;AA4DX,2CAA2C;AAC3C,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,aAAa;IACb,qBAAqB;IACrB,eAAe;IACf,gBAAgB;IAChB,uBAAuB;IACvB,oBAAoB;IACpB,cAAc;CACN,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 harrylabsj
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Merchant Ops API(战略 v2.5 §7.6 / §7.7)。
|
|
18
|
+
*
|
|
19
|
+
* Host/Hermes 作为 Operator Console 查看 RFQ 队列、处理 human_required、批准
|
|
20
|
+
* 异常报价、查看 Agreement/Analytics。Merchant Core 仍是状态权威;Ops 只投影
|
|
21
|
+
* 状态与接收审批输入(§7.5 Intelligence & Ops Plane)。
|
|
22
|
+
*
|
|
23
|
+
* 命名空间隔离(§7.7):本服务用 **merchant token** 认证(`kiwi.merchant.*`);
|
|
24
|
+
* 任何 Buyer token 不得访问 Merchant Ops,任何 Merchant Ops token 不得获得
|
|
25
|
+
* Buyer Principal Memory。与 `kiwi.buyer.*`(Buyer Kit)完全分离。
|
|
26
|
+
*/
|
|
27
|
+
export interface MerchantOpsServiceOptions {
|
|
28
|
+
baseUrl: string;
|
|
29
|
+
/** 商家 API token(merchant 作用域,非 buyer token)。 */
|
|
30
|
+
merchantToken: string;
|
|
31
|
+
timeoutMs?: number;
|
|
32
|
+
fetchImpl?: typeof fetch;
|
|
33
|
+
}
|
|
34
|
+
export interface RfqConversation {
|
|
35
|
+
id: string;
|
|
36
|
+
buyer_id: string;
|
|
37
|
+
sku: string;
|
|
38
|
+
status: string;
|
|
39
|
+
next_actor: string;
|
|
40
|
+
created_at: string;
|
|
41
|
+
updated_at: string;
|
|
42
|
+
last_sender: string;
|
|
43
|
+
message_count?: number;
|
|
44
|
+
}
|
|
45
|
+
export interface HumanReviewConversation {
|
|
46
|
+
id: string;
|
|
47
|
+
buyer_id: string;
|
|
48
|
+
status: string;
|
|
49
|
+
reason?: string;
|
|
50
|
+
created_at?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface MerchantAnalytics {
|
|
53
|
+
merchant_id: string;
|
|
54
|
+
total_rfqs: number;
|
|
55
|
+
pending_rfqs: number;
|
|
56
|
+
completed_rfqs: number;
|
|
57
|
+
human_review_count: number;
|
|
58
|
+
}
|
|
59
|
+
export declare class MerchantOpsService {
|
|
60
|
+
private readonly baseUrl;
|
|
61
|
+
private readonly merchantToken;
|
|
62
|
+
private readonly timeoutMs;
|
|
63
|
+
private readonly fetchImpl;
|
|
64
|
+
constructor(options: MerchantOpsServiceOptions);
|
|
65
|
+
/** RFQ 队列:商家名下活跃会话(§7.6 查看 RFQ)。 */
|
|
66
|
+
listRfqQueue(merchantId: string): Promise<{
|
|
67
|
+
rfqs: RfqConversation[];
|
|
68
|
+
}>;
|
|
69
|
+
/** human_required 会话(§7.6 处理人工审核)。 */
|
|
70
|
+
listHumanReview(merchantId: string): Promise<{
|
|
71
|
+
conversations: HumanReviewConversation[];
|
|
72
|
+
}>;
|
|
73
|
+
/** 处理 human_required:resolve 会话(商家运营决定)。 */
|
|
74
|
+
resolveReview(merchantId: string, conversationId: string, decision: string): Promise<{
|
|
75
|
+
ok: boolean;
|
|
76
|
+
}>;
|
|
77
|
+
/** Analytics:RFQ 量、待办/完成、人工审核数(§7.6)。 */
|
|
78
|
+
analytics(merchantId: string): Promise<MerchantAnalytics>;
|
|
79
|
+
private getJson;
|
|
80
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 harrylabsj
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
export class MerchantOpsService {
|
|
17
|
+
baseUrl;
|
|
18
|
+
merchantToken;
|
|
19
|
+
timeoutMs;
|
|
20
|
+
fetchImpl;
|
|
21
|
+
constructor(options) {
|
|
22
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
23
|
+
this.merchantToken = options.merchantToken;
|
|
24
|
+
this.timeoutMs = options.timeoutMs ?? 5000;
|
|
25
|
+
this.fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
26
|
+
}
|
|
27
|
+
/** RFQ 队列:商家名下活跃会话(§7.6 查看 RFQ)。 */
|
|
28
|
+
async listRfqQueue(merchantId) {
|
|
29
|
+
const data = await this.getJson(`/merchants/${encodeURIComponent(merchantId)}/conversations`);
|
|
30
|
+
const rfqs = Array.isArray(data)
|
|
31
|
+
? data
|
|
32
|
+
: ((data.conversations ?? data.results) ?? []);
|
|
33
|
+
return { rfqs };
|
|
34
|
+
}
|
|
35
|
+
/** human_required 会话(§7.6 处理人工审核)。 */
|
|
36
|
+
async listHumanReview(merchantId) {
|
|
37
|
+
const data = await this.getJson(`/merchants/${encodeURIComponent(merchantId)}/human-review`);
|
|
38
|
+
return { conversations: data.conversations ?? [] };
|
|
39
|
+
}
|
|
40
|
+
/** 处理 human_required:resolve 会话(商家运营决定)。 */
|
|
41
|
+
async resolveReview(merchantId, conversationId, decision) {
|
|
42
|
+
const res = await this.fetchImpl(`${this.baseUrl}/conversations/${encodeURIComponent(conversationId)}/human-review/resolve`, {
|
|
43
|
+
method: "POST",
|
|
44
|
+
headers: { authorization: `Bearer ${this.merchantToken}`, "content-type": "application/json" },
|
|
45
|
+
body: JSON.stringify({ decision, merchant_id: merchantId }),
|
|
46
|
+
signal: AbortSignal.timeout(this.timeoutMs),
|
|
47
|
+
});
|
|
48
|
+
if (!res.ok)
|
|
49
|
+
throw new Error(`resolve review ${res.status}`);
|
|
50
|
+
const data = (await res.json());
|
|
51
|
+
return { ok: data.ok === true };
|
|
52
|
+
}
|
|
53
|
+
/** Analytics:RFQ 量、待办/完成、人工审核数(§7.6)。 */
|
|
54
|
+
async analytics(merchantId) {
|
|
55
|
+
const { rfqs } = await this.listRfqQueue(merchantId);
|
|
56
|
+
const { conversations } = await this.listHumanReview(merchantId);
|
|
57
|
+
return {
|
|
58
|
+
merchant_id: merchantId,
|
|
59
|
+
total_rfqs: rfqs.length,
|
|
60
|
+
pending_rfqs: rfqs.filter((r) => r.status === "waiting_merchant").length,
|
|
61
|
+
completed_rfqs: rfqs.filter((r) => r.status === "closed").length,
|
|
62
|
+
human_review_count: conversations.length,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
async getJson(path) {
|
|
66
|
+
const res = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
67
|
+
headers: { authorization: `Bearer ${this.merchantToken}`, accept: "application/json" },
|
|
68
|
+
signal: AbortSignal.timeout(this.timeoutMs),
|
|
69
|
+
});
|
|
70
|
+
if (!res.ok)
|
|
71
|
+
throw new Error(`merchant ops ${path} ${res.status}`);
|
|
72
|
+
return (await res.json());
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=ops.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ops.js","sourceRoot":"","sources":["../../src/merchant/ops.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 harrylabsj
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Merchant UCP Profile 生成(战略 v2.5 §7.1 Protocol Publishing / §7.8 UCP-ready)。
|
|
18
|
+
*
|
|
19
|
+
* 商家在 `/.well-known/ucp` 发布 UCP Profile:声明 Catalog service(指向真实
|
|
20
|
+
* 商品 endpoint)与 KNP 磋商 capability。Kiwi 的 Buyer 端(UcpProfileResolver)
|
|
21
|
+
* 通过该 profile 发现商家能力;商品 truth 仍在 merchant/marketplace,不落 Kiwi。
|
|
22
|
+
*
|
|
23
|
+
* UCP 命名不变量(基线 §8.3):service 名 = {reverse-domain}.{service},
|
|
24
|
+
* reverse-domain 反转即 namespace authority host;spec/schema URL origin MUST
|
|
25
|
+
* 与 namespace authority 一致。
|
|
26
|
+
*/
|
|
27
|
+
import type { UcpProfile } from "../discovery/ucp/types.js";
|
|
28
|
+
export declare const UCP_VERSION = "2026-04-08";
|
|
29
|
+
export interface MerchantUcpProfileOptions {
|
|
30
|
+
/** 商家规范域名(如 xihu-digital.example.com)——决定 namespace authority。 */
|
|
31
|
+
domain: string;
|
|
32
|
+
/** 商家 id(marketplace 商家 id,如 merchant-hz-xihu)。 */
|
|
33
|
+
merchantId: string;
|
|
34
|
+
/** 真实商品 catalog endpoint(marketplace search,如 http://127.0.0.1:8765/search/products)。 */
|
|
35
|
+
catalogEndpoint: string;
|
|
36
|
+
}
|
|
37
|
+
/** 由域名派生 reverse-domain(UCP §8.3:反转 authority host 的 label)。 */
|
|
38
|
+
export declare function reverseDomain(domain: string): string;
|
|
39
|
+
export declare function buildMerchantUcpProfile(options: MerchantUcpProfileOptions): UcpProfile;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 harrylabsj
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
export const UCP_VERSION = "2026-04-08";
|
|
17
|
+
/** 由域名派生 reverse-domain(UCP §8.3:反转 authority host 的 label)。 */
|
|
18
|
+
export function reverseDomain(domain) {
|
|
19
|
+
return domain.split(".").reverse().join(".");
|
|
20
|
+
}
|
|
21
|
+
export function buildMerchantUcpProfile(options) {
|
|
22
|
+
const authority = options.domain;
|
|
23
|
+
const rd = reverseDomain(options.domain);
|
|
24
|
+
const catalogService = `${rd}.catalog`;
|
|
25
|
+
const negotiationCapability = "com.harrylabsj.kiwi.shopping.negotiation";
|
|
26
|
+
return {
|
|
27
|
+
ucp: {
|
|
28
|
+
version: UCP_VERSION,
|
|
29
|
+
services: {
|
|
30
|
+
[catalogService]: [
|
|
31
|
+
{
|
|
32
|
+
version: UCP_VERSION,
|
|
33
|
+
spec: `https://${authority}/.well-known/ucp#catalog`,
|
|
34
|
+
transport: "rest",
|
|
35
|
+
endpoint: options.catalogEndpoint,
|
|
36
|
+
schema: `https://${authority}/schemas/catalog.json`,
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
capabilities: {
|
|
41
|
+
[negotiationCapability]: [
|
|
42
|
+
{
|
|
43
|
+
version: "1.0",
|
|
44
|
+
spec: "https://kiwi.harrylabsj.com/spec/negotiation/1.0",
|
|
45
|
+
schema: "https://kiwi.harrylabsj.com/schemas/negotiation/1.0/schema.json",
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
signing_keys: [],
|
|
51
|
+
// 商家元信息(非 UCP 标准字段,forward-compat)。
|
|
52
|
+
merchant_id: options.merchantId,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=ucp-profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ucp-profile.js","sourceRoot":"","sources":["../../src/merchant/ucp-profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAgBH,MAAM,CAAC,MAAM,WAAW,GAAG,YAAY,CAAC;AAWxC,gEAAgE;AAChE,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAkC;IACxE,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;IACjC,MAAM,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,cAAc,GAAG,GAAG,EAAE,UAAU,CAAC;IACvC,MAAM,qBAAqB,GAAG,0CAA0C,CAAC;IAEzE,OAAO;QACL,GAAG,EAAE;YACH,OAAO,EAAE,WAAW;YACpB,QAAQ,EAAE;gBACR,CAAC,cAAc,CAAC,EAAE;oBAChB;wBACE,OAAO,EAAE,WAAW;wBACpB,IAAI,EAAE,WAAW,SAAS,0BAA0B;wBACpD,SAAS,EAAE,MAAM;wBACjB,QAAQ,EAAE,OAAO,CAAC,eAAe;wBACjC,MAAM,EAAE,WAAW,SAAS,uBAAuB;qBACpD;iBACF;aACF;YACD,YAAY,EAAE;gBACZ,CAAC,qBAAqB,CAAC,EAAE;oBACvB;wBACE,OAAO,EAAE,KAAK;wBACd,IAAI,EAAE,kDAAkD;wBACxD,MAAM,EAAE,iEAAiE;qBAC1E;iBACF;aACF;SACF;QACD,YAAY,EAAE,EAAE;QAChB,oCAAoC;QACpC,WAAW,EAAE,OAAO,CAAC,UAAU;KAChC,CAAC;AACJ,CAAC"}
|
package/dist/product-cli.d.ts
CHANGED
|
@@ -42,7 +42,7 @@ export declare const DEFAULT_PROFILE_PATH: string;
|
|
|
42
42
|
*/
|
|
43
43
|
export declare function writeDefaultProfile(yaml: string, profilePath?: string): void;
|
|
44
44
|
/** 与 package.json / USAGE 同步的产品版本。 */
|
|
45
|
-
export declare const PRODUCT_VERSION = "0.7.
|
|
45
|
+
export declare const PRODUCT_VERSION = "0.7.10";
|
|
46
46
|
/**
|
|
47
47
|
* 缺省 kiwi-catalog 地址(单一来源,cli.ts 各处解析一致)。
|
|
48
48
|
*
|
package/dist/product-cli.js
CHANGED
|
@@ -51,7 +51,7 @@ export function writeDefaultProfile(yaml, profilePath) {
|
|
|
51
51
|
writeFileSync(target, yaml, { mode: 0o600 });
|
|
52
52
|
}
|
|
53
53
|
/** 与 package.json / USAGE 同步的产品版本。 */
|
|
54
|
-
export const PRODUCT_VERSION = "0.7.
|
|
54
|
+
export const PRODUCT_VERSION = "0.7.10";
|
|
55
55
|
/**
|
|
56
56
|
* 缺省 kiwi-catalog 地址(单一来源,cli.ts 各处解析一致)。
|
|
57
57
|
*
|
package/dist/product-cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-cli.js","sourceRoot":"","sources":["../src/product-cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE3F;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;AAE/E;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,WAAoB;IACpE,MAAM,MAAM,GAAG,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,oBAAoB,CAAC;IACvF,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAClE,aAAa,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED,sCAAsC;AACtC,MAAM,CAAC,MAAM,eAAe,GAAG,
|
|
1
|
+
{"version":3,"file":"product-cli.js","sourceRoot":"","sources":["../src/product-cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -99,6 +99,8 @@ export declare class HttpMessageSignatureVerifier implements AuthVerifier {
|
|
|
99
99
|
private readonly maxClockSkewSeconds;
|
|
100
100
|
private readonly maxSignatureAgeSeconds;
|
|
101
101
|
private readonly expectedAuthority;
|
|
102
|
+
/** scheme 是否显式配置(公网 https 节点经反代终结 TLS 时必须显式 https)。 */
|
|
103
|
+
private readonly schemeExplicit;
|
|
102
104
|
constructor(options: HttpMessageSignatureVerifierOptions);
|
|
103
105
|
verify(ctx: AuthContext): AuthResult;
|
|
104
106
|
}
|
|
@@ -48,6 +48,20 @@ export function parseClaimedIdentityHeader(headers) {
|
|
|
48
48
|
out.role = obj.role;
|
|
49
49
|
return out;
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* authority(host[:port])→ hostname 归一(审查 K-M19)。Host 头可能带端口
|
|
53
|
+
* (veyquo.com:8443)或 IPv6 括号形式([::1]:8080);expectedAuthority 常为
|
|
54
|
+
* 无端口的 hostname。跨主机重放判定只看 hostname,端口差异不构成重放。
|
|
55
|
+
*/
|
|
56
|
+
function authorityHostname(authority) {
|
|
57
|
+
const trimmed = authority.trim();
|
|
58
|
+
if (trimmed.startsWith("[")) {
|
|
59
|
+
const end = trimmed.indexOf("]");
|
|
60
|
+
return end === -1 ? trimmed.toLowerCase() : trimmed.slice(0, end + 1).toLowerCase();
|
|
61
|
+
}
|
|
62
|
+
const host = trimmed.split(":")[0] ?? "";
|
|
63
|
+
return host.toLowerCase();
|
|
64
|
+
}
|
|
51
65
|
/** 完整 HTTP Message Signature 入站验证器(AuthVerifier 实现)。 */
|
|
52
66
|
export class HttpMessageSignatureVerifier {
|
|
53
67
|
name = "http-message-signature";
|
|
@@ -62,12 +76,15 @@ export class HttpMessageSignatureVerifier {
|
|
|
62
76
|
maxClockSkewSeconds;
|
|
63
77
|
maxSignatureAgeSeconds;
|
|
64
78
|
expectedAuthority;
|
|
79
|
+
/** scheme 是否显式配置(公网 https 节点经反代终结 TLS 时必须显式 https)。 */
|
|
80
|
+
schemeExplicit;
|
|
65
81
|
constructor(options) {
|
|
66
82
|
this.resolver = options.resolver;
|
|
67
83
|
this.policy = options.policy ?? DEFAULT_TRUST_POLICY;
|
|
68
84
|
this.nonceStore = options.nonceStore;
|
|
69
85
|
this.now = options.now ?? (() => Math.floor(Date.now() / 1000));
|
|
70
86
|
this.scheme = options.scheme ?? "http";
|
|
87
|
+
this.schemeExplicit = options.scheme !== undefined;
|
|
71
88
|
this.anonymousTrustLevel = options.anonymousTrustLevel ?? "T0";
|
|
72
89
|
this.anonymousIdentity = options.anonymousIdentity ?? "anonymous";
|
|
73
90
|
this.verifyCardJws = options.verifyCardJws;
|
|
@@ -90,7 +107,14 @@ export class HttpMessageSignatureVerifier {
|
|
|
90
107
|
}
|
|
91
108
|
// 签名请求:重建 @target-uri / @authority(服务端只有 origin-form req.url)。
|
|
92
109
|
const authority = headerValue(headers, "host") ?? "";
|
|
93
|
-
|
|
110
|
+
// scheme 优先级:节点**显式**配置了 scheme + expectedAuthority(声明固定公网
|
|
111
|
+
// 身份,如 https://veyquo.com,反代终结 TLS、本地 socket 是 http)时,
|
|
112
|
+
// @target-uri 必须用节点声明的 scheme——否则签名者按 https 签、节点按本地 http
|
|
113
|
+
// 重建,验签必败。scheme 未显式配置(默认 http)时维持 ctx.scheme 优先(兼容
|
|
114
|
+
// 未配置身份的既有调用方)。
|
|
115
|
+
const scheme = this.schemeExplicit && this.expectedAuthority !== undefined
|
|
116
|
+
? this.scheme
|
|
117
|
+
: (ctx.scheme ?? this.scheme);
|
|
94
118
|
const targetUri = ctx.url.startsWith("http://") || ctx.url.startsWith("https://")
|
|
95
119
|
? ctx.url
|
|
96
120
|
: `${scheme}://${authority}${ctx.url}`;
|
|
@@ -98,8 +122,12 @@ export class HttpMessageSignatureVerifier {
|
|
|
98
122
|
// 并在此通过验签(签名绑定的是「签名者声明的目标」而非「实际连接目标」)。
|
|
99
123
|
// 配置 expectedAuthority(自身广告主机 / SNI / TLS 证书 host)时强制绑定:
|
|
100
124
|
// 声明的 authority 必须等于它,跨主机重放直接拒绝。
|
|
125
|
+
// 审查 K-M19:authority 可能带端口(Host: veyquo.com:8443),而
|
|
126
|
+
// expectedAuthority 是 hostname(advertised.hostname 无端口)——字符串全等
|
|
127
|
+
// 会把非默认端口的合法签名全拒(匿名却照常放行,签名认证形同虚设)。
|
|
128
|
+
// hostname 归一比较:端口差异不构成跨主机重放,hostname 不同仍拒绝。
|
|
101
129
|
if (this.expectedAuthority !== undefined &&
|
|
102
|
-
authority
|
|
130
|
+
authorityHostname(authority) !== authorityHostname(this.expectedAuthority)) {
|
|
103
131
|
return {
|
|
104
132
|
authenticated: false,
|
|
105
133
|
protocolCode: "authorization_failed",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-verifier.js","sourceRoot":"","sources":["../../../src/trust/identity/auth-verifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAyBH,OAAO,EAAE,YAAY,EAAgD,MAAM,uBAAuB,CAAC;AAEnG,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAEpE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EACL,oBAAoB,GAGrB,MAAM,mBAAmB,CAAC;AAE3B,iCAAiC;AACjC,MAAM,CAAC,MAAM,eAAe,GAAG,kBAAkB,CAAC;AAClD,yCAAyC;AACzC,MAAM,CAAC,MAAM,uBAAuB,GAAG,yBAAyB,CAAC;AAmCjE;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CACxC,OAAsD;IAEtD,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,EAAE,uBAAuB,CAAC,CAAC;IAC5D,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAC7F,MAAM,GAAG,GAAG,MAAiC,CAAC;IAC9C,MAAM,GAAG,GAAoB,EAAE,CAAC;IAChC,IAAI,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ;QAAE,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;IAClE,IAAI,OAAO,GAAG,CAAC,YAAY,KAAK,QAAQ;QAAE,GAAG,CAAC,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC;IAC9E,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU;QAAE,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;IACzE,OAAO,GAAG,CAAC;AACb,CAAC;AAED,wDAAwD;AACxD,MAAM,OAAO,4BAA4B;IAC9B,IAAI,GAAG,wBAAwB,CAAC;IACxB,QAAQ,CAAc;IACtB,MAAM,CAAc;IACpB,UAAU,CAAyB;IACnC,GAAG,CAAe;IAClB,MAAM,CAAmB;IACzB,mBAAmB,CAAa;IAChC,iBAAiB,CAAS;IAC1B,aAAa,CAA2D;IACxE,mBAAmB,CAAS;IAC5B,sBAAsB,CAAS;IAC/B,iBAAiB,CAAqB;
|
|
1
|
+
{"version":3,"file":"auth-verifier.js","sourceRoot":"","sources":["../../../src/trust/identity/auth-verifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -225,14 +225,20 @@ function verifyEntry(entry, signatureBytes, input, now, skew, maxAge) {
|
|
|
225
225
|
};
|
|
226
226
|
}
|
|
227
227
|
const algorithm = requested ?? key.algorithm;
|
|
228
|
-
// created/expires 窗口(RFC 9421 §
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
}
|
|
228
|
+
// created/expires 窗口(RFC 9421 §2.2:created 必选——缺失即无任何防重放
|
|
229
|
+
// 时间边界,捕获签名可无限期重放。审查 K-M17:fail-closed,不再跳过时间检查)。
|
|
230
|
+
if (entry.params.created === undefined) {
|
|
231
|
+
return {
|
|
232
|
+
ok: false,
|
|
233
|
+
code: "authorization_failed",
|
|
234
|
+
reason: "signature has no created parameter (RFC 9421 requires it)",
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
if (entry.params.created > now + skew) {
|
|
238
|
+
return { ok: false, code: "authorization_failed", reason: "signature created in the future" };
|
|
239
|
+
}
|
|
240
|
+
if (entry.params.expires === undefined && now - entry.params.created > maxAge) {
|
|
241
|
+
return { ok: false, code: "authorization_failed", reason: "signature is too old" };
|
|
236
242
|
}
|
|
237
243
|
if (entry.params.expires !== undefined && entry.params.expires < now - skew) {
|
|
238
244
|
return { ok: false, code: "authorization_failed", reason: "signature has expired" };
|