sealbridge 0.0.1 → 0.2.0
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/NOTICE +43 -0
- package/README.ja.md +397 -0
- package/README.md +567 -1
- package/dist/cli/dist/acp.d.ts +2 -0
- package/dist/cli/dist/acp.js +6 -0
- package/dist/cli/dist/acp.js.map +1 -0
- package/dist/cli/dist/approval-summary.d.ts +2 -0
- package/dist/cli/dist/approval-summary.js +32 -0
- package/dist/cli/dist/approval-summary.js.map +1 -0
- package/dist/cli/dist/board.d.ts +47 -0
- package/dist/cli/dist/board.js +255 -0
- package/dist/cli/dist/board.js.map +1 -0
- package/dist/cli/dist/contacts.d.ts +18 -0
- package/dist/cli/dist/contacts.js +154 -0
- package/dist/cli/dist/contacts.js.map +1 -0
- package/dist/cli/dist/doctor.d.ts +13 -0
- package/dist/cli/dist/doctor.js +30 -0
- package/dist/cli/dist/doctor.js.map +1 -0
- package/dist/cli/dist/error-messages.d.ts +2 -0
- package/dist/cli/dist/error-messages.js +24 -0
- package/dist/cli/dist/error-messages.js.map +1 -0
- package/dist/cli/dist/index.d.ts +2 -0
- package/dist/cli/dist/index.js +194 -0
- package/dist/cli/dist/index.js.map +1 -0
- package/dist/cli/dist/invite-share.d.ts +16 -0
- package/dist/cli/dist/invite-share.js +163 -0
- package/dist/cli/dist/invite-share.js.map +1 -0
- package/dist/cli/dist/mcp.d.ts +17 -0
- package/dist/cli/dist/mcp.js +105 -0
- package/dist/cli/dist/mcp.js.map +1 -0
- package/dist/cli/dist/network.d.ts +1 -0
- package/dist/cli/dist/network.js +396 -0
- package/dist/cli/dist/network.js.map +1 -0
- package/dist/cli/dist/public-settings.d.ts +27 -0
- package/dist/cli/dist/public-settings.js +33 -0
- package/dist/cli/dist/public-settings.js.map +1 -0
- package/dist/cli/dist/receipt.d.ts +39 -0
- package/dist/cli/dist/receipt.js +90 -0
- package/dist/cli/dist/receipt.js.map +1 -0
- package/dist/cli/dist/receive-hook.d.ts +2 -0
- package/dist/cli/dist/receive-hook.js +35 -0
- package/dist/cli/dist/receive-hook.js.map +1 -0
- package/dist/cli/dist/task-input.d.ts +2 -0
- package/dist/cli/dist/task-input.js +19 -0
- package/dist/cli/dist/task-input.js.map +1 -0
- package/dist/cli/dist/wake-hook.d.ts +3 -0
- package/dist/cli/dist/wake-hook.js +32 -0
- package/dist/cli/dist/wake-hook.js.map +1 -0
- package/dist/examples/two-owner-demo/alice-policy.json +4 -0
- package/dist/examples/two-owner-demo/bob-policy.json +4 -0
- package/dist/examples/two-owner-demo/dist/run-demo.d.ts +71 -0
- package/dist/examples/two-owner-demo/dist/run-demo.js +383 -0
- package/dist/examples/two-owner-demo/dist/run-demo.js.map +1 -0
- package/dist/package.json +1 -0
- package/dist/packages/adapters/dist/command.d.ts +122 -0
- package/dist/packages/adapters/dist/command.js +378 -0
- package/dist/packages/adapters/dist/command.js.map +1 -0
- package/dist/packages/adapters/dist/credential-proxy.d.ts +37 -0
- package/dist/packages/adapters/dist/credential-proxy.js +363 -0
- package/dist/packages/adapters/dist/credential-proxy.js.map +1 -0
- package/dist/packages/adapters/dist/index.d.ts +6 -0
- package/dist/packages/adapters/dist/index.js +6 -0
- package/dist/packages/adapters/dist/index.js.map +1 -0
- package/dist/packages/adapters/dist/mcp.d.ts +32 -0
- package/dist/packages/adapters/dist/mcp.js +87 -0
- package/dist/packages/adapters/dist/mcp.js.map +1 -0
- package/dist/packages/adapters/dist/openai.d.ts +23 -0
- package/dist/packages/adapters/dist/openai.js +81 -0
- package/dist/packages/adapters/dist/openai.js.map +1 -0
- package/dist/packages/adapters/dist/sandbox.d.ts +45 -0
- package/dist/packages/adapters/dist/sandbox.js +60 -0
- package/dist/packages/adapters/dist/sandbox.js.map +1 -0
- package/dist/packages/core/dist/capability.d.ts +36 -0
- package/dist/packages/core/dist/capability.js +203 -0
- package/dist/packages/core/dist/capability.js.map +1 -0
- package/dist/packages/core/dist/contract.d.ts +33 -0
- package/dist/packages/core/dist/contract.js +97 -0
- package/dist/packages/core/dist/contract.js.map +1 -0
- package/dist/packages/core/dist/crypto.d.ts +34 -0
- package/dist/packages/core/dist/crypto.js +329 -0
- package/dist/packages/core/dist/crypto.js.map +1 -0
- package/dist/packages/core/dist/discovery.d.ts +129 -0
- package/dist/packages/core/dist/discovery.js +527 -0
- package/dist/packages/core/dist/discovery.js.map +1 -0
- package/dist/packages/core/dist/edge.d.ts +4 -0
- package/dist/packages/core/dist/edge.js +6 -0
- package/dist/packages/core/dist/edge.js.map +1 -0
- package/dist/packages/core/dist/index.d.ts +9 -0
- package/dist/packages/core/dist/index.js +10 -0
- package/dist/packages/core/dist/index.js.map +1 -0
- package/dist/packages/core/dist/receipts.d.ts +9 -0
- package/dist/packages/core/dist/receipts.js +67 -0
- package/dist/packages/core/dist/receipts.js.map +1 -0
- package/dist/packages/core/dist/relay-auth.d.ts +40 -0
- package/dist/packages/core/dist/relay-auth.js +106 -0
- package/dist/packages/core/dist/relay-auth.js.map +1 -0
- package/dist/packages/core/dist/revocation.d.ts +58 -0
- package/dist/packages/core/dist/revocation.js +112 -0
- package/dist/packages/core/dist/revocation.js.map +1 -0
- package/dist/packages/core/dist/schema.d.ts +11 -0
- package/dist/packages/core/dist/schema.js +48 -0
- package/dist/packages/core/dist/schema.js.map +1 -0
- package/dist/packages/core/dist/types.d.ts +172 -0
- package/dist/packages/core/dist/types.js +2 -0
- package/dist/packages/core/dist/types.js.map +1 -0
- package/dist/packages/ledger/dist/index.d.ts +84 -0
- package/dist/packages/ledger/dist/index.js +269 -0
- package/dist/packages/ledger/dist/index.js.map +1 -0
- package/dist/packages/relay/dist/fetch.d.ts +250 -0
- package/dist/packages/relay/dist/fetch.js +1401 -0
- package/dist/packages/relay/dist/fetch.js.map +1 -0
- package/dist/packages/relay/dist/index.d.ts +103 -0
- package/dist/packages/relay/dist/index.js +855 -0
- package/dist/packages/relay/dist/index.js.map +1 -0
- package/dist/packages/relay/dist/journal.d.ts +77 -0
- package/dist/packages/relay/dist/journal.js +339 -0
- package/dist/packages/relay/dist/journal.js.map +1 -0
- package/dist/packages/relay/dist/notifications.d.ts +63 -0
- package/dist/packages/relay/dist/notifications.js +55 -0
- package/dist/packages/relay/dist/notifications.js.map +1 -0
- package/dist/packages/relay/dist/retry.d.ts +12 -0
- package/dist/packages/relay/dist/retry.js +59 -0
- package/dist/packages/relay/dist/retry.js.map +1 -0
- package/dist/packages/relay/dist/ssrf.d.ts +32 -0
- package/dist/packages/relay/dist/ssrf.js +213 -0
- package/dist/packages/relay/dist/ssrf.js.map +1 -0
- package/dist/packages/relay/dist/worker.d.ts +92 -0
- package/dist/packages/relay/dist/worker.js +460 -0
- package/dist/packages/relay/dist/worker.js.map +1 -0
- package/dist/packages/runtime/dist/a2a.d.ts +8 -0
- package/dist/packages/runtime/dist/a2a.js +69 -0
- package/dist/packages/runtime/dist/a2a.js.map +1 -0
- package/dist/packages/runtime/dist/adapter.d.ts +51 -0
- package/dist/packages/runtime/dist/adapter.js +2 -0
- package/dist/packages/runtime/dist/adapter.js.map +1 -0
- package/dist/packages/runtime/dist/approval-providers.d.ts +99 -0
- package/dist/packages/runtime/dist/approval-providers.js +269 -0
- package/dist/packages/runtime/dist/approval-providers.js.map +1 -0
- package/dist/packages/runtime/dist/daily-limit.d.ts +2 -0
- package/dist/packages/runtime/dist/daily-limit.js +54 -0
- package/dist/packages/runtime/dist/daily-limit.js.map +1 -0
- package/dist/packages/runtime/dist/gateway.d.ts +35 -0
- package/dist/packages/runtime/dist/gateway.js +92 -0
- package/dist/packages/runtime/dist/gateway.js.map +1 -0
- package/dist/packages/runtime/dist/inbox.d.ts +10 -0
- package/dist/packages/runtime/dist/inbox.js +24 -0
- package/dist/packages/runtime/dist/inbox.js.map +1 -0
- package/dist/packages/runtime/dist/index.d.ts +13 -0
- package/dist/packages/runtime/dist/index.js +14 -0
- package/dist/packages/runtime/dist/index.js.map +1 -0
- package/dist/packages/runtime/dist/mcp-server.d.ts +90 -0
- package/dist/packages/runtime/dist/mcp-server.js +647 -0
- package/dist/packages/runtime/dist/mcp-server.js.map +1 -0
- package/dist/packages/runtime/dist/mcp-tool-catalog.d.ts +3 -0
- package/dist/packages/runtime/dist/mcp-tool-catalog.js +507 -0
- package/dist/packages/runtime/dist/mcp-tool-catalog.js.map +1 -0
- package/dist/packages/runtime/dist/mcp.d.ts +73 -0
- package/dist/packages/runtime/dist/mcp.js +67 -0
- package/dist/packages/runtime/dist/mcp.js.map +1 -0
- package/dist/packages/runtime/dist/policy.d.ts +19 -0
- package/dist/packages/runtime/dist/policy.js +41 -0
- package/dist/packages/runtime/dist/policy.js.map +1 -0
- package/dist/packages/runtime/dist/quota.d.ts +39 -0
- package/dist/packages/runtime/dist/quota.js +147 -0
- package/dist/packages/runtime/dist/quota.js.map +1 -0
- package/dist/packages/runtime/dist/session-audit.d.ts +107 -0
- package/dist/packages/runtime/dist/session-audit.js +520 -0
- package/dist/packages/runtime/dist/session-audit.js.map +1 -0
- package/dist/packages/runtime/dist/session-timeouts.d.ts +33 -0
- package/dist/packages/runtime/dist/session-timeouts.js +62 -0
- package/dist/packages/runtime/dist/session-timeouts.js.map +1 -0
- package/dist/packages/runtime/dist/session.d.ts +323 -0
- package/dist/packages/runtime/dist/session.js +2252 -0
- package/dist/packages/runtime/dist/session.js.map +1 -0
- package/dist/packages/runtime/dist/task-journal.d.ts +36 -0
- package/dist/packages/runtime/dist/task-journal.js +104 -0
- package/dist/packages/runtime/dist/task-journal.js.map +1 -0
- package/dist/packages/runtime/dist/verifier.d.ts +64 -0
- package/dist/packages/runtime/dist/verifier.js +109 -0
- package/dist/packages/runtime/dist/verifier.js.map +1 -0
- package/dist/packages/sandbox/dist/container.d.ts +33 -0
- package/dist/packages/sandbox/dist/container.js +189 -0
- package/dist/packages/sandbox/dist/container.js.map +1 -0
- package/dist/packages/sandbox/dist/index.d.ts +34 -0
- package/dist/packages/sandbox/dist/index.js +179 -0
- package/dist/packages/sandbox/dist/index.js.map +1 -0
- package/dist/packages/sandbox/dist/permission.d.ts +58 -0
- package/dist/packages/sandbox/dist/permission.js +90 -0
- package/dist/packages/sandbox/dist/permission.js.map +1 -0
- package/dist/spec/README.ja.md +76 -0
- package/dist/spec/README.md +135 -0
- package/dist/spec/ack-receipt.schema.json +77 -0
- package/dist/spec/agent-card.schema.json +83 -0
- package/dist/spec/approval-receipt.schema.json +94 -0
- package/dist/spec/audit-entry.schema.json +101 -0
- package/dist/spec/capability-token.schema.json +133 -0
- package/dist/spec/envelope.schema.json +197 -0
- package/dist/spec/examples/sample-ack-receipt.json +16 -0
- package/dist/spec/examples/sample-agent-card.json +35 -0
- package/dist/spec/examples/sample-approval-receipt.json +18 -0
- package/dist/spec/examples/sample-audit-entry.json +37 -0
- package/dist/spec/examples/sample-capability-token.json +39 -0
- package/dist/spec/examples/sample-envelope.json +21 -0
- package/dist/spec/examples/sample-task-manifest.json +141 -0
- package/dist/spec/examples/sample-usage-receipt.json +19 -0
- package/dist/spec/task-manifest.schema.json +422 -0
- package/dist/spec/usage-receipt.schema.json +91 -0
- package/package.json +61 -5
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { Readable, Writable } from 'node:stream';
|
|
2
|
+
import type { ApprovalReceipt, Gate, KeyPair } from '@acp/core';
|
|
3
|
+
import type { OwnerPolicy } from './policy.js';
|
|
4
|
+
/** Caps a worker applies before it accepts a contract or spends owner credentials. */
|
|
5
|
+
export interface WorkerAcceptancePolicy {
|
|
6
|
+
/** When non-empty, only these requester owner DIDs may be accepted. */
|
|
7
|
+
allowedRequesterDids?: readonly string[];
|
|
8
|
+
/** Explicit opt-in to accept every requester. Takes precedence over the allowlist. */
|
|
9
|
+
allowAnyRequester?: boolean;
|
|
10
|
+
maxInputTokens?: number;
|
|
11
|
+
maxOutputTokens?: number;
|
|
12
|
+
maxToolInvocations?: number;
|
|
13
|
+
maxWallClockSeconds?: number;
|
|
14
|
+
maxConcurrentTasks?: number;
|
|
15
|
+
/** How many PROPOSE envelopes one requester DID may submit per minute. */
|
|
16
|
+
maxTasksPerRequesterPerMinute?: number;
|
|
17
|
+
/** Replaces the one-minute window when set. */
|
|
18
|
+
requesterRateLimit?: {
|
|
19
|
+
maxRequests: number;
|
|
20
|
+
windowMs: number;
|
|
21
|
+
};
|
|
22
|
+
/** Register the worker AgentCard in the relay directory. Default is off. */
|
|
23
|
+
publishToRegistry?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare class ProposalRejectedError extends Error {
|
|
26
|
+
readonly reason: string;
|
|
27
|
+
readonly approved = false;
|
|
28
|
+
readonly code = "PROPOSAL_REJECTED";
|
|
29
|
+
constructor(reason: string);
|
|
30
|
+
}
|
|
31
|
+
/** Returns approved:false with a reason when a proposal exceeds the worker policy. */
|
|
32
|
+
export declare function evaluateContractAcceptance(policy: WorkerAcceptancePolicy | undefined, details: unknown, from?: string): {
|
|
33
|
+
approved: true;
|
|
34
|
+
} | {
|
|
35
|
+
approved: false;
|
|
36
|
+
reason: string;
|
|
37
|
+
};
|
|
38
|
+
export interface ApprovalRequest {
|
|
39
|
+
taskId: string;
|
|
40
|
+
gate: Gate;
|
|
41
|
+
target: unknown;
|
|
42
|
+
details?: unknown;
|
|
43
|
+
signal?: AbortSignal;
|
|
44
|
+
}
|
|
45
|
+
export interface ApprovalProvider {
|
|
46
|
+
approve(request: ApprovalRequest): Promise<ApprovalReceipt>;
|
|
47
|
+
}
|
|
48
|
+
export declare class InteractiveCliApprovalProvider implements ApprovalProvider {
|
|
49
|
+
readonly owner: KeyPair;
|
|
50
|
+
readonly options: {
|
|
51
|
+
input?: Readable;
|
|
52
|
+
output?: Writable;
|
|
53
|
+
formatRequest?: (request: ApprovalRequest) => string;
|
|
54
|
+
};
|
|
55
|
+
constructor(owner: KeyPair, options?: {
|
|
56
|
+
input?: Readable;
|
|
57
|
+
output?: Writable;
|
|
58
|
+
formatRequest?: (request: ApprovalRequest) => string;
|
|
59
|
+
});
|
|
60
|
+
approve(request: ApprovalRequest): Promise<ApprovalReceipt>;
|
|
61
|
+
}
|
|
62
|
+
export declare class PolicyAutoApprovalProvider implements ApprovalProvider {
|
|
63
|
+
readonly owner: KeyPair;
|
|
64
|
+
readonly policy: OwnerPolicy;
|
|
65
|
+
readonly options: {
|
|
66
|
+
yes?: boolean;
|
|
67
|
+
confirmedGates?: Gate[];
|
|
68
|
+
acceptance?: WorkerAcceptancePolicy;
|
|
69
|
+
};
|
|
70
|
+
constructor(owner: KeyPair, policy?: OwnerPolicy, options?: {
|
|
71
|
+
yes?: boolean;
|
|
72
|
+
confirmedGates?: Gate[];
|
|
73
|
+
acceptance?: WorkerAcceptancePolicy;
|
|
74
|
+
});
|
|
75
|
+
approve(r: ApprovalRequest): Promise<ApprovalReceipt>;
|
|
76
|
+
}
|
|
77
|
+
export interface WebhookApprovalProviderOptions {
|
|
78
|
+
url: string;
|
|
79
|
+
ownerDid?: string;
|
|
80
|
+
fetch?: typeof fetch;
|
|
81
|
+
timeoutMs?: number;
|
|
82
|
+
/**
|
|
83
|
+
* `signed-receipt` (default) posts a signed approval request and requires a
|
|
84
|
+
* signed ApprovalReceipt. `owner-decision` posts
|
|
85
|
+
* `{ taskId, summaryHash, reason, approverDid }` and signs locally when the
|
|
86
|
+
* webhook returns `{ approved: true }`.
|
|
87
|
+
*/
|
|
88
|
+
response?: 'signed-receipt' | 'owner-decision';
|
|
89
|
+
}
|
|
90
|
+
/** Reject webhook URLs that are not plain HTTP(S) endpoints. */
|
|
91
|
+
export declare function assertApprovalWebhookUrl(value: string): void;
|
|
92
|
+
export declare class WebhookApprovalProvider implements ApprovalProvider {
|
|
93
|
+
readonly owner: KeyPair;
|
|
94
|
+
readonly options: WebhookApprovalProviderOptions;
|
|
95
|
+
constructor(owner: KeyPair, options: WebhookApprovalProviderOptions);
|
|
96
|
+
approve(r: ApprovalRequest): Promise<ApprovalReceipt>;
|
|
97
|
+
/** Sign with the owner key only when the webhook explicitly approves. */
|
|
98
|
+
private approveOwnerDecision;
|
|
99
|
+
}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { createInterface } from 'node:readline';
|
|
3
|
+
import { signApproval, signPayload, verifyApproval, digest } from '../../core/dist/index.js';
|
|
4
|
+
export class ProposalRejectedError extends Error {
|
|
5
|
+
reason;
|
|
6
|
+
approved = false;
|
|
7
|
+
code = 'PROPOSAL_REJECTED';
|
|
8
|
+
constructor(reason) {
|
|
9
|
+
super('PROPOSAL_REJECTED: ' + reason);
|
|
10
|
+
this.reason = reason;
|
|
11
|
+
this.name = 'ProposalRejectedError';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const budgetFields = [
|
|
15
|
+
'maxInputTokens',
|
|
16
|
+
'maxOutputTokens',
|
|
17
|
+
'maxToolInvocations',
|
|
18
|
+
'maxWallClockSeconds',
|
|
19
|
+
];
|
|
20
|
+
function proposedManifest(details) {
|
|
21
|
+
if (!details || typeof details !== 'object')
|
|
22
|
+
return undefined;
|
|
23
|
+
const manifest = details.manifest;
|
|
24
|
+
if (!manifest || typeof manifest !== 'object' || Array.isArray(manifest))
|
|
25
|
+
return undefined;
|
|
26
|
+
return manifest;
|
|
27
|
+
}
|
|
28
|
+
function envelopeFrom(details, from) {
|
|
29
|
+
if (typeof from === 'string' && from.length > 0)
|
|
30
|
+
return from;
|
|
31
|
+
if (!details || typeof details !== 'object')
|
|
32
|
+
return undefined;
|
|
33
|
+
const value = details.from;
|
|
34
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
35
|
+
}
|
|
36
|
+
function budgetLimit(policy, field) {
|
|
37
|
+
return policy[field];
|
|
38
|
+
}
|
|
39
|
+
/** Returns approved:false with a reason when a proposal exceeds the worker policy. */
|
|
40
|
+
export function evaluateContractAcceptance(policy, details, from) {
|
|
41
|
+
if (!policy)
|
|
42
|
+
return { approved: true };
|
|
43
|
+
const manifest = proposedManifest(details);
|
|
44
|
+
const limited = budgetFields.some((field) => policy[field] !== undefined);
|
|
45
|
+
if (limited && !manifest)
|
|
46
|
+
return { approved: false, reason: 'manifest is missing' };
|
|
47
|
+
if (manifest && limited) {
|
|
48
|
+
const budget = manifest.budget;
|
|
49
|
+
if (!budget || typeof budget !== 'object' || Array.isArray(budget))
|
|
50
|
+
return { approved: false, reason: 'budget is missing' };
|
|
51
|
+
for (const field of budgetFields) {
|
|
52
|
+
const limit = budgetLimit(policy, field);
|
|
53
|
+
if (limit === undefined)
|
|
54
|
+
continue;
|
|
55
|
+
const proposed = budget[field];
|
|
56
|
+
if (typeof proposed !== 'number' || !Number.isFinite(proposed))
|
|
57
|
+
return { approved: false, reason: field + ' is missing or not a finite number' };
|
|
58
|
+
if (proposed > limit)
|
|
59
|
+
return {
|
|
60
|
+
approved: false,
|
|
61
|
+
reason: field + ' ' + proposed + ' exceeds worker limit ' + limit,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (manifest && policy.maxWallClockSeconds !== undefined && 'timeoutSeconds' in manifest) {
|
|
66
|
+
const timeout = manifest.timeoutSeconds;
|
|
67
|
+
if (typeof timeout !== 'number' || !Number.isFinite(timeout))
|
|
68
|
+
return { approved: false, reason: 'timeoutSeconds is missing or not a finite number' };
|
|
69
|
+
if (timeout > policy.maxWallClockSeconds)
|
|
70
|
+
return {
|
|
71
|
+
approved: false,
|
|
72
|
+
reason: 'timeoutSeconds ' +
|
|
73
|
+
timeout +
|
|
74
|
+
' exceeds worker limit ' +
|
|
75
|
+
policy.maxWallClockSeconds,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (policy.allowAnyRequester)
|
|
79
|
+
return { approved: true };
|
|
80
|
+
const allow = (policy.allowedRequesterDids ?? []).map((did) => did.trim()).filter(Boolean);
|
|
81
|
+
if (allow.length === 0)
|
|
82
|
+
return { approved: true };
|
|
83
|
+
const ownerDid = manifest?.requester?.ownerDid;
|
|
84
|
+
const sender = envelopeFrom(details, from);
|
|
85
|
+
if (typeof sender === 'string' && typeof ownerDid === 'string' && sender !== ownerDid)
|
|
86
|
+
return {
|
|
87
|
+
approved: false,
|
|
88
|
+
reason: 'requester ' + ownerDid + ' does not match envelope from ' + sender,
|
|
89
|
+
};
|
|
90
|
+
const authenticated = typeof ownerDid === 'string' && ownerDid.length > 0 ? ownerDid : sender;
|
|
91
|
+
if (typeof authenticated === 'string' && allow.includes(authenticated))
|
|
92
|
+
return { approved: true };
|
|
93
|
+
return {
|
|
94
|
+
approved: false,
|
|
95
|
+
reason: 'requester ' + (authenticated ?? 'unknown') + ' is not allowed',
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
export class InteractiveCliApprovalProvider {
|
|
99
|
+
owner;
|
|
100
|
+
options;
|
|
101
|
+
constructor(owner, options = {}) {
|
|
102
|
+
this.owner = owner;
|
|
103
|
+
this.options = options;
|
|
104
|
+
}
|
|
105
|
+
async approve(request) {
|
|
106
|
+
const output = this.options.output ?? process.stdout;
|
|
107
|
+
output.write((this.options.formatRequest?.(request) ?? JSON.stringify({
|
|
108
|
+
taskId: request.taskId,
|
|
109
|
+
gate: request.gate,
|
|
110
|
+
targetDigest: digest(request.target),
|
|
111
|
+
target: request.target,
|
|
112
|
+
details: request.details ?? null,
|
|
113
|
+
}, null, 2)) + '\nApprove [y/N]? ');
|
|
114
|
+
const rl = createInterface({ input: this.options.input ?? process.stdin, crlfDelay: Infinity });
|
|
115
|
+
try {
|
|
116
|
+
const answer = await new Promise((resolve, reject) => {
|
|
117
|
+
const abort = () => {
|
|
118
|
+
cleanup();
|
|
119
|
+
reject(new Error('APPROVAL_ABORTED'));
|
|
120
|
+
};
|
|
121
|
+
const cleanup = () => request.signal?.removeEventListener('abort', abort);
|
|
122
|
+
rl.once('line', (line) => {
|
|
123
|
+
cleanup();
|
|
124
|
+
resolve(line);
|
|
125
|
+
});
|
|
126
|
+
rl.once('close', () => {
|
|
127
|
+
cleanup();
|
|
128
|
+
resolve('');
|
|
129
|
+
});
|
|
130
|
+
rl.once('error', (e) => {
|
|
131
|
+
cleanup();
|
|
132
|
+
reject(e);
|
|
133
|
+
});
|
|
134
|
+
request.signal?.addEventListener('abort', abort, { once: true });
|
|
135
|
+
if (request.signal?.aborted)
|
|
136
|
+
abort();
|
|
137
|
+
});
|
|
138
|
+
return signApproval(request.taskId, request.gate, request.target, this.owner, /^y(es)?$/i.test(answer.trim()) ? 'APPROVED' : 'REJECTED');
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
rl.close();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
export class PolicyAutoApprovalProvider {
|
|
146
|
+
owner;
|
|
147
|
+
policy;
|
|
148
|
+
options;
|
|
149
|
+
constructor(owner, policy = {
|
|
150
|
+
requiredGates: [],
|
|
151
|
+
autoApprove: ['contract_acceptance', 'final_verification'],
|
|
152
|
+
}, options = {}) {
|
|
153
|
+
this.owner = owner;
|
|
154
|
+
this.policy = policy;
|
|
155
|
+
this.options = options;
|
|
156
|
+
}
|
|
157
|
+
async approve(r) {
|
|
158
|
+
if (r.gate === 'contract_acceptance') {
|
|
159
|
+
const decision = evaluateContractAcceptance(this.options.acceptance, r.details);
|
|
160
|
+
if (!decision.approved)
|
|
161
|
+
throw new ProposalRejectedError(decision.reason);
|
|
162
|
+
}
|
|
163
|
+
const explicit = this.options.confirmedGates?.includes(r.gate);
|
|
164
|
+
const sensitive = ['external_side_effect', 'budget_increase'].includes(r.gate);
|
|
165
|
+
if (!explicit &&
|
|
166
|
+
(sensitive ||
|
|
167
|
+
this.policy.requiredGates.includes(r.gate) ||
|
|
168
|
+
(!this.options.yes && !this.policy.autoApprove.includes(r.gate))))
|
|
169
|
+
throw new Error('HITL_REQUIRED: ' + r.gate);
|
|
170
|
+
return signApproval(r.taskId, r.gate, r.target, this.owner);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/** Reject webhook URLs that are not plain HTTP(S) endpoints. */
|
|
174
|
+
export function assertApprovalWebhookUrl(value) {
|
|
175
|
+
let url;
|
|
176
|
+
try {
|
|
177
|
+
url = new URL(value);
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
throw new Error('INVALID_APPROVAL_WEBHOOK_URL');
|
|
181
|
+
}
|
|
182
|
+
if ((url.protocol !== 'http:' && url.protocol !== 'https:') || url.username || url.password)
|
|
183
|
+
throw new Error('INVALID_APPROVAL_WEBHOOK_URL');
|
|
184
|
+
}
|
|
185
|
+
function approvalReason(request) {
|
|
186
|
+
const details = request.details;
|
|
187
|
+
if (details && typeof details === 'object' && !Array.isArray(details)) {
|
|
188
|
+
const reason = details.reason;
|
|
189
|
+
if (typeof reason === 'string' && reason.length > 0)
|
|
190
|
+
return reason;
|
|
191
|
+
}
|
|
192
|
+
return request.gate;
|
|
193
|
+
}
|
|
194
|
+
export class WebhookApprovalProvider {
|
|
195
|
+
owner;
|
|
196
|
+
options;
|
|
197
|
+
constructor(owner, options) {
|
|
198
|
+
this.owner = owner;
|
|
199
|
+
this.options = options;
|
|
200
|
+
if (options.response === 'owner-decision')
|
|
201
|
+
assertApprovalWebhookUrl(options.url);
|
|
202
|
+
}
|
|
203
|
+
async approve(r) {
|
|
204
|
+
if (this.options.response === 'owner-decision')
|
|
205
|
+
return this.approveOwnerDecision(r);
|
|
206
|
+
const body = signPayload({
|
|
207
|
+
type: 'ApprovalRequest',
|
|
208
|
+
taskId: r.taskId,
|
|
209
|
+
gate: r.gate,
|
|
210
|
+
target: r.target,
|
|
211
|
+
targetDigest: digest(r.target),
|
|
212
|
+
details: r.details ?? null,
|
|
213
|
+
}, this.owner);
|
|
214
|
+
const signal = AbortSignal.any([
|
|
215
|
+
AbortSignal.timeout(this.options.timeoutMs ?? 60000),
|
|
216
|
+
...(r.signal ? [r.signal] : []),
|
|
217
|
+
]);
|
|
218
|
+
const response = await (this.options.fetch ?? fetch)(this.options.url, {
|
|
219
|
+
method: 'POST',
|
|
220
|
+
headers: { 'content-type': 'application/json' },
|
|
221
|
+
body: JSON.stringify(body),
|
|
222
|
+
signal,
|
|
223
|
+
redirect: 'error',
|
|
224
|
+
});
|
|
225
|
+
if (!response.ok)
|
|
226
|
+
throw new Error('APPROVAL_WEBHOOK_FAILED');
|
|
227
|
+
const receipt = (await response.json());
|
|
228
|
+
if (!verifyApproval(receipt, this.options.ownerDid ?? this.owner.did, r.taskId, r.gate, r.target))
|
|
229
|
+
throw new Error('INVALID_APPROVAL_RESPONSE');
|
|
230
|
+
return receipt;
|
|
231
|
+
}
|
|
232
|
+
/** Sign with the owner key only when the webhook explicitly approves. */
|
|
233
|
+
async approveOwnerDecision(r) {
|
|
234
|
+
const body = {
|
|
235
|
+
taskId: r.taskId,
|
|
236
|
+
summaryHash: digest(r.target),
|
|
237
|
+
reason: approvalReason(r),
|
|
238
|
+
approverDid: this.owner.did,
|
|
239
|
+
};
|
|
240
|
+
const signal = AbortSignal.any([
|
|
241
|
+
AbortSignal.timeout(this.options.timeoutMs ?? 60000),
|
|
242
|
+
...(r.signal ? [r.signal] : []),
|
|
243
|
+
]);
|
|
244
|
+
const response = await (this.options.fetch ?? fetch)(this.options.url, {
|
|
245
|
+
method: 'POST',
|
|
246
|
+
headers: { 'content-type': 'application/json' },
|
|
247
|
+
body: JSON.stringify(body),
|
|
248
|
+
signal,
|
|
249
|
+
redirect: 'error',
|
|
250
|
+
});
|
|
251
|
+
if (!response.ok)
|
|
252
|
+
throw new Error('APPROVAL_REJECTED');
|
|
253
|
+
let parsed;
|
|
254
|
+
try {
|
|
255
|
+
parsed = await response.json();
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
throw new Error('APPROVAL_REJECTED');
|
|
259
|
+
}
|
|
260
|
+
const approved = !!parsed &&
|
|
261
|
+
typeof parsed === 'object' &&
|
|
262
|
+
!Array.isArray(parsed) &&
|
|
263
|
+
parsed.approved === true;
|
|
264
|
+
if (!approved)
|
|
265
|
+
throw new Error('APPROVAL_REJECTED');
|
|
266
|
+
return signApproval(r.taskId, r.gate, r.target, this.owner, 'APPROVED');
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=approval-providers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-providers.js","sourceRoot":"","sources":["../src/approval-providers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { mkdirSync, readFileSync, writeFileSync, renameSync, unlinkSync } from 'node:fs';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
5
|
+
/** Host-wide UTC admission counter. Lock contention and corrupt state fail closed. */
|
|
6
|
+
export function consumeDailyTask(path, limit, taskId, now = Date.now()) {
|
|
7
|
+
if (!Number.isSafeInteger(limit) || limit < 1 || !Number.isFinite(now) || !taskId)
|
|
8
|
+
throw new Error('INVALID_DAILY_LIMIT');
|
|
9
|
+
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
10
|
+
const lock = path + '.lock', temporary = path + '.' + randomUUID() + '.tmp';
|
|
11
|
+
try {
|
|
12
|
+
writeFileSync(lock, '', { flag: 'wx', mode: 0o600 });
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
throw new Error('DAILY_LIMIT_BUSY: retry later; never remove a live lock');
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const day = new Date(now).toISOString().slice(0, 10);
|
|
19
|
+
let state = { version: 1, day, tasks: [] };
|
|
20
|
+
try {
|
|
21
|
+
state = JSON.parse(readFileSync(path, 'utf8'));
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
if (e.code !== 'ENOENT')
|
|
25
|
+
throw new Error('DAILY_LIMIT_INVALID');
|
|
26
|
+
}
|
|
27
|
+
if (state.version !== 1 || !/^\d{4}-\d{2}-\d{2}$/.test(state.day) ||
|
|
28
|
+
!Array.isArray(state.tasks) || state.tasks.some(t => typeof t !== 'string') ||
|
|
29
|
+
new Set(state.tasks).size !== state.tasks.length)
|
|
30
|
+
throw new Error('DAILY_LIMIT_INVALID');
|
|
31
|
+
if (day < state.day)
|
|
32
|
+
throw new Error('DAILY_LIMIT_CLOCK_ROLLBACK');
|
|
33
|
+
if (day > state.day)
|
|
34
|
+
state = { version: 1, day, tasks: [] };
|
|
35
|
+
if (state.tasks.includes(taskId))
|
|
36
|
+
throw new Error('DAILY_TASK_REPLAY');
|
|
37
|
+
if (state.tasks.length >= limit)
|
|
38
|
+
throw new Error('DAILY_LIMIT_REACHED');
|
|
39
|
+
state.tasks.push(taskId);
|
|
40
|
+
writeFileSync(temporary, JSON.stringify(state), { flag: 'wx', mode: 0o600, flush: true });
|
|
41
|
+
renameSync(temporary, path);
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
try {
|
|
45
|
+
unlinkSync(temporary);
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
if (e.code !== 'ENOENT')
|
|
49
|
+
throw e;
|
|
50
|
+
}
|
|
51
|
+
unlinkSync(lock);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=daily-limit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daily-limit.js","sourceRoot":"","sources":["../src/daily-limit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ContractMachine, CapabilityGuard } from '@acp/core';
|
|
2
|
+
import type { TaskContract, KeyPair, ApprovalReceipt, CapabilityToken, Capability, Signed, Transition, ContractEvent, Json, SignedEnvelope, RevocationList } from '@acp/core';
|
|
3
|
+
import type { SandboxBoundaryMetadata } from '@acp/sandbox';
|
|
4
|
+
import { ApprovalGate } from './policy.js';
|
|
5
|
+
import type { OwnerPolicy } from './policy.js';
|
|
6
|
+
import { QuotaMeter } from './quota.js';
|
|
7
|
+
import type { MCPProxy } from './mcp.js';
|
|
8
|
+
import { EnvelopeInbox } from './inbox.js';
|
|
9
|
+
import { VerificationEngine } from './verifier.js';
|
|
10
|
+
export declare class OwnerGateway {
|
|
11
|
+
readonly owner: KeyPair;
|
|
12
|
+
readonly contract: TaskContract;
|
|
13
|
+
effectiveIsolationLevel: string;
|
|
14
|
+
/** Set by `execute` from the runner. Undefined until a sandbox task has run. */
|
|
15
|
+
sandboxBoundary?: SandboxBoundaryMetadata;
|
|
16
|
+
readonly capabilities: CapabilityGuard;
|
|
17
|
+
readonly inbox: EnvelopeInbox;
|
|
18
|
+
readonly machine: ContractMachine;
|
|
19
|
+
readonly approvals: ApprovalGate;
|
|
20
|
+
readonly quota: QuotaMeter;
|
|
21
|
+
constructor(owner: KeyPair, contract: TaskContract, policy: OwnerPolicy, revocation?: RevocationList);
|
|
22
|
+
accept(receipt: ApprovalReceipt): Signed<Transition>;
|
|
23
|
+
private applyOwn;
|
|
24
|
+
transition(event: ContractEvent): Signed<Transition>;
|
|
25
|
+
verifyAndSettle(envelope: SignedEnvelope, engine: VerificationEngine, approval?: ApprovalReceipt | (() => Promise<ApprovalReceipt>), options?: {
|
|
26
|
+
allowUnencryptedEnvelopes?: boolean;
|
|
27
|
+
}): Promise<{
|
|
28
|
+
result: import("./verifier.js").VerificationResult;
|
|
29
|
+
verification: Signed<Transition>;
|
|
30
|
+
settlement: Signed<Transition> | undefined;
|
|
31
|
+
}>;
|
|
32
|
+
redelegate(chain: CapabilityToken[], params: Omit<Capability, 'id' | 'type' | 'issuer' | 'parentHash'>, receipt: ApprovalReceipt): CapabilityToken;
|
|
33
|
+
execute(code: string, proxy: MCPProxy, input?: Json): Promise<Json>;
|
|
34
|
+
close(): void;
|
|
35
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { ContractMachine, createCapability, verifyCapabilityChain, digest, CapabilityGuard, } from '../../core/dist/index.js';
|
|
3
|
+
import { runContainerOrSubprocessSandbox } from '../../sandbox/dist/index.js';
|
|
4
|
+
import { ApprovalGate } from './policy.js';
|
|
5
|
+
import { QuotaMeter } from './quota.js';
|
|
6
|
+
import { EnvelopeInbox } from './inbox.js';
|
|
7
|
+
export class OwnerGateway {
|
|
8
|
+
owner;
|
|
9
|
+
contract;
|
|
10
|
+
effectiveIsolationLevel = 'subprocess_restricted';
|
|
11
|
+
/** Set by `execute` from the runner. Undefined until a sandbox task has run. */
|
|
12
|
+
sandboxBoundary;
|
|
13
|
+
capabilities;
|
|
14
|
+
inbox;
|
|
15
|
+
machine;
|
|
16
|
+
approvals;
|
|
17
|
+
quota;
|
|
18
|
+
constructor(owner, contract, policy, revocation) {
|
|
19
|
+
this.owner = owner;
|
|
20
|
+
this.contract = contract;
|
|
21
|
+
if (![contract.manifest.requester.ownerDid, contract.manifest.worker?.ownerDid].includes(owner.did))
|
|
22
|
+
throw new Error('GATEWAY_OWNER_MISMATCH');
|
|
23
|
+
this.inbox = new EnvelopeInbox(owner.did, owner.did === contract.manifest.requester.ownerDid
|
|
24
|
+
? contract.manifest.worker.ownerDid
|
|
25
|
+
: contract.manifest.requester.ownerDid, contract.manifest.taskId);
|
|
26
|
+
this.machine = new ContractMachine(contract);
|
|
27
|
+
this.capabilities = new CapabilityGuard(revocation);
|
|
28
|
+
this.approvals = new ApprovalGate(owner.did, policy);
|
|
29
|
+
this.quota = new QuotaMeter(contract.manifest.taskId, contract.manifest.budget, owner.did);
|
|
30
|
+
}
|
|
31
|
+
accept(receipt) {
|
|
32
|
+
this.approvals.require(this.contract.manifest.taskId, 'contract_acceptance', this.contract.contractDigest, receipt);
|
|
33
|
+
return this.applyOwn('ACCEPT');
|
|
34
|
+
}
|
|
35
|
+
applyOwn(event) {
|
|
36
|
+
const signed = this.machine.event(event, this.owner);
|
|
37
|
+
this.machine.apply(signed);
|
|
38
|
+
if (['SETTLED', 'CANCELLED'].includes(this.machine.state))
|
|
39
|
+
this.capabilities.revokeTask(this.contract.manifest.taskId);
|
|
40
|
+
return signed;
|
|
41
|
+
}
|
|
42
|
+
transition(event) {
|
|
43
|
+
if (['ACCEPT', 'VERIFY_ACCEPT', 'VERIFY_REJECT', 'SETTLE'].includes(event))
|
|
44
|
+
throw new Error('GATED_TRANSITION_REQUIRED');
|
|
45
|
+
return this.applyOwn(event);
|
|
46
|
+
}
|
|
47
|
+
async verifyAndSettle(envelope, engine, approval, options) {
|
|
48
|
+
if (this.owner.did !== this.contract.manifest.requester.ownerDid ||
|
|
49
|
+
this.machine.state !== 'DELIVERED')
|
|
50
|
+
throw new Error('INVALID_VERIFICATION_STATE');
|
|
51
|
+
const result = await engine.verify(this.contract, envelope, this.approvals, approval, this.owner, options);
|
|
52
|
+
const verification = this.applyOwn(result.event);
|
|
53
|
+
const settlement = result.accepted ? this.applyOwn('SETTLE') : undefined;
|
|
54
|
+
return { result, verification, settlement };
|
|
55
|
+
}
|
|
56
|
+
redelegate(chain, params, receipt) {
|
|
57
|
+
if (this.machine.state !== 'IN_PROGRESS')
|
|
58
|
+
throw new Error('CAPABILITY_VIOLATION: inactive task');
|
|
59
|
+
verifyCapabilityChain(chain, {
|
|
60
|
+
rootDid: this.contract.manifest.requester.ownerDid,
|
|
61
|
+
audience: this.owner.did,
|
|
62
|
+
taskId: this.contract.manifest.taskId,
|
|
63
|
+
});
|
|
64
|
+
this.approvals.require(this.contract.manifest.taskId, 'redelegation', { parentDigest: digest(chain.at(-1)), params }, receipt);
|
|
65
|
+
return createCapability(params, this.owner, chain.at(-1));
|
|
66
|
+
}
|
|
67
|
+
async execute(code, proxy, input) {
|
|
68
|
+
if (this.machine.state !== 'IN_PROGRESS')
|
|
69
|
+
throw new Error('CONTRACT_NOT_RUNNING');
|
|
70
|
+
const policy = this.contract.manifest.sandboxPolicy;
|
|
71
|
+
if (!['subprocess_restricted', 'oci_container'].includes(policy.isolationLevel) ||
|
|
72
|
+
policy.networkAccess !== 'none' ||
|
|
73
|
+
policy.filesystemScope !== 'ephemeral_workspace_only')
|
|
74
|
+
throw new Error('UNSUPPORTED_SANDBOX_POLICY');
|
|
75
|
+
const result = await runContainerOrSubprocessSandbox({
|
|
76
|
+
isolationLevel: policy.isolationLevel,
|
|
77
|
+
code,
|
|
78
|
+
input,
|
|
79
|
+
timeoutMs: this.quota.budget.maxWallClockSeconds * 1000,
|
|
80
|
+
signal: this.quota.controller.signal,
|
|
81
|
+
onTool: (name, args) => proxy.callTool(name, args),
|
|
82
|
+
onUsage: (i, o) => this.quota.record(i, o),
|
|
83
|
+
});
|
|
84
|
+
this.effectiveIsolationLevel = result.effectiveIsolationLevel;
|
|
85
|
+
this.sandboxBoundary = result.sandboxBoundary;
|
|
86
|
+
return result.output;
|
|
87
|
+
}
|
|
88
|
+
close() {
|
|
89
|
+
this.quota.close();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway.js","sourceRoot":"","sources":["../src/gateway.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SignedEnvelope } from '@acp/core';
|
|
2
|
+
/** Gateway-owned replay defense, independent of any relay behavior. */
|
|
3
|
+
export declare class EnvelopeInbox {
|
|
4
|
+
#private;
|
|
5
|
+
readonly recipientDid: string;
|
|
6
|
+
readonly senderDid: string;
|
|
7
|
+
readonly taskId: string;
|
|
8
|
+
constructor(recipientDid: string, senderDid: string, taskId: string);
|
|
9
|
+
receive(envelope: SignedEnvelope): SignedEnvelope;
|
|
10
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { verifyEnvelope } from '../../core/dist/index.js';
|
|
3
|
+
/** Gateway-owned replay defense, independent of any relay behavior. */
|
|
4
|
+
export class EnvelopeInbox {
|
|
5
|
+
recipientDid;
|
|
6
|
+
senderDid;
|
|
7
|
+
taskId;
|
|
8
|
+
#next = 0;
|
|
9
|
+
constructor(recipientDid, senderDid, taskId) {
|
|
10
|
+
this.recipientDid = recipientDid;
|
|
11
|
+
this.senderDid = senderDid;
|
|
12
|
+
this.taskId = taskId;
|
|
13
|
+
}
|
|
14
|
+
receive(envelope) {
|
|
15
|
+
if (!verifyEnvelope(envelope, this.recipientDid) ||
|
|
16
|
+
envelope.payload.senderDid !== this.senderDid ||
|
|
17
|
+
envelope.payload.taskId !== this.taskId ||
|
|
18
|
+
envelope.payload.seq !== this.#next)
|
|
19
|
+
throw new Error('INVALID_OR_REPLAYED_ENVELOPE');
|
|
20
|
+
this.#next++;
|
|
21
|
+
return structuredClone(envelope);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=inbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox.js","sourceRoot":"","sources":["../src/inbox.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,uEAAuE;AACvE,MAAM,OAAO,aAAa;IAGb;IACA;IACA;IAJX,KAAK,GAAG,CAAC,CAAC;IACV,YACW,YAAoB,EACpB,SAAiB,EACjB,MAAc;QAFd,iBAAY,GAAZ,YAAY,CAAQ;QACpB,cAAS,GAAT,SAAS,CAAQ;QACjB,WAAM,GAAN,MAAM,CAAQ;IACtB,CAAC;IACJ,OAAO,CAAC,QAAwB;QAC9B,IACE,CAAC,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC;YAC5C,QAAQ,CAAC,OAAO,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS;YAC7C,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM;YACvC,QAAQ,CAAC,OAAO,CAAC,GAAG,KAAK,IAAI,CAAC,KAAK;YAEnC,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAClD,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,OAAO,eAAe,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from './policy.js';
|
|
2
|
+
export * from './quota.js';
|
|
3
|
+
export * from './mcp.js';
|
|
4
|
+
export * from './mcp-server.js';
|
|
5
|
+
export * from './verifier.js';
|
|
6
|
+
export * from './gateway.js';
|
|
7
|
+
export * from './a2a.js';
|
|
8
|
+
export * from './inbox.js';
|
|
9
|
+
export * from './adapter.js';
|
|
10
|
+
export * from './approval-providers.js';
|
|
11
|
+
export { createSignedAgentCard, verifySignedAgentCard, toA2AAgentCard, createInviteToken, parseAndVerifyInviteToken, } from '@acp/core';
|
|
12
|
+
export * from './session.js';
|
|
13
|
+
export { PeerRejectedError } from './session-audit.js';
|