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,67 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { randomUUID } from 'node:crypto';
3
+ import { digest, encryptEnvelopePayload, signPayload, verifySigned } from './crypto.js';
4
+ import { validateSchema } from './schema.js';
5
+ export function signApproval(taskId, gate, target, key, decision = 'APPROVED') {
6
+ return signPayload({
7
+ type: 'ApprovalReceipt',
8
+ receiptId: randomUUID(),
9
+ taskId,
10
+ gate,
11
+ targetDigest: digest(target),
12
+ decision,
13
+ approvedAt: new Date().toISOString(),
14
+ }, key);
15
+ }
16
+ export function verifyApproval(receipt, ownerDid, taskId, gate, target) {
17
+ try {
18
+ validateSchema('approval-receipt', receipt);
19
+ const p = receipt.payload;
20
+ return (verifySigned(receipt, ownerDid) &&
21
+ p.taskId === taskId &&
22
+ p.gate === gate &&
23
+ p.targetDigest === digest(target) &&
24
+ p.decision === 'APPROVED');
25
+ }
26
+ catch {
27
+ return false;
28
+ }
29
+ }
30
+ export function signUsage(payload, key) {
31
+ const r = signPayload(payload, key);
32
+ validateSchema('usage-receipt', r);
33
+ return r;
34
+ }
35
+ export function signAck(payload, key) {
36
+ if (payload.receiverDid !== key.did)
37
+ throw new Error('ACK_RECEIVER');
38
+ return signPayload(payload, key);
39
+ }
40
+ export function signEnvelope(payload, key, options) {
41
+ const envelope = {
42
+ ...payload,
43
+ type: 'SignedEnvelope',
44
+ envelopeId: randomUUID(),
45
+ senderDid: key.did,
46
+ };
47
+ if (options?.encrypt)
48
+ envelope.payload = encryptEnvelopePayload(envelope.payload, {
49
+ taskId: envelope.taskId,
50
+ seq: envelope.seq,
51
+ eventType: envelope.eventType,
52
+ senderDid: envelope.senderDid,
53
+ recipientDid: envelope.recipientDid,
54
+ });
55
+ return signPayload(envelope, key);
56
+ }
57
+ export function verifyEnvelope(envelope, recipientDid) {
58
+ try {
59
+ validateSchema('envelope', envelope);
60
+ return (verifySigned(envelope, envelope.payload.senderDid) &&
61
+ (!recipientDid || envelope.payload.recipientDid === recipientDid));
62
+ }
63
+ catch {
64
+ return false;
65
+ }
66
+ }
67
+ //# sourceMappingURL=receipts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"receipts.js","sourceRoot":"","sources":["../src/receipts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { KeyPair } from './types.js';
2
+ export type RelayAuthAction = 'receive' | 'stream' | 'subscribe';
3
+ export interface RelayAuthPayload {
4
+ type: 'RelayAuth';
5
+ recipientDid: string;
6
+ action: RelayAuthAction;
7
+ timestamp: string;
8
+ nonce: string;
9
+ /** Canonical destination origin. `ws:`/`wss:` are stored as `http:`/`https:`. */
10
+ origin?: string;
11
+ }
12
+ export interface CreateRelayAuthOptions {
13
+ action?: RelayAuthAction;
14
+ now?: string;
15
+ nonce?: string;
16
+ /** Destination relay URL or origin. Normalized before it is signed. */
17
+ origin?: string;
18
+ /** Alias of `origin` for callers that have a relay URL. */
19
+ relayUrl?: string;
20
+ }
21
+ export interface VerifyRelayAuthOptions {
22
+ now?: number;
23
+ maxSkewMs?: number;
24
+ expectedOrigin?: string;
25
+ requireOrigin?: boolean;
26
+ }
27
+ export interface RelayAuthVerification {
28
+ valid: boolean;
29
+ nonce?: string;
30
+ action?: RelayAuthAction;
31
+ error?: string;
32
+ reason?: string;
33
+ }
34
+ /**
35
+ * Canonical origin for HTTP, SSE, and WebSocket on the same host:port.
36
+ * `ws:` becomes `http:` and `wss:` becomes `https:` before `origin` is taken.
37
+ */
38
+ export declare function normalizeRelayOrigin(urlOrOrigin: string): string;
39
+ export declare function createRelayAuthToken(recipient: KeyPair, options?: CreateRelayAuthOptions): string;
40
+ export declare function verifyRelayAuthToken(token: string, expectedRecipientDid: string, options?: VerifyRelayAuthOptions): RelayAuthVerification;
@@ -0,0 +1,106 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { randomUUID } from 'node:crypto';
3
+ import { signPayload, verifySigned } from './crypto.js';
4
+ const RELAY_AUTH_ACTIONS = new Set(['receive', 'stream', 'subscribe']);
5
+ /**
6
+ * Canonical origin for HTTP, SSE, and WebSocket on the same host:port.
7
+ * `ws:` becomes `http:` and `wss:` becomes `https:` before `origin` is taken.
8
+ */
9
+ export function normalizeRelayOrigin(urlOrOrigin) {
10
+ if (typeof urlOrOrigin !== 'string' || !urlOrOrigin.trim())
11
+ throw new Error('INVALID_RELAY_ORIGIN');
12
+ let url;
13
+ try {
14
+ url = new URL(urlOrOrigin.trim());
15
+ }
16
+ catch {
17
+ throw new Error('INVALID_RELAY_ORIGIN');
18
+ }
19
+ if (url.protocol === 'ws:')
20
+ url.protocol = 'http:';
21
+ else if (url.protocol === 'wss:')
22
+ url.protocol = 'https:';
23
+ else if (url.protocol !== 'http:' && url.protocol !== 'https:')
24
+ throw new Error('INVALID_RELAY_ORIGIN');
25
+ if (!url.host || url.origin === 'null')
26
+ throw new Error('INVALID_RELAY_ORIGIN');
27
+ return url.origin.toLowerCase();
28
+ }
29
+ export function createRelayAuthToken(recipient, options = {}) {
30
+ const rawOrigin = options.origin ?? options.relayUrl;
31
+ const payload = {
32
+ type: 'RelayAuth',
33
+ recipientDid: recipient.did,
34
+ action: options.action ?? 'receive',
35
+ timestamp: options.now ?? new Date().toISOString(),
36
+ nonce: options.nonce ?? randomUUID(),
37
+ ...(rawOrigin !== undefined ? { origin: normalizeRelayOrigin(rawOrigin) } : {}),
38
+ };
39
+ return Buffer.from(JSON.stringify(signPayload(payload, recipient))).toString('base64url');
40
+ }
41
+ function originFailure(code) {
42
+ return { valid: false, error: code, reason: code };
43
+ }
44
+ function checkRelayAuthOrigin(origin, options) {
45
+ const hasOrigin = typeof origin === 'string' && origin.trim().length > 0;
46
+ if (origin !== undefined && !hasOrigin) {
47
+ if (options.expectedOrigin !== undefined)
48
+ return originFailure('RELAY_AUTH_ORIGIN_MISMATCH');
49
+ if (options.requireOrigin)
50
+ return originFailure('RELAY_AUTH_ORIGIN_REQUIRED');
51
+ return { valid: false, error: 'RELAY_UNAUTHORIZED' };
52
+ }
53
+ if (!hasOrigin) {
54
+ if (options.requireOrigin)
55
+ return originFailure('RELAY_AUTH_ORIGIN_REQUIRED');
56
+ return undefined;
57
+ }
58
+ let canonical;
59
+ try {
60
+ canonical = normalizeRelayOrigin(origin);
61
+ }
62
+ catch {
63
+ if (options.expectedOrigin !== undefined)
64
+ return originFailure('RELAY_AUTH_ORIGIN_MISMATCH');
65
+ return { valid: false, error: 'RELAY_UNAUTHORIZED' };
66
+ }
67
+ if (options.expectedOrigin === undefined)
68
+ return undefined;
69
+ try {
70
+ if (canonical !== normalizeRelayOrigin(options.expectedOrigin))
71
+ return originFailure('RELAY_AUTH_ORIGIN_MISMATCH');
72
+ }
73
+ catch {
74
+ return originFailure('RELAY_AUTH_ORIGIN_MISMATCH');
75
+ }
76
+ return undefined;
77
+ }
78
+ export function verifyRelayAuthToken(token, expectedRecipientDid, options = {}) {
79
+ try {
80
+ if (typeof token !== 'string' || token.length > 16384 || !/^[A-Za-z0-9_-]+$/.test(token))
81
+ throw new Error();
82
+ const signed = JSON.parse(Buffer.from(token, 'base64url').toString('utf8')), p = signed.payload;
83
+ const now = options.now ?? Date.now(), skew = options.maxSkewMs ?? 300000;
84
+ if (!verifySigned(signed, expectedRecipientDid) ||
85
+ p.type !== 'RelayAuth' ||
86
+ p.recipientDid !== expectedRecipientDid ||
87
+ !RELAY_AUTH_ACTIONS.has(p.action) ||
88
+ typeof p.nonce !== 'string' ||
89
+ !p.nonce.trim() ||
90
+ typeof p.timestamp !== 'string' ||
91
+ !Number.isFinite(Date.parse(p.timestamp)) ||
92
+ !Number.isFinite(now) ||
93
+ !Number.isFinite(skew) ||
94
+ skew < 0 ||
95
+ Math.abs(now - Date.parse(p.timestamp)) > skew)
96
+ throw new Error();
97
+ const origin = checkRelayAuthOrigin(p.origin, options);
98
+ if (origin)
99
+ return origin;
100
+ return { valid: true, nonce: p.nonce, action: p.action };
101
+ }
102
+ catch {
103
+ return { valid: false, error: 'RELAY_UNAUTHORIZED' };
104
+ }
105
+ }
106
+ //# sourceMappingURL=relay-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relay-auth.js","sourceRoot":"","sources":["../src/relay-auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import type { KeyPair, Signed } from './types.js';
2
+ export interface RevocationNotice {
3
+ type: 'RevocationNotice';
4
+ revocationId: string;
5
+ issuerDid: string;
6
+ targetType: 'invite' | 'capability';
7
+ targetId: string;
8
+ reason: string;
9
+ revokedAt: string;
10
+ }
11
+ export type SignedRevocationNotice = Signed<RevocationNotice>;
12
+ /** Structural view so callers can pass a registry built from another compilation of this package. */
13
+ export interface RevocationList {
14
+ isRevoked(targetType: 'invite' | 'capability', targetId: string): boolean;
15
+ assertNotRevoked(targetType: 'invite' | 'capability', targetId: string): void;
16
+ /**
17
+ * Signature-checked notices for this target.
18
+ * A capability notice applies only when its issuer issued that token or an
19
+ * ancestor in the verified chain being evaluated. Another issuer's notice
20
+ * for the same target id must not revoke that chain.
21
+ */
22
+ noticesFor?(targetType: 'invite' | 'capability', targetId: string): SignedRevocationNotice[];
23
+ /**
24
+ * True when `isRevoked` is set by a source that cannot list notice issuers.
25
+ * A listed notice from a different issuer is not unexplained.
26
+ */
27
+ unexplainedRevocation?(targetType: 'invite' | 'capability', targetId: string): boolean;
28
+ }
29
+ /** Stable invite target id: JCS SHA-256 of the verified payload, including expired invites. */
30
+ export declare function inviteRevocationId(token: string, options?: {
31
+ allowPrivateRelay?: boolean;
32
+ }): string;
33
+ export declare function createRevocationNotice(input: {
34
+ targetType: 'invite' | 'capability';
35
+ targetId: string;
36
+ reason: string;
37
+ revokedAt?: string;
38
+ }, issuer: KeyPair): SignedRevocationNotice;
39
+ /** Ed25519 over RFC 8785 JCS. A notice signed by someone other than issuerDid is rejected. */
40
+ export declare function verifyRevocationNotice(notice: SignedRevocationNotice, expectedIssuer?: string): boolean;
41
+ /**
42
+ * In-memory, serializable set of verified revocation notices.
43
+ * Invite lookup keys are derived from verified payloads and bound to their owner.
44
+ * Signed notices remain unchanged; imports rebuild the derived lookup keys.
45
+ * Capability notices are kept per issuer. A second issuer revoking the same
46
+ * target id must not replace the first: chain checks match the notice issuer
47
+ * to the verified token, and a colliding id is not a global kill switch.
48
+ */
49
+ export declare class RevocationRegistry {
50
+ private readonly notices;
51
+ revoke(notice: SignedRevocationNotice, expectedIssuer?: string): void;
52
+ isRevoked(targetType: 'invite' | 'capability', targetId: string): boolean;
53
+ noticesFor(targetType: 'invite' | 'capability', targetId: string): SignedRevocationNotice[];
54
+ assertNotRevoked(targetType: 'invite' | 'capability', targetId: string): void;
55
+ exportNotices(): SignedRevocationNotice[];
56
+ importNotices(notices: SignedRevocationNotice[]): void;
57
+ private lookupKey;
58
+ }
@@ -0,0 +1,112 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { randomUUID } from 'node:crypto';
3
+ import { digest, signPayload, verifySigned } from './crypto.js';
4
+ import { parseAndVerifyInviteToken } from './discovery.js';
5
+ function verifiedInvite(token, options = {}) {
6
+ const uri = /^[\w-]+$/.test(token) ? 'acp-invite:' + token : token;
7
+ return parseAndVerifyInviteToken(uri, Date.now(), { ...options, allowExpired: true });
8
+ }
9
+ /** Stable invite target id: JCS SHA-256 of the verified payload, including expired invites. */
10
+ export function inviteRevocationId(token, options = {}) {
11
+ return digest(verifiedInvite(token, options));
12
+ }
13
+ function inviteTargetId(targetId, issuerDid) {
14
+ let invite;
15
+ try {
16
+ // Lookup is local and does not dial the invite's relay.
17
+ invite = verifiedInvite(targetId, { allowPrivateRelay: true });
18
+ }
19
+ catch {
20
+ // Opaque ids and unverifiable invite targets retain exact-string lookup.
21
+ return targetId;
22
+ }
23
+ if (issuerDid && invite.ownerDid !== issuerDid)
24
+ throw new Error('INVALID_REVOCATION_ISSUER');
25
+ return digest(invite);
26
+ }
27
+ export function createRevocationNotice(input, issuer) {
28
+ if (input.targetType !== 'invite' && input.targetType !== 'capability')
29
+ throw new Error('INVALID_REVOCATION');
30
+ if (!input.targetId || !input.reason)
31
+ throw new Error('INVALID_REVOCATION');
32
+ const revokedAt = input.revokedAt ?? new Date().toISOString();
33
+ if (!Number.isFinite(Date.parse(revokedAt)))
34
+ throw new Error('INVALID_REVOCATION');
35
+ return signPayload({
36
+ type: 'RevocationNotice',
37
+ revocationId: randomUUID(),
38
+ issuerDid: issuer.did,
39
+ targetType: input.targetType,
40
+ targetId: input.targetId,
41
+ reason: input.reason,
42
+ revokedAt,
43
+ }, issuer);
44
+ }
45
+ /** Ed25519 over RFC 8785 JCS. A notice signed by someone other than issuerDid is rejected. */
46
+ export function verifyRevocationNotice(notice, expectedIssuer) {
47
+ try {
48
+ const payload = notice.payload;
49
+ return (verifySigned(notice, payload.issuerDid) &&
50
+ (!expectedIssuer || payload.issuerDid === expectedIssuer) &&
51
+ payload.type === 'RevocationNotice' &&
52
+ (payload.targetType === 'invite' || payload.targetType === 'capability') &&
53
+ typeof payload.revocationId === 'string' &&
54
+ payload.revocationId.length > 0 &&
55
+ typeof payload.targetId === 'string' &&
56
+ payload.targetId.length > 0 &&
57
+ typeof payload.reason === 'string' &&
58
+ payload.reason.length > 0 &&
59
+ Number.isFinite(Date.parse(payload.revokedAt)) &&
60
+ notice.signature.signerDid === payload.issuerDid);
61
+ }
62
+ catch {
63
+ return false;
64
+ }
65
+ }
66
+ function registryKey(targetType, targetId) {
67
+ return targetType + '\0' + targetId;
68
+ }
69
+ /**
70
+ * In-memory, serializable set of verified revocation notices.
71
+ * Invite lookup keys are derived from verified payloads and bound to their owner.
72
+ * Signed notices remain unchanged; imports rebuild the derived lookup keys.
73
+ * Capability notices are kept per issuer. A second issuer revoking the same
74
+ * target id must not replace the first: chain checks match the notice issuer
75
+ * to the verified token, and a colliding id is not a global kill switch.
76
+ */
77
+ export class RevocationRegistry {
78
+ notices = new Map();
79
+ revoke(notice, expectedIssuer) {
80
+ if (!verifyRevocationNotice(notice, expectedIssuer))
81
+ throw new Error('INVALID_REVOCATION');
82
+ const { targetType, targetId, issuerDid } = notice.payload;
83
+ const key = registryKey(targetType, targetType === 'invite' ? inviteTargetId(targetId, issuerDid) : targetId);
84
+ const list = this.notices.get(key) ?? [];
85
+ const duplicate = list.some((existing) => existing.payload.issuerDid === notice.payload.issuerDid &&
86
+ existing.payload.revocationId === notice.payload.revocationId);
87
+ if (!duplicate)
88
+ list.push(structuredClone(notice));
89
+ this.notices.set(key, list);
90
+ }
91
+ isRevoked(targetType, targetId) {
92
+ return (this.notices.get(this.lookupKey(targetType, targetId))?.length ?? 0) > 0;
93
+ }
94
+ noticesFor(targetType, targetId) {
95
+ return (this.notices.get(this.lookupKey(targetType, targetId)) ?? []).map((notice) => structuredClone(notice));
96
+ }
97
+ assertNotRevoked(targetType, targetId) {
98
+ if (this.isRevoked(targetType, targetId))
99
+ throw new Error('TOKEN_REVOKED');
100
+ }
101
+ exportNotices() {
102
+ return [...this.notices.values()].flat().map((notice) => structuredClone(notice));
103
+ }
104
+ importNotices(notices) {
105
+ for (const notice of notices)
106
+ this.revoke(notice);
107
+ }
108
+ lookupKey(targetType, targetId) {
109
+ return registryKey(targetType, targetType === 'invite' ? inviteTargetId(targetId) : targetId);
110
+ }
111
+ }
112
+ //# sourceMappingURL=revocation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revocation.js","sourceRoot":"","sources":["../src/revocation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { Ajv2020 } from 'ajv/dist/2020.js';
2
+ import type { TaskManifest, Schema } from './types.js';
3
+ export declare function createAjv(): Ajv2020;
4
+ export declare const specDirectory: URL;
5
+ export declare function loadSchema(name: string): Schema;
6
+ /** Spec files are static. Rebuilding Ajv for every envelope check dominates a session. */
7
+ export declare function schemaRegistry(): Ajv2020;
8
+ export declare function validateSchema(name: string, value: unknown): void;
9
+ export declare function validateManifest(value: unknown): asserts value is TaskManifest;
10
+ export declare function assertSynchronousSchema(schema: unknown): void;
11
+ export declare function validateOutput(schema: Schema, value: unknown): boolean;
@@ -0,0 +1,48 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { readFileSync, readdirSync } from 'node:fs';
3
+ import { Ajv2020 } from 'ajv/dist/2020.js';
4
+ import formats from 'ajv-formats';
5
+ export function createAjv() {
6
+ const ajv = new Ajv2020({ allErrors: true, strict: false, validateFormats: true });
7
+ formats(ajv);
8
+ return ajv;
9
+ }
10
+ export const specDirectory = new URL('../../../spec/', import.meta.url);
11
+ export function loadSchema(name) {
12
+ if (!/^[a-z-]+$/.test(name))
13
+ throw new Error('INVALID_SCHEMA_NAME');
14
+ return JSON.parse(readFileSync(new URL(name + '.schema.json', specDirectory), 'utf8'));
15
+ }
16
+ let cachedRegistry;
17
+ /** Spec files are static. Rebuilding Ajv for every envelope check dominates a session. */
18
+ export function schemaRegistry() {
19
+ if (cachedRegistry)
20
+ return cachedRegistry;
21
+ const ajv = createAjv();
22
+ for (const f of readdirSync(specDirectory).filter((f) => f.endsWith('.schema.json')))
23
+ ajv.addSchema(loadSchema(f.slice(0, -12)), f.slice(0, -12));
24
+ cachedRegistry = ajv;
25
+ return ajv;
26
+ }
27
+ export function validateSchema(name, value) {
28
+ const ajv = schemaRegistry();
29
+ const validate = ajv.getSchema(name);
30
+ if (!validate(value))
31
+ throw new Error('SCHEMA_VIOLATION: ' + ajv.errorsText(validate.errors));
32
+ }
33
+ export function validateManifest(value) {
34
+ validateSchema('task-manifest', value);
35
+ }
36
+ export function assertSynchronousSchema(schema) {
37
+ if (!schema || typeof schema !== 'object')
38
+ return;
39
+ if (Object.hasOwn(schema, '$async'))
40
+ throw new Error('ASYNC_SCHEMA_FORBIDDEN');
41
+ for (const value of Object.values(schema))
42
+ assertSynchronousSchema(value);
43
+ }
44
+ export function validateOutput(schema, value) {
45
+ assertSynchronousSchema(schema);
46
+ return createAjv().compile(schema)(value) === true;
47
+ }
48
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,OAAO,MAAM,aAAa,CAAC;AAElC,MAAM,UAAU,SAAS;IACvB,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;IAClF,OAA2C,CAAC,GAAG,CAAC,CAAC;IAClD,OAAO,GAAG,CAAC;AACb,CAAC;AACD,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACxE,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACpE,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,IAAI,GAAG,cAAc,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAW,CAAC;AACnG,CAAC;AACD,IAAI,cAAwD,CAAC;AAC7D,0FAA0F;AAC1F,MAAM,UAAU,cAAc;IAC5B,IAAI,cAAc;QAAE,OAAO,cAAc,CAAC;IAC1C,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,KAAK,MAAM,CAAC,IAAI,WAAW,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;QAClF,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9D,cAAc,GAAG,GAAG,CAAC;IACrB,OAAO,GAAG,CAAC;AACb,CAAC;AACD,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,KAAc;IACzD,MAAM,GAAG,GAAG,cAAc,EAAE,CAAC;IAC7B,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,CAAC,IAAI,CAAE,CAAC;IACtC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,GAAG,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAChG,CAAC;AACD,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,cAAc,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;AACzC,CAAC;AACD,MAAM,UAAU,uBAAuB,CAAC,MAAe;IACrD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO;IAClD,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC/E,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;QAAE,uBAAuB,CAAC,KAAK,CAAC,CAAC;AAC5E,CAAC;AACD,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,KAAc;IAC3D,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChC,OAAO,SAAS,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;AACrD,CAAC"}
@@ -0,0 +1,172 @@
1
+ export type Json = null | boolean | number | string | Json[] | {
2
+ [key: string]: Json;
3
+ };
4
+ export type Schema = Record<string, unknown>;
5
+ export interface KeyPair {
6
+ did: string;
7
+ privateKey: string;
8
+ }
9
+ export interface Signature {
10
+ signerDid: string;
11
+ canonicalization: 'RFC8785-JCS';
12
+ payloadDigest: string;
13
+ signedAt: string;
14
+ signature: string;
15
+ }
16
+ export interface Signed<T> {
17
+ payload: T;
18
+ signature: Signature;
19
+ }
20
+ export type Gate = 'contract_acceptance' | 'external_side_effect' | 'budget_increase' | 'redelegation' | 'final_verification';
21
+ export interface Approval {
22
+ type: 'ApprovalReceipt';
23
+ receiptId: string;
24
+ taskId: string;
25
+ gate: Gate;
26
+ targetDigest: string;
27
+ decision: 'APPROVED' | 'REJECTED';
28
+ approvedAt: string;
29
+ }
30
+ export type ApprovalReceipt = Signed<Approval>;
31
+ export interface Usage {
32
+ type: 'UsageReceipt';
33
+ taskId: string;
34
+ inputTokens: number;
35
+ outputTokens: number;
36
+ totalTokens: number;
37
+ toolCalls: number;
38
+ wallTimeMs: number;
39
+ halted: boolean;
40
+ }
41
+ export type UsageReceipt = Signed<Usage>;
42
+ export interface Ack {
43
+ type: 'AckReceipt';
44
+ taskId: string;
45
+ entryHash: string;
46
+ actorDid: string;
47
+ receiverDid: string;
48
+ }
49
+ export type AckReceipt = Signed<Ack>;
50
+ /** Ciphertext wrapper stored in `envelope.payload.payload`. The relay never receives the plaintext. */
51
+ export type EncryptedEnvelopePayload = {
52
+ __acpEncrypted: 'X25519-HKDF-AES256GCM';
53
+ /** Ephemeral X25519 SPKI DER, or the raw 32-byte public key, base64url. */
54
+ ephemeralPublicKey: string;
55
+ /**
56
+ * 12-byte AES-GCM nonce, base64url. Also the HKDF salt.
57
+ * HKDF info binds the canonical header plus the ephemeral and recipient X25519 public keys.
58
+ */
59
+ iv: string;
60
+ ciphertext: string;
61
+ /** 16-byte AES-GCM tag, base64url. */
62
+ tag: string;
63
+ };
64
+ export interface Envelope {
65
+ type: 'SignedEnvelope';
66
+ envelopeId: string;
67
+ taskId: string;
68
+ seq: number;
69
+ eventType: string;
70
+ senderDid: string;
71
+ recipientDid: string;
72
+ payload: Json;
73
+ }
74
+ export type SignedEnvelope = Signed<Envelope>;
75
+ export interface Capability {
76
+ type: 'CapabilityToken';
77
+ id: string;
78
+ issuer: string;
79
+ audience: string;
80
+ taskId: string;
81
+ resource: string;
82
+ allowedTools: string[];
83
+ argConstraints: Record<string, Schema>;
84
+ maxCalls: number;
85
+ notBefore: string;
86
+ expiresAt: string;
87
+ maxDepth: number;
88
+ parentHash: string | null;
89
+ }
90
+ export type CapabilityToken = Signed<Capability>;
91
+ export interface BudgetSpec {
92
+ costBearer: 'worker_byok' | 'bilateral_quota' | 'external_settlement_plugin';
93
+ maxInputTokens: number;
94
+ maxOutputTokens: number;
95
+ maxToolInvocations: number;
96
+ maxWallClockSeconds: number;
97
+ onOverrun: 'hard_stop' | 'request_hitl_amendment';
98
+ }
99
+ export interface TaskManifest {
100
+ protocolVersion: string;
101
+ taskId: string;
102
+ createdAt: string;
103
+ deadline: string;
104
+ requester: {
105
+ ownerDid: string;
106
+ agentDid: string;
107
+ displayName?: string;
108
+ relayEndpoint?: string;
109
+ };
110
+ worker?: {
111
+ ownerDid: string;
112
+ agentDid: string;
113
+ displayName?: string;
114
+ relayEndpoint?: string;
115
+ };
116
+ task: {
117
+ skillId?: string;
118
+ taskType?: string;
119
+ title: string;
120
+ description: string;
121
+ acceptanceCriteria: {
122
+ id: string;
123
+ description: string;
124
+ required: boolean;
125
+ }[];
126
+ };
127
+ io: {
128
+ inputSchema: Schema;
129
+ outputSchema: Schema;
130
+ inputArtifacts?: {
131
+ name: string;
132
+ digest: string;
133
+ mediaType: string;
134
+ sizeBytes: number;
135
+ }[];
136
+ };
137
+ verification: {
138
+ mode: string;
139
+ requireUsageReceipt: boolean;
140
+ requireExecutionAttestation: boolean;
141
+ maxRetries: number;
142
+ checks?: {
143
+ checkId: string;
144
+ kind: string;
145
+ target: string;
146
+ expectedExitCode?: number;
147
+ }[];
148
+ };
149
+ budget: BudgetSpec;
150
+ permissions: {
151
+ maxDelegationDepth: number;
152
+ grantedCapabilities: {
153
+ capabilityId: string;
154
+ resource: string;
155
+ allowedTools: string[];
156
+ argConstraints?: Schema;
157
+ maxInvocations: number;
158
+ expiresAt: string;
159
+ }[];
160
+ };
161
+ sandboxPolicy: {
162
+ isolationLevel: string;
163
+ networkAccess: string;
164
+ filesystemScope: string;
165
+ allowedHosts?: string[];
166
+ allowSubprocessFallback?: boolean;
167
+ };
168
+ hitlPolicy: {
169
+ requiredGates: string[];
170
+ };
171
+ signatures?: Record<string, Signature>;
172
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}