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.
Files changed (208) hide show
  1. package/NOTICE +43 -0
  2. package/README.ja.md +397 -0
  3. package/README.md +567 -1
  4. package/dist/cli/dist/acp.d.ts +2 -0
  5. package/dist/cli/dist/acp.js +6 -0
  6. package/dist/cli/dist/acp.js.map +1 -0
  7. package/dist/cli/dist/approval-summary.d.ts +2 -0
  8. package/dist/cli/dist/approval-summary.js +32 -0
  9. package/dist/cli/dist/approval-summary.js.map +1 -0
  10. package/dist/cli/dist/board.d.ts +47 -0
  11. package/dist/cli/dist/board.js +255 -0
  12. package/dist/cli/dist/board.js.map +1 -0
  13. package/dist/cli/dist/contacts.d.ts +18 -0
  14. package/dist/cli/dist/contacts.js +154 -0
  15. package/dist/cli/dist/contacts.js.map +1 -0
  16. package/dist/cli/dist/doctor.d.ts +13 -0
  17. package/dist/cli/dist/doctor.js +30 -0
  18. package/dist/cli/dist/doctor.js.map +1 -0
  19. package/dist/cli/dist/error-messages.d.ts +2 -0
  20. package/dist/cli/dist/error-messages.js +24 -0
  21. package/dist/cli/dist/error-messages.js.map +1 -0
  22. package/dist/cli/dist/index.d.ts +2 -0
  23. package/dist/cli/dist/index.js +194 -0
  24. package/dist/cli/dist/index.js.map +1 -0
  25. package/dist/cli/dist/invite-share.d.ts +16 -0
  26. package/dist/cli/dist/invite-share.js +163 -0
  27. package/dist/cli/dist/invite-share.js.map +1 -0
  28. package/dist/cli/dist/mcp.d.ts +17 -0
  29. package/dist/cli/dist/mcp.js +105 -0
  30. package/dist/cli/dist/mcp.js.map +1 -0
  31. package/dist/cli/dist/network.d.ts +1 -0
  32. package/dist/cli/dist/network.js +396 -0
  33. package/dist/cli/dist/network.js.map +1 -0
  34. package/dist/cli/dist/public-settings.d.ts +27 -0
  35. package/dist/cli/dist/public-settings.js +33 -0
  36. package/dist/cli/dist/public-settings.js.map +1 -0
  37. package/dist/cli/dist/receipt.d.ts +39 -0
  38. package/dist/cli/dist/receipt.js +90 -0
  39. package/dist/cli/dist/receipt.js.map +1 -0
  40. package/dist/cli/dist/receive-hook.d.ts +2 -0
  41. package/dist/cli/dist/receive-hook.js +35 -0
  42. package/dist/cli/dist/receive-hook.js.map +1 -0
  43. package/dist/cli/dist/task-input.d.ts +2 -0
  44. package/dist/cli/dist/task-input.js +19 -0
  45. package/dist/cli/dist/task-input.js.map +1 -0
  46. package/dist/cli/dist/wake-hook.d.ts +3 -0
  47. package/dist/cli/dist/wake-hook.js +32 -0
  48. package/dist/cli/dist/wake-hook.js.map +1 -0
  49. package/dist/examples/two-owner-demo/alice-policy.json +4 -0
  50. package/dist/examples/two-owner-demo/bob-policy.json +4 -0
  51. package/dist/examples/two-owner-demo/dist/run-demo.d.ts +71 -0
  52. package/dist/examples/two-owner-demo/dist/run-demo.js +383 -0
  53. package/dist/examples/two-owner-demo/dist/run-demo.js.map +1 -0
  54. package/dist/package.json +1 -0
  55. package/dist/packages/adapters/dist/command.d.ts +122 -0
  56. package/dist/packages/adapters/dist/command.js +378 -0
  57. package/dist/packages/adapters/dist/command.js.map +1 -0
  58. package/dist/packages/adapters/dist/credential-proxy.d.ts +37 -0
  59. package/dist/packages/adapters/dist/credential-proxy.js +363 -0
  60. package/dist/packages/adapters/dist/credential-proxy.js.map +1 -0
  61. package/dist/packages/adapters/dist/index.d.ts +6 -0
  62. package/dist/packages/adapters/dist/index.js +6 -0
  63. package/dist/packages/adapters/dist/index.js.map +1 -0
  64. package/dist/packages/adapters/dist/mcp.d.ts +32 -0
  65. package/dist/packages/adapters/dist/mcp.js +87 -0
  66. package/dist/packages/adapters/dist/mcp.js.map +1 -0
  67. package/dist/packages/adapters/dist/openai.d.ts +23 -0
  68. package/dist/packages/adapters/dist/openai.js +81 -0
  69. package/dist/packages/adapters/dist/openai.js.map +1 -0
  70. package/dist/packages/adapters/dist/sandbox.d.ts +45 -0
  71. package/dist/packages/adapters/dist/sandbox.js +60 -0
  72. package/dist/packages/adapters/dist/sandbox.js.map +1 -0
  73. package/dist/packages/core/dist/capability.d.ts +36 -0
  74. package/dist/packages/core/dist/capability.js +203 -0
  75. package/dist/packages/core/dist/capability.js.map +1 -0
  76. package/dist/packages/core/dist/contract.d.ts +33 -0
  77. package/dist/packages/core/dist/contract.js +97 -0
  78. package/dist/packages/core/dist/contract.js.map +1 -0
  79. package/dist/packages/core/dist/crypto.d.ts +34 -0
  80. package/dist/packages/core/dist/crypto.js +329 -0
  81. package/dist/packages/core/dist/crypto.js.map +1 -0
  82. package/dist/packages/core/dist/discovery.d.ts +129 -0
  83. package/dist/packages/core/dist/discovery.js +527 -0
  84. package/dist/packages/core/dist/discovery.js.map +1 -0
  85. package/dist/packages/core/dist/edge.d.ts +4 -0
  86. package/dist/packages/core/dist/edge.js +6 -0
  87. package/dist/packages/core/dist/edge.js.map +1 -0
  88. package/dist/packages/core/dist/index.d.ts +9 -0
  89. package/dist/packages/core/dist/index.js +10 -0
  90. package/dist/packages/core/dist/index.js.map +1 -0
  91. package/dist/packages/core/dist/receipts.d.ts +9 -0
  92. package/dist/packages/core/dist/receipts.js +67 -0
  93. package/dist/packages/core/dist/receipts.js.map +1 -0
  94. package/dist/packages/core/dist/relay-auth.d.ts +40 -0
  95. package/dist/packages/core/dist/relay-auth.js +106 -0
  96. package/dist/packages/core/dist/relay-auth.js.map +1 -0
  97. package/dist/packages/core/dist/revocation.d.ts +58 -0
  98. package/dist/packages/core/dist/revocation.js +112 -0
  99. package/dist/packages/core/dist/revocation.js.map +1 -0
  100. package/dist/packages/core/dist/schema.d.ts +11 -0
  101. package/dist/packages/core/dist/schema.js +48 -0
  102. package/dist/packages/core/dist/schema.js.map +1 -0
  103. package/dist/packages/core/dist/types.d.ts +172 -0
  104. package/dist/packages/core/dist/types.js +2 -0
  105. package/dist/packages/core/dist/types.js.map +1 -0
  106. package/dist/packages/ledger/dist/index.d.ts +84 -0
  107. package/dist/packages/ledger/dist/index.js +269 -0
  108. package/dist/packages/ledger/dist/index.js.map +1 -0
  109. package/dist/packages/relay/dist/fetch.d.ts +250 -0
  110. package/dist/packages/relay/dist/fetch.js +1401 -0
  111. package/dist/packages/relay/dist/fetch.js.map +1 -0
  112. package/dist/packages/relay/dist/index.d.ts +103 -0
  113. package/dist/packages/relay/dist/index.js +855 -0
  114. package/dist/packages/relay/dist/index.js.map +1 -0
  115. package/dist/packages/relay/dist/journal.d.ts +77 -0
  116. package/dist/packages/relay/dist/journal.js +339 -0
  117. package/dist/packages/relay/dist/journal.js.map +1 -0
  118. package/dist/packages/relay/dist/notifications.d.ts +63 -0
  119. package/dist/packages/relay/dist/notifications.js +55 -0
  120. package/dist/packages/relay/dist/notifications.js.map +1 -0
  121. package/dist/packages/relay/dist/retry.d.ts +12 -0
  122. package/dist/packages/relay/dist/retry.js +59 -0
  123. package/dist/packages/relay/dist/retry.js.map +1 -0
  124. package/dist/packages/relay/dist/ssrf.d.ts +32 -0
  125. package/dist/packages/relay/dist/ssrf.js +213 -0
  126. package/dist/packages/relay/dist/ssrf.js.map +1 -0
  127. package/dist/packages/relay/dist/worker.d.ts +92 -0
  128. package/dist/packages/relay/dist/worker.js +460 -0
  129. package/dist/packages/relay/dist/worker.js.map +1 -0
  130. package/dist/packages/runtime/dist/a2a.d.ts +8 -0
  131. package/dist/packages/runtime/dist/a2a.js +69 -0
  132. package/dist/packages/runtime/dist/a2a.js.map +1 -0
  133. package/dist/packages/runtime/dist/adapter.d.ts +51 -0
  134. package/dist/packages/runtime/dist/adapter.js +2 -0
  135. package/dist/packages/runtime/dist/adapter.js.map +1 -0
  136. package/dist/packages/runtime/dist/approval-providers.d.ts +99 -0
  137. package/dist/packages/runtime/dist/approval-providers.js +269 -0
  138. package/dist/packages/runtime/dist/approval-providers.js.map +1 -0
  139. package/dist/packages/runtime/dist/daily-limit.d.ts +2 -0
  140. package/dist/packages/runtime/dist/daily-limit.js +54 -0
  141. package/dist/packages/runtime/dist/daily-limit.js.map +1 -0
  142. package/dist/packages/runtime/dist/gateway.d.ts +35 -0
  143. package/dist/packages/runtime/dist/gateway.js +92 -0
  144. package/dist/packages/runtime/dist/gateway.js.map +1 -0
  145. package/dist/packages/runtime/dist/inbox.d.ts +10 -0
  146. package/dist/packages/runtime/dist/inbox.js +24 -0
  147. package/dist/packages/runtime/dist/inbox.js.map +1 -0
  148. package/dist/packages/runtime/dist/index.d.ts +13 -0
  149. package/dist/packages/runtime/dist/index.js +14 -0
  150. package/dist/packages/runtime/dist/index.js.map +1 -0
  151. package/dist/packages/runtime/dist/mcp-server.d.ts +90 -0
  152. package/dist/packages/runtime/dist/mcp-server.js +647 -0
  153. package/dist/packages/runtime/dist/mcp-server.js.map +1 -0
  154. package/dist/packages/runtime/dist/mcp-tool-catalog.d.ts +3 -0
  155. package/dist/packages/runtime/dist/mcp-tool-catalog.js +507 -0
  156. package/dist/packages/runtime/dist/mcp-tool-catalog.js.map +1 -0
  157. package/dist/packages/runtime/dist/mcp.d.ts +73 -0
  158. package/dist/packages/runtime/dist/mcp.js +67 -0
  159. package/dist/packages/runtime/dist/mcp.js.map +1 -0
  160. package/dist/packages/runtime/dist/policy.d.ts +19 -0
  161. package/dist/packages/runtime/dist/policy.js +41 -0
  162. package/dist/packages/runtime/dist/policy.js.map +1 -0
  163. package/dist/packages/runtime/dist/quota.d.ts +39 -0
  164. package/dist/packages/runtime/dist/quota.js +147 -0
  165. package/dist/packages/runtime/dist/quota.js.map +1 -0
  166. package/dist/packages/runtime/dist/session-audit.d.ts +107 -0
  167. package/dist/packages/runtime/dist/session-audit.js +520 -0
  168. package/dist/packages/runtime/dist/session-audit.js.map +1 -0
  169. package/dist/packages/runtime/dist/session-timeouts.d.ts +33 -0
  170. package/dist/packages/runtime/dist/session-timeouts.js +62 -0
  171. package/dist/packages/runtime/dist/session-timeouts.js.map +1 -0
  172. package/dist/packages/runtime/dist/session.d.ts +323 -0
  173. package/dist/packages/runtime/dist/session.js +2252 -0
  174. package/dist/packages/runtime/dist/session.js.map +1 -0
  175. package/dist/packages/runtime/dist/task-journal.d.ts +36 -0
  176. package/dist/packages/runtime/dist/task-journal.js +104 -0
  177. package/dist/packages/runtime/dist/task-journal.js.map +1 -0
  178. package/dist/packages/runtime/dist/verifier.d.ts +64 -0
  179. package/dist/packages/runtime/dist/verifier.js +109 -0
  180. package/dist/packages/runtime/dist/verifier.js.map +1 -0
  181. package/dist/packages/sandbox/dist/container.d.ts +33 -0
  182. package/dist/packages/sandbox/dist/container.js +189 -0
  183. package/dist/packages/sandbox/dist/container.js.map +1 -0
  184. package/dist/packages/sandbox/dist/index.d.ts +34 -0
  185. package/dist/packages/sandbox/dist/index.js +179 -0
  186. package/dist/packages/sandbox/dist/index.js.map +1 -0
  187. package/dist/packages/sandbox/dist/permission.d.ts +58 -0
  188. package/dist/packages/sandbox/dist/permission.js +90 -0
  189. package/dist/packages/sandbox/dist/permission.js.map +1 -0
  190. package/dist/spec/README.ja.md +76 -0
  191. package/dist/spec/README.md +135 -0
  192. package/dist/spec/ack-receipt.schema.json +77 -0
  193. package/dist/spec/agent-card.schema.json +83 -0
  194. package/dist/spec/approval-receipt.schema.json +94 -0
  195. package/dist/spec/audit-entry.schema.json +101 -0
  196. package/dist/spec/capability-token.schema.json +133 -0
  197. package/dist/spec/envelope.schema.json +197 -0
  198. package/dist/spec/examples/sample-ack-receipt.json +16 -0
  199. package/dist/spec/examples/sample-agent-card.json +35 -0
  200. package/dist/spec/examples/sample-approval-receipt.json +18 -0
  201. package/dist/spec/examples/sample-audit-entry.json +37 -0
  202. package/dist/spec/examples/sample-capability-token.json +39 -0
  203. package/dist/spec/examples/sample-envelope.json +21 -0
  204. package/dist/spec/examples/sample-task-manifest.json +141 -0
  205. package/dist/spec/examples/sample-usage-receipt.json +19 -0
  206. package/dist/spec/task-manifest.schema.json +422 -0
  207. package/dist/spec/usage-receipt.schema.json +91 -0
  208. package/package.json +61 -5
@@ -0,0 +1,12 @@
1
+ export declare class RelayTimeoutError extends Error {
2
+ readonly code = "ETIMEDOUT";
3
+ constructor();
4
+ }
5
+ export declare function isTransientRelayError(error: unknown): boolean;
6
+ export type RelayConnectionStatus = 'connected' | 'reconnecting' | 'unavailable' | 'stopped';
7
+ /** Never include an HTTP response body or arbitrary transport text in diagnostics. */
8
+ export declare function relayDiagnostic(error: unknown): Error;
9
+ export declare function relayRetryDelay(attempt: number): number;
10
+ export declare function waitForRelayRetry(ms: number, signal?: AbortSignal): Promise<void>;
11
+ /** Bound even injected transports/resolvers that do not honor cancellation. */
12
+ export declare function relayDeadline<T>(work: Promise<T>, ms: number, signal?: AbortSignal): Promise<T>;
@@ -0,0 +1,59 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ export class RelayTimeoutError extends Error {
3
+ code = 'ETIMEDOUT';
4
+ constructor() { super('RELAY_REQUEST_TIMEOUT'); this.name = 'RelayTimeoutError'; }
5
+ }
6
+ export function isTransientRelayError(error) {
7
+ const causes = [];
8
+ for (let current = error; current instanceof Error && !causes.includes(current) && causes.length < 16; current = current.cause)
9
+ causes.push(current);
10
+ if (causes.some(e => /^(?:RELAY_(?:REGISTRATION_)?REJECTED:\s*(?:401|403)\b|RELAY_TAMPERING_DETECTED)/.test(e.message)))
11
+ return false;
12
+ return causes.some(e => e.name === 'TimeoutError' ||
13
+ ['ETIMEDOUT', 'ECONNRESET', 'EAI_AGAIN', 'ECONNREFUSED', 'EPIPE', 'ENETUNREACH', 'EHOSTUNREACH']
14
+ .includes(e.code ?? '') ||
15
+ /^(?:SSE_CLOSED|RELAY_IDLE_TIMEOUT)$/.test(e.message) ||
16
+ (e instanceof TypeError && /^(?:fetch failed|terminated)$/.test(e.message)) ||
17
+ /^socket hang up$/i.test(e.message) ||
18
+ /^RELAY_(?:REGISTRATION_)?REJECTED:\s*(429|502|503|504)\b/.test(e.message));
19
+ }
20
+ /** Never include an HTTP response body or arbitrary transport text in diagnostics. */
21
+ export function relayDiagnostic(error) {
22
+ const message = error instanceof Error ? error.message : '';
23
+ const status = /^RELAY_(?:REGISTRATION_)?REJECTED:\s*(\d{3})\b/.exec(message)?.[1];
24
+ const code = /^(?:RELAY_[A-Z_]+|SSE_[A-Z_]+|SSRF_BLOCKED_RELAY_URL)$/.test(message)
25
+ ? message : 'RELAY_UNAVAILABLE';
26
+ return Object.assign(new Error(status ? 'RELAY_REJECTED: ' + status : code), { code: 'RELAY_TERMINAL', ...(status ? { status: Number(status) } : {}) });
27
+ }
28
+ export function relayRetryDelay(attempt) {
29
+ return Math.round(Math.min(30_000, 250 * 2 ** Math.min(attempt, 7)) * (0.5 + Math.random() * 0.5));
30
+ }
31
+ export function waitForRelayRetry(ms, signal) {
32
+ return new Promise((resolve, reject) => {
33
+ const abort = () => { clearTimeout(timer); reject(signal?.reason ?? new Error('SESSION_ABORTED')); };
34
+ const timer = setTimeout(() => { signal?.removeEventListener('abort', abort); resolve(); }, ms);
35
+ signal?.addEventListener('abort', abort, { once: true });
36
+ if (signal?.aborted)
37
+ abort();
38
+ });
39
+ }
40
+ /** Bound even injected transports/resolvers that do not honor cancellation. */
41
+ export async function relayDeadline(work, ms, signal) {
42
+ let timer;
43
+ let abort;
44
+ try {
45
+ return await Promise.race([work, new Promise((_, reject) => {
46
+ timer = setTimeout(() => reject(new RelayTimeoutError()), ms);
47
+ abort = () => reject(signal?.reason ?? new Error('SESSION_ABORTED'));
48
+ signal?.addEventListener('abort', abort, { once: true });
49
+ if (signal?.aborted)
50
+ abort();
51
+ })]);
52
+ }
53
+ finally {
54
+ clearTimeout(timer);
55
+ if (abort)
56
+ signal?.removeEventListener('abort', abort);
57
+ }
58
+ }
59
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { LookupFunction } from 'node:net';
2
+ import type { RelayEndpointPolicy } from '@acp/core';
3
+ export interface ResolvedAddress {
4
+ address: string;
5
+ family: 4 | 6;
6
+ }
7
+ /** Injectable DNS resolver. Tests pass a mock; production uses dns.lookup. */
8
+ export interface RelayLookup {
9
+ (hostname: string, options?: {
10
+ all?: boolean;
11
+ family?: number;
12
+ verbatim?: boolean;
13
+ }): Promise<ResolvedAddress[]>;
14
+ }
15
+ export interface RelayClientSecurityOptions extends RelayEndpointPolicy {
16
+ lookup?: RelayLookup;
17
+ requestTimeoutMs?: number;
18
+ socketTimeoutMs?: number;
19
+ }
20
+ export interface ResolvedRelayEndpoint {
21
+ url: URL;
22
+ addresses: ResolvedAddress[];
23
+ /** Returns only the addresses accepted before the socket is opened. */
24
+ lookup: LookupFunction;
25
+ }
26
+ /**
27
+ * Resolve every A/AAAA answer and reject the endpoint when any address is disallowed.
28
+ * Literal IP hosts skip DNS. The returned lookup never resolves again.
29
+ */
30
+ export declare function resolveAndValidateRelayEndpoint(value: string, options?: RelayClientSecurityOptions): Promise<ResolvedRelayEndpoint>;
31
+ /** Fetch that dials only the addresses accepted by resolveAndValidateRelayEndpoint. */
32
+ export declare function createPinnedRelayFetch(endpoint: string | ResolvedRelayEndpoint, options?: RelayClientSecurityOptions): typeof fetch;
@@ -0,0 +1,213 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { lookup as dnsLookup } from 'node:dns/promises';
3
+ import http from 'node:http';
4
+ import https from 'node:https';
5
+ import { Readable } from 'node:stream';
6
+ import { validateIpAddress, validateRelayEndpointUrl } from '../../core/dist/index.js';
7
+ import { RelayTimeoutError, relayDeadline, isTransientRelayError } from './retry.js';
8
+ async function systemLookup(hostname) {
9
+ const found = await dnsLookup(hostname, { all: true, verbatim: true });
10
+ return found.map((item) => ({
11
+ address: item.address,
12
+ family: item.family === 6 ? 6 : 4,
13
+ }));
14
+ }
15
+ function pinnedNodeLookup(addresses) {
16
+ const listed = addresses.map((item) => ({ address: item.address, family: item.family }));
17
+ const lookup = (_hostname, options, callback) => {
18
+ const family = options.family;
19
+ const selected = family === 4 || family === 6 ? listed.filter((item) => item.family === family) : listed;
20
+ const chosen = selected.length > 0 ? selected : listed;
21
+ if (chosen.length === 0) {
22
+ callback(Object.assign(new Error('SSRF_BLOCKED_RELAY_URL'), { code: 'ENOTFOUND' }), '', 4);
23
+ return;
24
+ }
25
+ if (options.all) {
26
+ callback(null, chosen);
27
+ return;
28
+ }
29
+ callback(null, chosen[0].address, chosen[0].family);
30
+ };
31
+ return lookup;
32
+ }
33
+ function literalAddress(hostname) {
34
+ if (hostname.includes(':'))
35
+ return { address: hostname, family: 6 };
36
+ if (/^(?:0|[1-9]\d{0,2})(?:\.(?:0|[1-9]\d{0,2})){3}$/.test(hostname))
37
+ return { address: hostname, family: 4 };
38
+ return undefined;
39
+ }
40
+ /**
41
+ * Resolve every A/AAAA answer and reject the endpoint when any address is disallowed.
42
+ * Literal IP hosts skip DNS. The returned lookup never resolves again.
43
+ */
44
+ export async function resolveAndValidateRelayEndpoint(value, options = {}) {
45
+ validateRelayEndpointUrl(value, { allowPrivateRelay: options.allowPrivateRelay });
46
+ const url = new URL(value);
47
+ const hostname = url.hostname.replace(/^\[|\]$/g, '').replace(/\.+$/, '').toLowerCase();
48
+ const literal = literalAddress(hostname);
49
+ let addresses;
50
+ if (literal) {
51
+ validateIpAddress(literal.address, { allowPrivateRelay: options.allowPrivateRelay });
52
+ addresses = [literal];
53
+ }
54
+ else {
55
+ let found;
56
+ try {
57
+ found = await relayDeadline((options.lookup ?? systemLookup)(hostname, { all: true, verbatim: true }), options.requestTimeoutMs ?? 45_000);
58
+ }
59
+ catch (error) {
60
+ if (isTransientRelayError(error))
61
+ throw error;
62
+ if (error instanceof Error && error.message === 'SSRF_BLOCKED_RELAY_URL')
63
+ throw error;
64
+ throw new Error('SSRF_BLOCKED_RELAY_URL');
65
+ }
66
+ if (!Array.isArray(found) || found.length === 0)
67
+ throw new Error('SSRF_BLOCKED_RELAY_URL');
68
+ addresses = found.map((item) => ({
69
+ address: item.address,
70
+ family: item.family === 6 ? 6 : 4,
71
+ }));
72
+ for (const item of addresses)
73
+ validateIpAddress(item.address, { allowPrivateRelay: options.allowPrivateRelay });
74
+ }
75
+ return { url, addresses, lookup: pinnedNodeLookup(addresses) };
76
+ }
77
+ function requestUrl(input) {
78
+ if (typeof input === 'string')
79
+ return new URL(input);
80
+ if (input instanceof URL)
81
+ return new URL(input.href);
82
+ return new URL(input.url);
83
+ }
84
+ function headerRecord(headers) {
85
+ const out = {};
86
+ new Headers(headers).forEach((value, key) => {
87
+ if (key === 'host')
88
+ return;
89
+ out[key] = value;
90
+ });
91
+ return out;
92
+ }
93
+ function abortError(signal) {
94
+ if (signal.reason instanceof Error)
95
+ return signal.reason;
96
+ return Object.assign(new Error('ABORT'), { name: 'AbortError' });
97
+ }
98
+ function sameOrigin(target, endpoint) {
99
+ return (target.protocol === endpoint.protocol &&
100
+ target.hostname === endpoint.hostname &&
101
+ target.port === endpoint.port);
102
+ }
103
+ async function pinnedRequest(pin, input, init, options = {}) {
104
+ const target = requestUrl(input);
105
+ if (!sameOrigin(target, pin.url))
106
+ throw new Error('SSRF_BLOCKED_RELAY_URL');
107
+ const secure = target.protocol === 'https:';
108
+ if (target.protocol !== 'http:' && target.protocol !== 'https:')
109
+ throw new Error('SSRF_BLOCKED_RELAY_URL');
110
+ const hostname = target.hostname.replace(/^\[|\]$/g, '');
111
+ const lib = secure ? https : http;
112
+ const signal = init?.signal ?? undefined;
113
+ return new Promise((resolve, reject) => {
114
+ let response;
115
+ const req = lib.request({
116
+ protocol: target.protocol,
117
+ hostname,
118
+ port: target.port === '' ? undefined : Number(target.port),
119
+ method: init?.method ?? (input instanceof Request ? input.method : 'GET'),
120
+ path: target.pathname + target.search,
121
+ headers: headerRecord(init?.headers),
122
+ lookup: pin.lookup,
123
+ agent: false,
124
+ ...(secure ? { servername: hostname } : {}),
125
+ }, (incoming) => {
126
+ response = incoming;
127
+ // SSE is intentionally long-lived; retain its idle timeout after headers arrive.
128
+ if (target.pathname.endsWith('/stream') && incoming.headers['content-type']?.startsWith('text/event-stream'))
129
+ clearTimeout(deadline);
130
+ const headers = new Headers();
131
+ for (const [key, value] of Object.entries(incoming.headers)) {
132
+ if (value === undefined)
133
+ continue;
134
+ if (key === 'transfer-encoding' || key === 'content-length')
135
+ continue;
136
+ if (Array.isArray(value))
137
+ for (const item of value)
138
+ headers.append(key, item);
139
+ else
140
+ headers.set(key, value);
141
+ }
142
+ const status = incoming.statusCode ?? 0;
143
+ // 204/205/304 cannot carry a body. A stream argument makes Response throw.
144
+ const nullBody = status === 101 || status === 204 || status === 205 || status === 304;
145
+ if (nullBody)
146
+ incoming.resume();
147
+ const body = nullBody
148
+ ? null
149
+ : Readable.toWeb(incoming);
150
+ try {
151
+ resolve(new Response(body, {
152
+ status,
153
+ statusText: incoming.statusMessage,
154
+ headers,
155
+ }));
156
+ }
157
+ catch (error) {
158
+ incoming.destroy();
159
+ reject(error instanceof Error ? error : new Error(String(error)));
160
+ }
161
+ });
162
+ const fail = (error) => {
163
+ if (signal?.aborted)
164
+ reject(abortError(signal));
165
+ else
166
+ reject(error);
167
+ };
168
+ req.on('error', fail);
169
+ const timeout = () => {
170
+ const error = new RelayTimeoutError();
171
+ response?.destroy(error);
172
+ req.destroy(error);
173
+ };
174
+ const deadline = setTimeout(timeout, options.requestTimeoutMs ?? 45_000);
175
+ req.setTimeout(options.socketTimeoutMs ?? 35_000, timeout);
176
+ req.once('close', () => clearTimeout(deadline));
177
+ if (signal) {
178
+ const onAbort = () => req.destroy(abortError(signal));
179
+ if (signal.aborted) {
180
+ req.destroy();
181
+ reject(abortError(signal));
182
+ return;
183
+ }
184
+ signal.addEventListener('abort', onAbort, { once: true });
185
+ req.on('close', () => signal.removeEventListener('abort', onAbort));
186
+ }
187
+ const body = init?.body ?? null;
188
+ if (body == null)
189
+ req.end();
190
+ else if (typeof body === 'string' || body instanceof Uint8Array)
191
+ req.end(body);
192
+ else if (body instanceof URLSearchParams)
193
+ req.end(body.toString());
194
+ else
195
+ req.destroy(new Error('UNSUPPORTED_BODY'));
196
+ });
197
+ }
198
+ /** Fetch that dials only the addresses accepted by resolveAndValidateRelayEndpoint. */
199
+ export function createPinnedRelayFetch(endpoint, options = {}) {
200
+ let pending;
201
+ const resolve = () => {
202
+ if (typeof endpoint !== 'string')
203
+ return Promise.resolve(endpoint);
204
+ pending ??= resolveAndValidateRelayEndpoint(endpoint, options).catch((error) => {
205
+ if (isTransientRelayError(error))
206
+ pending = undefined;
207
+ throw error;
208
+ });
209
+ return pending;
210
+ };
211
+ return (async (input, init) => pinnedRequest(await resolve(), input, init, options));
212
+ }
213
+ //# sourceMappingURL=ssrf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssrf.js","sourceRoot":"","sources":["../src/ssrf.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ interface DurableStorage {
2
+ get<T>(key: string): Promise<T | undefined>;
3
+ put(key: string, value: unknown): Promise<void>;
4
+ delete?(key: string): Promise<unknown>;
5
+ setAlarm?(scheduledTime: number | Date): Promise<void>;
6
+ deleteAlarm?(): Promise<void>;
7
+ }
8
+ interface DurableState {
9
+ storage: DurableStorage;
10
+ waitUntil?(promise: Promise<unknown>): void;
11
+ blockConcurrencyWhile<T>(callback: () => Promise<T>): Promise<T>;
12
+ }
13
+ /**
14
+ * One inbox or the registry. Storage is granular: a POST writes the new
15
+ * envelope, its seen-id slot, and the fixed-size meta record. Write cost does
16
+ * not grow with the number of queued envelopes or registered agents.
17
+ */
18
+ export declare class RelayDurableObject {
19
+ private state;
20
+ private relay;
21
+ private handler;
22
+ private ready;
23
+ /** Serializes handler mutation, snapshot write, and rollback for every request. */
24
+ private turn;
25
+ private persistedVersion;
26
+ private notifications?;
27
+ private notificationKey;
28
+ private configuredNotificationKey?;
29
+ private committedSnapshot;
30
+ private cursor;
31
+ constructor(state: DurableState, env?: Record<string, unknown>);
32
+ private bootstrap;
33
+ /** Rewrite a pre-sharding blob into per-key records once, then drop the blob. */
34
+ private migrateLegacy;
35
+ /** Queue one turn. A rejection stays on that turn and does not poison the next one. */
36
+ private enqueue;
37
+ /**
38
+ * Persist the current relay. Caller must already hold the request turn.
39
+ * A single POST /envelopes or DELETE /envelopes/:id commits a constant
40
+ * number of keys (the touched envelope, its replay slot, and `meta`).
41
+ * The fixed-size `meta` record is independent of inbox and registry length.
42
+ */
43
+ private writeSnapshot;
44
+ private commitPlan;
45
+ private bestEffortAlarm;
46
+ /** Later SSE pulls persist after the request turn has released this lock. */
47
+ private persist;
48
+ /** Claims and completions are serialized; external notification delivery never holds the inbox turn. */
49
+ private runNotifications;
50
+ private scheduleNotifications;
51
+ alarm(): Promise<void>;
52
+ fetch(request: Request): Promise<Response>;
53
+ /** Positive waitMs on GET /envelopes. Invalid values stay on the normal handler path. */
54
+ private longPollWait;
55
+ private emptyPoll;
56
+ /**
57
+ * Authenticate and pop inside the mutation turn, then release that turn while
58
+ * relay.wait is pending so a POST can wake the poll.
59
+ */
60
+ private handleLongPoll;
61
+ private openLongPoll;
62
+ private finishLongPoll;
63
+ private handle;
64
+ }
65
+ export declare const DEFAULT_RATE_LIMIT_MAX = 300;
66
+ export declare const DEFAULT_RATE_LIMIT_WINDOW_MS = 60000;
67
+ interface RelayNamespace {
68
+ idFromName(name: string): unknown;
69
+ get(id: unknown): {
70
+ fetch(request: Request): Promise<Response>;
71
+ };
72
+ }
73
+ export interface RelayEdgeEnv {
74
+ RELAY?: RelayNamespace;
75
+ RATE_LIMITER?: {
76
+ limit(options: {
77
+ key: string;
78
+ }): Promise<{
79
+ success: boolean;
80
+ }>;
81
+ };
82
+ [key: string]: unknown;
83
+ }
84
+ /** Test hook. Production isolates keep this map for the life of the isolate. */
85
+ export declare function resetRelayRateLimits(): void;
86
+ /** CF-Connecting-IP wins. X-Forwarded-For is only a fallback for local tests. */
87
+ export declare function clientIp(request: Request): string;
88
+ export declare function handleRelayEdge(request: Request, env?: RelayEdgeEnv): Promise<Response>;
89
+ declare const _default: {
90
+ fetch(request: Request, env?: RelayEdgeEnv): Promise<Response>;
91
+ };
92
+ export default _default;