@7h3/protocol 0.1.2 → 0.4.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 (230) hide show
  1. package/.dockerignore +19 -0
  2. package/.github/dependabot.yml +32 -0
  3. package/.github/workflows/ci.yml +31 -0
  4. package/.github/workflows/publish.yml +59 -0
  5. package/.github/workflows/scorecard.yml +37 -0
  6. package/7h3.example.yaml +125 -0
  7. package/CHANGELOG.md +92 -0
  8. package/CONTRIBUTING.md +82 -0
  9. package/Dockerfile +73 -0
  10. package/GOVERNANCE.md +62 -0
  11. package/README.md +323 -6
  12. package/SECURITY.md +70 -0
  13. package/bench-results/replay-cache-full-1777891033256.json +10 -0
  14. package/bench-results/replay-cache-full-1777896317488.json +10 -0
  15. package/bench-results/replay-cache-full-1777900993184.json +10 -0
  16. package/bench-results/replay-cache-full-1777901019285.json +10 -0
  17. package/bench-results/replay-cache-quick-1777870170126.json +10 -0
  18. package/bench-results/signature-profiles-quick-1775875160079.json +85 -0
  19. package/bench-results/signature-profiles-quick-1775983539716.json +85 -0
  20. package/bench-results/signature-profiles-quick-1776237913190.json +85 -0
  21. package/bench-results/wire-codecs-full-1777891019803.json +93 -0
  22. package/bench-results/wire-codecs-full-1777896260964.json +93 -0
  23. package/bench-results/wire-codecs-full-1777901004247.json +93 -0
  24. package/bench-results/wire-codecs-quick-1775972879056.json +93 -0
  25. package/bench-results/wire-codecs-quick-1775983541111.json +93 -0
  26. package/bench-results/wire-codecs-quick-1776237914299.json +93 -0
  27. package/bench-results/wire-codecs-quick-1777841285236.json +93 -0
  28. package/bench-results/wire-codecs-quick-1777841321772.json +93 -0
  29. package/bench-results/wire-codecs-quick-1777841330408.json +93 -0
  30. package/bench-results/wire-codecs-quick-1777852886082.json +93 -0
  31. package/bench-results/wire-codecs-quick-1777852988773.json +93 -0
  32. package/bench-results/wire-codecs-quick-1777870188095.json +93 -0
  33. package/bench-results/wire-codecs-quick-1777870263918.json +93 -0
  34. package/bench-results/wire-codecs-quick-1777870455034.json +93 -0
  35. package/bench-results/wire-codecs-quick-1778816163081.json +93 -0
  36. package/bench-results/wire-codecs-quick-1778843936130.json +93 -0
  37. package/bin/7h3.ts +385 -0
  38. package/conformance/7h3_v0_1.json +77 -0
  39. package/conformance/7h3_v0_1_binary.json +20 -0
  40. package/conformance/aip_v0_1_binary.json +20 -0
  41. package/docker-compose.yaml +77 -0
  42. package/docs/ADOPTION_PLAN.md +120 -0
  43. package/docs/AGENTS.md +77 -0
  44. package/docs/AIP_RFC_v0.1.md +97 -0
  45. package/docs/AI_DECISION_CARD.md +122 -0
  46. package/docs/AI_RUNTIME_POLICY.json +126 -0
  47. package/docs/AI_RUNTIME_POLICY.yaml +110 -0
  48. package/docs/BACKPRESSURE_TUNING.md +65 -0
  49. package/docs/BENCHMARK_CLAIM_MATRIX.md +42 -0
  50. package/docs/BENCHMARK_REPORT_TEMPLATE.md +169 -0
  51. package/docs/BINARY_CODEC_BENCH.md +23 -0
  52. package/docs/CLEAN_CLONE_RUNBOOK.md +36 -0
  53. package/docs/CLOCK_SKEW_POLICY.md +30 -0
  54. package/docs/DISTRIBUTED_REPLAY.md +142 -0
  55. package/docs/FUZZ_CAMPAIGN.md +121 -0
  56. package/docs/GATEWAY.md +195 -0
  57. package/docs/KEY_MANAGEMENT_POLICY.md +53 -0
  58. package/docs/KEY_REVOCATION.md +69 -0
  59. package/docs/MCP_WRAPPER.md +159 -0
  60. package/docs/MIGRATION_GUIDE.md +40 -0
  61. package/docs/OPERATORS.md +184 -0
  62. package/docs/PERF_REGRESSION_POLICY.md +34 -0
  63. package/docs/PROJECT_EXAMINATION_2026-05-31.md +219 -0
  64. package/docs/RELEASE_BENCHMARK_REPORT_2026-05-15.md +135 -0
  65. package/docs/RELEASE_GATE.md +25 -0
  66. package/docs/RELEASE_NOTES_v0.1.0.md +54 -0
  67. package/docs/SECURITY_REVIEW_2026-06-05.md +165 -0
  68. package/docs/TELEMETRY.md +41 -0
  69. package/docs/THREAT_MODEL.md +89 -0
  70. package/docs/VERSIONING_POLICY.md +30 -0
  71. package/docs/assets/banner.png +0 -0
  72. package/eslint.config.js +15 -0
  73. package/fuzz/ts/harness-decode.ts +136 -0
  74. package/fuzz/ts/harness-verify.ts +121 -0
  75. package/fuzz/ts/run.ts +35 -0
  76. package/mcp-server/README.md +38 -0
  77. package/mcp-server/package-lock.json +1187 -0
  78. package/mcp-server/package.json +35 -0
  79. package/mcp-server/src/index.ts +236 -0
  80. package/mcp-server/tsconfig.json +14 -0
  81. package/package.json +79 -13
  82. package/scripts/aip-framework-quickstart.ts +110 -0
  83. package/scripts/aip-mcp-gateway.ts +38 -0
  84. package/scripts/aip-mcp-wrap-demo.ts +72 -0
  85. package/scripts/aip-quickstart.ts +60 -0
  86. package/scripts/bench-diff.ts +118 -0
  87. package/scripts/bench-protocol-e2e.ts +937 -0
  88. package/scripts/bench-protocol-openloop.ts +1397 -0
  89. package/scripts/bench-replay-cache.ts +76 -0
  90. package/scripts/bench-signature-profiles.ts +180 -0
  91. package/scripts/bench-wire-codecs.ts +161 -0
  92. package/scripts/build-binary-conformance.ts +36 -0
  93. package/scripts/build-release-dashboard.ts +175 -0
  94. package/scripts/canary-rollout.ts +38 -0
  95. package/scripts/mcpGatewayCli.test.ts +116 -0
  96. package/scripts/prepare-aip-package.ts +88 -0
  97. package/scripts/regen-conformance-sigs.ts +18 -0
  98. package/scripts/release-gate.ts +19 -0
  99. package/scripts/validate-runtime-policy.ts +18 -0
  100. package/sdk/browser/index.test.ts +162 -0
  101. package/sdk/browser/index.ts +257 -0
  102. package/sdk/browser/package.json +13 -0
  103. package/sdk/go/go.mod +3 -0
  104. package/sdk/go/http.go +135 -0
  105. package/sdk/go/protocol.go +324 -0
  106. package/sdk/go/protocol_test.go +334 -0
  107. package/sdk/go/webhook.go +136 -0
  108. package/sdk/python/README.md +18 -0
  109. package/sdk/python/protocol_7h3/__init__.py +46 -0
  110. package/sdk/python/protocol_7h3/http.py +212 -0
  111. package/sdk/python/protocol_7h3/keys.py +149 -0
  112. package/sdk/python/protocol_7h3/protocol.py +525 -0
  113. package/sdk/python/protocol_7h3/queue.py +118 -0
  114. package/sdk/python/protocol_7h3/webhook.py +116 -0
  115. package/sdk/python/pyproject.toml +40 -0
  116. package/sdk/python/tests/test_conformance.py +110 -0
  117. package/sdk/python/tests/test_http.py +305 -0
  118. package/sdk/python/tests/test_keys.py +417 -0
  119. package/sdk/python/tests/test_queue.py +120 -0
  120. package/sdk/python/tests/test_webhook.py +345 -0
  121. package/sdk/rust/Cargo.lock +371 -0
  122. package/sdk/rust/Cargo.toml +25 -0
  123. package/sdk/rust/README.md +31 -0
  124. package/sdk/rust/fuzz/Cargo.toml +29 -0
  125. package/sdk/rust/fuzz/fuzz_targets/fuzz_canonicalize.rs +46 -0
  126. package/sdk/rust/fuzz/fuzz_targets/fuzz_decode.rs +11 -0
  127. package/sdk/rust/src/bin/aip_mcp_gateway.rs +59 -0
  128. package/sdk/rust/src/http.rs +145 -0
  129. package/sdk/rust/src/keys.rs +161 -0
  130. package/sdk/rust/src/lib.rs +688 -0
  131. package/sdk/rust/src/queue.rs +79 -0
  132. package/sdk/rust/src/webhook.rs +86 -0
  133. package/sdk/rust/tests/conformance.rs +148 -0
  134. package/sdk/rust/tests/gateway.rs +130 -0
  135. package/sdk/rust/tests/http_webhook_queue.rs +201 -0
  136. package/sdk/rust/tests/keys.rs +189 -0
  137. package/src/agentAdapter.test.ts +48 -0
  138. package/src/agentAdapter.ts +56 -0
  139. package/src/auditLog.test.ts +145 -0
  140. package/src/auditLog.ts +147 -0
  141. package/src/conformance.test.ts +136 -0
  142. package/src/conformanceVectors.ts +99 -0
  143. package/src/frameworkAdapters.test.ts +290 -0
  144. package/src/frameworkAdapters.ts +261 -0
  145. package/src/gateway.test.ts +343 -0
  146. package/src/gateway.ts +171 -0
  147. package/src/grpcBinding.test.ts +211 -0
  148. package/src/grpcBinding.ts +103 -0
  149. package/src/httpBinding.test.ts +376 -0
  150. package/src/httpBinding.ts +163 -0
  151. package/src/index.ts +32 -0
  152. package/src/keyInfra.test.ts +278 -0
  153. package/src/keyInfra.ts +228 -0
  154. package/src/keyRegistry.ts +59 -0
  155. package/src/keyRotation.test.ts +78 -0
  156. package/src/keyRotation.ts +72 -0
  157. package/src/mcpGateway.test.ts +129 -0
  158. package/src/mcpGateway.ts +250 -0
  159. package/src/mcpTransports.test.ts +92 -0
  160. package/src/mcpTransports.ts +169 -0
  161. package/src/mcpWrapper.test.ts +179 -0
  162. package/src/mcpWrapper.ts +206 -0
  163. package/src/policyEnforcer.test.ts +99 -0
  164. package/src/policyEnforcer.ts +169 -0
  165. package/src/policyTelemetryFeedback.test.ts +25 -0
  166. package/src/policyTelemetryFeedback.ts +38 -0
  167. package/src/protocol.bench.ts +37 -0
  168. package/src/protocol.test.ts +155 -0
  169. package/src/protocol.ts +413 -0
  170. package/src/protocolAgent.test.ts +105 -0
  171. package/src/protocolAgent.ts +169 -0
  172. package/src/protocolBinary.test.ts +165 -0
  173. package/src/protocolBinary.ts +312 -0
  174. package/src/protocolCapabilities.ts +70 -0
  175. package/src/protocolFuzz.advanced.test.ts +235 -0
  176. package/src/protocolFuzz.test.ts +111 -0
  177. package/src/protocolNegative.test.ts +97 -0
  178. package/src/protocolReplay.test.ts +71 -0
  179. package/src/protocolReplay.ts +194 -0
  180. package/src/protocolTransport.test.ts +556 -0
  181. package/src/protocolTransport.ts +483 -0
  182. package/src/queueBinding.test.ts +130 -0
  183. package/src/queueBinding.ts +102 -0
  184. package/src/rateLimiter.test.ts +96 -0
  185. package/src/rateLimiter.ts +46 -0
  186. package/src/redisClient.ts +140 -0
  187. package/src/redisIntegration.test.ts +134 -0
  188. package/src/replayStores.test.ts +141 -0
  189. package/src/replayStores.ts +82 -0
  190. package/src/revocation.test.ts +98 -0
  191. package/src/revocation.ts +0 -0
  192. package/src/routePolicy.test.ts +87 -0
  193. package/src/routePolicy.ts +72 -0
  194. package/src/runtimePolicy.test.ts +49 -0
  195. package/src/runtimePolicy.ts +81 -0
  196. package/src/runtimePolicyManager.test.ts +29 -0
  197. package/src/runtimePolicyManager.ts +50 -0
  198. package/src/runtimePolicyPresets.ts +43 -0
  199. package/src/signedResponse.test.ts +111 -0
  200. package/src/signedResponse.ts +83 -0
  201. package/src/webhookBinding.test.ts +144 -0
  202. package/src/webhookBinding.ts +115 -0
  203. package/src/wsBinding.test.ts +221 -0
  204. package/src/wsBinding.ts +100 -0
  205. package/tsconfig.json +15 -0
  206. package/tsconfig.lib.json +23 -0
  207. package/vite.lib.config.ts +16 -0
  208. package/agentAdapter.d.ts +0 -26
  209. package/conformanceVectors.d.ts +0 -20
  210. package/frameworkAdapters.d.ts +0 -72
  211. package/index.d.ts +0 -20
  212. package/index.js +0 -1702
  213. package/keyRotation.d.ts +0 -20
  214. package/mcpGateway.d.ts +0 -37
  215. package/mcpTransports.d.ts +0 -62
  216. package/mcpWrapper.d.ts +0 -83
  217. package/policyEnforcer.d.ts +0 -50
  218. package/policyTelemetryFeedback.d.ts +0 -11
  219. package/protocol.d.ts +0 -66
  220. package/protocolAgent.d.ts +0 -58
  221. package/protocolBinary.d.ts +0 -8
  222. package/protocolCapabilities.d.ts +0 -24
  223. package/protocolReplay.d.ts +0 -35
  224. package/protocolTransport.d.ts +0 -73
  225. package/redisClient.d.ts +0 -49
  226. package/replayStores.d.ts +0 -32
  227. package/revocation.d.ts +0 -71
  228. package/runtimePolicy.d.ts +0 -24
  229. package/runtimePolicyManager.d.ts +0 -15
  230. package/runtimePolicyPresets.d.ts +0 -11
package/keyRotation.d.ts DELETED
@@ -1,20 +0,0 @@
1
- import type { ProtocolEnvelope, SignatureVerificationMaterial } from './protocol';
2
- export type KeyStatus = 'active' | 'verify-only' | 'revoked';
3
- export interface KeyRecord {
4
- sender: string;
5
- keyId: string;
6
- alg: SignatureVerificationMaterial['alg'];
7
- status: KeyStatus;
8
- notBeforeMs: number;
9
- notAfterMs: number;
10
- material: SignatureVerificationMaterial;
11
- }
12
- export declare class RollingKeyring {
13
- private readonly records;
14
- constructor(records?: KeyRecord[]);
15
- add(record: KeyRecord): void;
16
- revoke(sender: string, keyId: string, revokedAtMs?: number): boolean;
17
- selectSigningKey(sender: string, alg: SignatureVerificationMaterial['alg'], nowMs?: number): KeyRecord | null;
18
- resolveVerificationMaterial(signature: NonNullable<ProtocolEnvelope['signature']>, sender: string, nowMs?: number): SignatureVerificationMaterial | undefined;
19
- }
20
- export declare function createKeyringSignatureResolver(keyring: RollingKeyring, nowMsProvider?: () => number): (signature: NonNullable<ProtocolEnvelope["signature"]>, sender: string) => Promise<SignatureVerificationMaterial | undefined>;
package/mcpGateway.d.ts DELETED
@@ -1,37 +0,0 @@
1
- import { type BootstrapRuntimePolicyEnforcerOptions } from './policyEnforcer';
2
- import { type JsonRpcPolicyEvent, type JsonRpcBridgeOptions } from './frameworkAdapters';
3
- export interface AipMcpGatewayOptions {
4
- sharedSecret: string;
5
- gatewayAgentId?: string;
6
- workerAgentId?: string;
7
- allowedMethods?: readonly string[];
8
- workerCapabilityPrefix?: string;
9
- methodToCapability?: JsonRpcBridgeOptions['methodToCapability'];
10
- authorizeMethod?: JsonRpcBridgeOptions['authorizeMethod'];
11
- rateLimitKey?: JsonRpcBridgeOptions['rateLimitKey'];
12
- rateLimiter?: JsonRpcBridgeOptions['rateLimiter'];
13
- onAuditEvent?: (event: AipMcpGatewayAuditEvent) => void | Promise<void>;
14
- gatewayWireFormat?: 'json' | 'compact' | 'binary';
15
- workerWireFormat?: 'json' | 'compact' | 'binary';
16
- runtimePolicy?: {
17
- enabled?: boolean;
18
- options?: BootstrapRuntimePolicyEnforcerOptions;
19
- concurrencyHint?: number;
20
- latencySensitive?: boolean;
21
- compatibilityFirst?: boolean;
22
- };
23
- }
24
- export interface AipMcpGatewayRuntime {
25
- handleLine: (line: string) => Promise<string | null>;
26
- }
27
- export interface AipMcpGatewayAuditEvent {
28
- phase: 'request_received' | 'policy' | 'verification_failed' | 'request_success' | 'request_error';
29
- id?: string | number | null;
30
- method?: string;
31
- code?: number;
32
- message?: string;
33
- policy?: JsonRpcPolicyEvent;
34
- timestampMs: number;
35
- }
36
- export declare function createAipMcpGatewayRuntime(options: AipMcpGatewayOptions): AipMcpGatewayRuntime;
37
- export declare function createAipMcpGatewayRuntimeWithPolicy(options: AipMcpGatewayOptions): Promise<AipMcpGatewayRuntime>;
@@ -1,62 +0,0 @@
1
- import type { IncomingMessage, ServerResponse } from 'node:http';
2
- import type { Readable, Writable } from 'node:stream';
3
- import type { WireEnvelope } from './protocolTransport';
4
- /**
5
- * Transport adapters for the MCP hardening wrapper.
6
- *
7
- * The wrapper (`wrapMcpServer` / `wrapMcpClient`) is transport-agnostic: it
8
- * operates on `WireEnvelope`s. These adapters connect it to real transports —
9
- * newline-delimited stdio and HTTP — so a secured server is deployable as-is.
10
- *
11
- * Note: the stdio adapter frames one envelope per line and therefore supports
12
- * the string wire formats (`json`, `compact`). For `binary`, use HTTP.
13
- */
14
- type WireHandler = (raw: WireEnvelope) => Promise<WireEnvelope>;
15
- export interface StdioServerHandle {
16
- close(): void;
17
- }
18
- /**
19
- * Serves a wrapped MCP handler over newline-delimited streams (default
20
- * `process.stdin` / `process.stdout`). Lines are processed sequentially so
21
- * responses are emitted in request order.
22
- */
23
- export declare function serveMcpOverStdio(handle: WireHandler, options?: {
24
- input?: Readable;
25
- output?: Writable;
26
- onError?: (error: unknown) => void;
27
- }): StdioServerHandle;
28
- export interface StdioClientHandle {
29
- send: WireHandler;
30
- close(): void;
31
- }
32
- /**
33
- * Creates a stdio client `send` function for `wrapMcpClient`. Requests and
34
- * responses are correlated by order over the single pipe (one envelope per line).
35
- */
36
- export declare function createStdioMcpClient(options: {
37
- input: Readable;
38
- output: Writable;
39
- }): StdioClientHandle;
40
- /**
41
- * Creates a `node:http`-compatible request handler that runs the wrapped MCP
42
- * handler. The request body is the wire envelope; the response body is the
43
- * signed reply envelope.
44
- */
45
- export declare function createHttpMcpHandler(handle: WireHandler, options?: {
46
- binary?: boolean;
47
- }): (req: IncomingMessage, res: ServerResponse) => void;
48
- export interface HttpClientHandle {
49
- send: WireHandler;
50
- }
51
- /**
52
- * Creates an HTTP client `send` function for `wrapMcpClient`. POSTs the request
53
- * envelope to `url` and returns the response envelope. Uses the global `fetch`
54
- * by default; inject `fetchImpl` for tests or custom agents.
55
- */
56
- export declare function createHttpMcpClient(options: {
57
- url: string;
58
- fetchImpl?: typeof fetch;
59
- binary?: boolean;
60
- headers?: Record<string, string>;
61
- }): HttpClientHandle;
62
- export {};
package/mcpWrapper.d.ts DELETED
@@ -1,83 +0,0 @@
1
- import { type ProtocolEnvelope } from './protocol';
2
- import { type ReceiveEnvelopeOptions, type WireEnvelope, type WireFormat } from './protocolTransport';
3
- /**
4
- * MCP hardening middleware.
5
- *
6
- * MCP messages are plain JSON-RPC 2.0 and, as shipped, carry no signature or
7
- * replay protection. These wrappers put an AIP envelope around each message on
8
- * the wire — signing, TTL-bounding, and replay-checking every request and
9
- * response — while the underlying MCP handler still receives plain JSON-RPC.
10
- * "Zero app changes": your handler signature does not change.
11
- *
12
- * The wrappers enforce four bindings beyond signature verification:
13
- * - recipient binding: the server only runs the handler when the envelope is
14
- * addressed to it (`recipient === selfAgentId`) — defeats cross-server relay.
15
- * - sender binding: the client only accepts responses from its expected peer
16
- * (`sender === peerAgentId`) — defeats response spoofing.
17
- * - correlation binding: the client only accepts a response whose
18
- * `correlationId` matches the request it sent — defeats response substitution.
19
- * - replay protection on by default (an `InMemoryReplayCache` if none supplied).
20
- *
21
- * Verification reuses the transport pipeline (`receiveEnvelope`), so it composes
22
- * directly with a Redis-backed replay cache (`createRedisReplayStore`) and
23
- * fleet-wide revocation (`withRevocationCheck`) via the `receive` options.
24
- */
25
- export type JsonRpcId = string | number | null;
26
- export interface JsonRpcRequest {
27
- jsonrpc: '2.0';
28
- id: JsonRpcId;
29
- method: string;
30
- params?: unknown;
31
- }
32
- export interface JsonRpcResponse {
33
- jsonrpc: '2.0';
34
- id: JsonRpcId;
35
- result?: unknown;
36
- error?: {
37
- code: number;
38
- message: string;
39
- data?: unknown;
40
- };
41
- }
42
- export type McpJsonRpcHandler = (request: JsonRpcRequest) => JsonRpcResponse | Promise<JsonRpcResponse>;
43
- export interface McpSecurityOptions {
44
- /** This peer's agent id, used as the envelope `sender` and enforced as the inbound `recipient`. */
45
- selfAgentId: string;
46
- /** The peer's agent id: set as the envelope `recipient` (client) and enforced as the response `sender`. */
47
- peerAgentId?: string;
48
- /** Signs an unsigned envelope, e.g. `(e) => signEnvelopeHmac(e, secret, keyId)`. */
49
- sign: (envelope: Omit<ProtocolEnvelope, 'signature'>) => Promise<ProtocolEnvelope>;
50
- /** Inbound verification options: signature material resolver, replay cache, clock skew, etc. */
51
- receive?: ReceiveEnvelopeOptions;
52
- /** Wire format for the envelope on the wire. Default `compact`. */
53
- wireFormat?: WireFormat;
54
- /** Envelope TTL in ms. Default 60_000. */
55
- ttlMs?: number;
56
- }
57
- export interface EncodedRequest {
58
- raw: WireEnvelope;
59
- /** The envelope `messageId` generated for this request; bind the response's `correlationId` to it. */
60
- messageId: string;
61
- }
62
- export interface DecodeResponseOptions {
63
- /** When set, require the response `correlationId` to equal this value (the request's messageId). */
64
- expectCorrelationId?: string;
65
- }
66
- /**
67
- * Wraps an existing MCP JSON-RPC handler so every inbound message is verified
68
- * (signature + replay + TTL + recipient binding) before the handler runs, and
69
- * every response is signed. Returns a function over the AIP wire envelope.
70
- */
71
- export declare function wrapMcpServer(handler: McpJsonRpcHandler, options: McpSecurityOptions): (raw: WireEnvelope) => Promise<WireEnvelope>;
72
- export interface McpClientCodec {
73
- encodeRequest(request: JsonRpcRequest): Promise<EncodedRequest>;
74
- decodeResponse(raw: WireEnvelope, options?: DecodeResponseOptions): Promise<JsonRpcResponse>;
75
- }
76
- /** Signs outbound requests and verifies inbound responses (with sender + correlation binding). */
77
- export declare function createMcpClientCodec(options: McpSecurityOptions): McpClientCodec;
78
- /**
79
- * Wraps a transport send function (`stdio`, HTTP, ...) so callers issue and
80
- * receive plain JSON-RPC while AIP signing, verification, and request/response
81
- * correlation happen on the wire.
82
- */
83
- export declare function wrapMcpClient(send: (raw: WireEnvelope) => Promise<WireEnvelope>, options: McpSecurityOptions): (request: JsonRpcRequest) => Promise<JsonRpcResponse>;
@@ -1,50 +0,0 @@
1
- import { type LoadRuntimePolicyOptions, type RuntimePolicy } from './runtimePolicy';
2
- export type RuntimeMode = 'http' | 'ws' | 'http-binary' | 'http-batch' | 'http-binary-batch' | 'ws-batch' | 'ws-binary' | 'ws-binary-batch';
3
- export interface ModeSelectionInput {
4
- concurrency: number;
5
- latencySensitive?: boolean;
6
- compatibilityFirst?: boolean;
7
- }
8
- export interface TuningInput {
9
- trafficClass: 'low' | 'medium' | 'high';
10
- p99Ms?: number;
11
- dropPct?: number;
12
- }
13
- export interface TuningDecision {
14
- batchSizeRange: [number, number];
15
- inflightCapRange: [number, number];
16
- retryBackoffMsRange: [number, number];
17
- actions: string[];
18
- }
19
- export interface RetryInput {
20
- error: unknown;
21
- attempt: number;
22
- }
23
- export interface InvariantConfig {
24
- signatureVerification: boolean;
25
- canonicalization: boolean;
26
- replayDefense: boolean;
27
- ttlClockSkewEnforcement: boolean;
28
- }
29
- export declare function createPolicyEnforcer(policy: RuntimePolicy): {
30
- selectMode: (input: ModeSelectionInput) => RuntimeMode;
31
- tune: (input: TuningInput) => TuningDecision;
32
- shouldRetry: (input: RetryInput) => boolean;
33
- assertInvariant: (config: InvariantConfig) => void;
34
- metadata: {
35
- policyName: string;
36
- policyVersion: string;
37
- policyStatus: string;
38
- enforcedSlo: {
39
- dropPctMax: number;
40
- p99MsMax: number;
41
- };
42
- };
43
- };
44
- export type PolicyEnforcer = ReturnType<typeof createPolicyEnforcer>;
45
- export type BootstrapRuntimePolicyEnforcerOptions = LoadRuntimePolicyOptions;
46
- export declare function bootstrapRuntimePolicyEnforcer(options?: BootstrapRuntimePolicyEnforcerOptions): Promise<{
47
- policy: RuntimePolicy;
48
- enforcer: PolicyEnforcer;
49
- }>;
50
- export declare function isRuntimeMode(value: string): value is RuntimeMode;
@@ -1,11 +0,0 @@
1
- export interface TelemetryFeedbackInput {
2
- mode: string;
3
- p99Ms: number;
4
- dropPct: number;
5
- concurrency: number;
6
- }
7
- export interface TelemetryFeedbackRecommendation {
8
- severity: 'normal' | 'warn' | 'critical';
9
- actions: string[];
10
- }
11
- export declare function recommendPolicyAdjustments(input: TelemetryFeedbackInput): TelemetryFeedbackRecommendation;
package/protocol.d.ts DELETED
@@ -1,66 +0,0 @@
1
- export type ProtocolVersion = 'aip/0.1';
2
- export type IntentKind = 'PING' | 'PONG' | 'CAPS' | 'TASK' | 'RESULT' | 'ERROR';
3
- export interface ProtocolHeader {
4
- version: ProtocolVersion;
5
- messageId: string;
6
- timestampMs: number;
7
- ttlMs: number;
8
- sender: string;
9
- recipient?: string;
10
- nonce: string;
11
- }
12
- export interface ProtocolBody {
13
- intent: IntentKind;
14
- content: string;
15
- capability?: string;
16
- correlationId?: string;
17
- }
18
- export interface ProtocolSignature {
19
- alg: 'HS256' | 'ED25519';
20
- keyId: string;
21
- value: string;
22
- }
23
- export interface ProtocolEnvelope {
24
- header: ProtocolHeader;
25
- body: ProtocolBody;
26
- signature?: ProtocolSignature;
27
- }
28
- export interface ProtocolDiagnostic {
29
- level: 'error' | 'warning';
30
- message: string;
31
- }
32
- export type SignatureVerificationMaterial = {
33
- alg: 'HS256';
34
- secret: string;
35
- } | {
36
- alg: 'ED25519';
37
- publicKey: string;
38
- };
39
- export declare function canonicalizeEnvelope(envelope: Omit<ProtocolEnvelope, 'signature'>): string;
40
- export declare function signCanonicalPayloadHmac(payload: string, secret: string): Promise<string>;
41
- export declare function verifyCanonicalPayloadHmac(payload: string, signature: string, secret: string): Promise<boolean>;
42
- export declare function generateEd25519KeypairBase64Url(): Promise<{
43
- publicKey: string;
44
- privateKey: string;
45
- }>;
46
- export declare function signCanonicalPayloadEd25519(payload: string, privateKeyPkcs8Base64Url: string): Promise<string>;
47
- export declare function verifyCanonicalPayloadEd25519(payload: string, signature: string, publicKeySpkiBase64Url: string): Promise<boolean>;
48
- export declare function signEnvelopeHmac(envelope: Omit<ProtocolEnvelope, 'signature'>, secret: string, keyId?: string): Promise<ProtocolEnvelope>;
49
- export declare function verifyEnvelopeHmac(envelope: ProtocolEnvelope, secret: string): Promise<boolean>;
50
- export declare function signEnvelopeEd25519(envelope: Omit<ProtocolEnvelope, 'signature'>, privateKeyPkcs8Base64Url: string, keyId?: string): Promise<ProtocolEnvelope>;
51
- export declare function verifyEnvelopeEd25519(envelope: ProtocolEnvelope, publicKeySpkiBase64Url: string): Promise<boolean>;
52
- export declare function verifyEnvelopeSignature(envelope: ProtocolEnvelope, material: SignatureVerificationMaterial): Promise<boolean>;
53
- export declare function verifyCanonicalPayloadSignature(payload: string, signature: ProtocolSignature | undefined, material: SignatureVerificationMaterial): Promise<boolean>;
54
- export declare function validateEnvelope(envelope: ProtocolEnvelope, nowMs?: number): ProtocolDiagnostic[];
55
- export declare function createEnvelope(input: {
56
- sender: string;
57
- recipient?: string;
58
- intent: IntentKind;
59
- content: string;
60
- capability?: string;
61
- correlationId?: string;
62
- ttlMs?: number;
63
- messageId?: string;
64
- nonce?: string;
65
- nowMs?: number;
66
- }): Omit<ProtocolEnvelope, 'signature'>;
@@ -1,58 +0,0 @@
1
- import { type IntentKind, type ProtocolDiagnostic, type ProtocolEnvelope } from './protocol';
2
- import { type AckMode } from './protocolCapabilities';
3
- import { InMemoryReplayCache } from './protocolReplay';
4
- import { type WireEnvelope, type WireFormat } from './protocolTransport';
5
- export interface TaskHandlerResult {
6
- intent?: 'RESULT' | 'ERROR';
7
- content: string;
8
- capability?: string;
9
- }
10
- export interface AgentSessionConfig {
11
- agentId: string;
12
- outboundSecret: string;
13
- keyId?: string;
14
- capabilities?: string[];
15
- supportedWireFormats?: WireFormat[];
16
- maxBatchSize?: number;
17
- ackModes?: AckMode[];
18
- requireSignature?: boolean;
19
- replayCache?: InMemoryReplayCache;
20
- sharedSecrets?: Record<string, string>;
21
- resolveInboundSecret?: (keyId: string, sender: string) => string | undefined | Promise<string | undefined>;
22
- onTask?: (envelope: ProtocolEnvelope) => TaskHandlerResult | Promise<TaskHandlerResult>;
23
- }
24
- export interface AgentReceiveResult {
25
- ok: boolean;
26
- diagnostics: ProtocolDiagnostic[];
27
- received: ProtocolEnvelope | null;
28
- response: ProtocolEnvelope | null;
29
- }
30
- export declare class AgentSession {
31
- private readonly agentId;
32
- private readonly outboundSecret;
33
- private readonly keyId;
34
- private readonly capabilities;
35
- private readonly supportedWireFormats;
36
- private readonly maxBatchSize;
37
- private readonly ackModes;
38
- private readonly requireSignature;
39
- private readonly replayCache;
40
- private readonly sharedSecrets;
41
- private readonly resolveInboundSecret?;
42
- private readonly onTask?;
43
- constructor(config: AgentSessionConfig);
44
- private inboundSecretResolver;
45
- createSignedIntent(input: {
46
- recipient?: string;
47
- intent: IntentKind;
48
- content: string;
49
- capability?: string;
50
- correlationId?: string;
51
- ttlMs?: number;
52
- messageId?: string;
53
- nonce?: string;
54
- nowMs?: number;
55
- }): Promise<ProtocolEnvelope>;
56
- receiveAndRespond(input: WireEnvelope | ProtocolEnvelope, nowMs?: number): Promise<AgentReceiveResult>;
57
- private buildAutoResponse;
58
- }
@@ -1,8 +0,0 @@
1
- import type { ProtocolEnvelope } from './protocol';
2
- import type { ReceiveEnvelopeResult } from './protocolTransport';
3
- export declare const DEFAULT_MAX_BINARY_ENVELOPE_BYTES: number;
4
- export interface BinaryDecodeOptions {
5
- maxFrameBytes?: number;
6
- }
7
- export declare function encodeEnvelopeBinary(envelope: ProtocolEnvelope): Uint8Array;
8
- export declare function decodeEnvelopeBinary(payload: Uint8Array, options?: BinaryDecodeOptions): ReceiveEnvelopeResult;
@@ -1,24 +0,0 @@
1
- import type { WireFormat } from './protocolTransport';
2
- export type AckMode = 'fast' | 'receipt';
3
- export interface AipCapabilities {
4
- agent: string;
5
- capabilities: string[];
6
- wireFormats: WireFormat[];
7
- batchMax: number;
8
- ackModes: AckMode[];
9
- }
10
- export interface NegotiatedAipCapabilities {
11
- wireFormat: WireFormat;
12
- batchMax: number;
13
- ackMode: AckMode;
14
- }
15
- export declare function createAipCapabilities(input: {
16
- agent: string;
17
- capabilities?: string[];
18
- wireFormats?: WireFormat[];
19
- batchMax?: number;
20
- ackModes?: AckMode[];
21
- }): AipCapabilities;
22
- export declare function encodeAipCapabilities(capabilities: AipCapabilities): string;
23
- export declare function parseAipCapabilities(raw: string): AipCapabilities | null;
24
- export declare function negotiateAipCapabilities(local: AipCapabilities, remote: AipCapabilities): NegotiatedAipCapabilities;
@@ -1,35 +0,0 @@
1
- import type { ProtocolEnvelope } from './protocol';
2
- export interface ReplayCheckResult {
3
- ok: boolean;
4
- reason?: string;
5
- }
6
- export interface ReplayCache {
7
- consume(envelope: ProtocolEnvelope, nowMs?: number): ReplayCheckResult | Promise<ReplayCheckResult>;
8
- consumeMany?(envelopes: ProtocolEnvelope[], nowMs?: number): ReplayCheckResult[] | Promise<ReplayCheckResult[]>;
9
- }
10
- export interface DistributedReplayStore {
11
- reserve(key: string, expiresAtMs: number, nowMs: number): boolean | Promise<boolean>;
12
- /** Optional batch reserve; enables single round-trip checks for batched envelopes. */
13
- reserveMany?(entries: Array<{
14
- key: string;
15
- expiresAtMs: number;
16
- }>, nowMs: number): boolean[] | Promise<boolean[]>;
17
- }
18
- export declare class InMemoryReplayCache implements ReplayCache {
19
- private readonly entries;
20
- private readonly maxEntries;
21
- private readonly expiries;
22
- constructor(maxEntries?: number);
23
- private makeKey;
24
- prune(nowMs?: number): void;
25
- private evictOne;
26
- consume(envelope: ProtocolEnvelope, nowMs?: number): ReplayCheckResult;
27
- consumeMany(envelopes: ProtocolEnvelope[], nowMs?: number): ReplayCheckResult[];
28
- }
29
- export declare class DistributedReplayCache implements ReplayCache {
30
- private readonly store;
31
- constructor(store: DistributedReplayStore);
32
- private makeKey;
33
- consume(envelope: ProtocolEnvelope, nowMs?: number): Promise<ReplayCheckResult>;
34
- consumeMany(envelopes: ProtocolEnvelope[], nowMs?: number): Promise<ReplayCheckResult[]>;
35
- }
@@ -1,73 +0,0 @@
1
- import { type SignatureVerificationMaterial, type IntentKind, type ProtocolDiagnostic, type ProtocolEnvelope } from './protocol';
2
- import { type ReplayCache } from './protocolReplay';
3
- export type WireFormat = 'json' | 'compact' | 'binary';
4
- export type BatchWireFormat = Exclude<WireFormat, 'binary'>;
5
- export interface ReceiveEnvelopeOptions {
6
- nowMs?: number;
7
- requireSignature?: boolean;
8
- maxClockSkewMs?: number;
9
- replayCache?: ReplayCache;
10
- verificationMaterialCache?: VerificationMaterialCache;
11
- secretResolver?: (keyId: string, sender: string) => string | undefined | Promise<string | undefined>;
12
- signatureResolver?: (signature: NonNullable<ProtocolEnvelope['signature']>, sender: string) => SignatureVerificationMaterial | undefined | Promise<SignatureVerificationMaterial | undefined>;
13
- telemetry?: (event: TransportTelemetryEvent) => void | Promise<void>;
14
- }
15
- export interface ReceiveEnvelopeBatchOptions extends ReceiveEnvelopeOptions {
16
- batchConcurrency?: number;
17
- }
18
- export interface TransportTelemetryEvent {
19
- phase: 'decoded' | 'rejected_clock_skew' | 'rejected_validation' | 'rejected_replay' | 'rejected_missing_signature' | 'rejected_missing_material' | 'rejected_bad_signature' | 'batch_summary' | 'accepted';
20
- nowMs: number;
21
- sender?: string;
22
- messageId?: string;
23
- reason?: string;
24
- }
25
- export interface ReceiveEnvelopeResult {
26
- ok: boolean;
27
- diagnostics: ProtocolDiagnostic[];
28
- envelope: ProtocolEnvelope | null;
29
- }
30
- export interface VerificationMaterialCache {
31
- get(key: string, nowMs?: number): SignatureVerificationMaterial | undefined;
32
- set(key: string, material: SignatureVerificationMaterial, expiresAtMs: number): void;
33
- delete?(key: string): void;
34
- }
35
- export declare class InMemoryVerificationMaterialCache implements VerificationMaterialCache {
36
- private readonly entries;
37
- private readonly maxEntries;
38
- constructor(maxEntries?: number);
39
- get(key: string, nowMs?: number): SignatureVerificationMaterial | undefined;
40
- set(key: string, material: SignatureVerificationMaterial, expiresAtMs: number): void;
41
- delete(key: string): void;
42
- }
43
- export type WireEnvelope = string | Uint8Array;
44
- export declare function decodeEnvelope(raw: WireEnvelope): ReceiveEnvelopeResult;
45
- export declare function encodeEnvelope(envelope: ProtocolEnvelope, format: 'binary'): Uint8Array;
46
- export declare function encodeEnvelope(envelope: ProtocolEnvelope, format?: 'json' | 'compact'): string;
47
- export declare function encodeEnvelope(envelope: ProtocolEnvelope, format: WireFormat): WireEnvelope;
48
- export declare function encodeEnvelopeBatch(envelopes: ProtocolEnvelope[], format?: BatchWireFormat): string;
49
- export declare function decodeEnvelopeBatch(raw: string): ReceiveEnvelopeResult[];
50
- export declare function receiveEnvelope(input: WireEnvelope | ProtocolEnvelope, options?: ReceiveEnvelopeOptions): Promise<ReceiveEnvelopeResult>;
51
- export declare function receiveEnvelopeBatch(input: string | Array<WireEnvelope | ProtocolEnvelope>, options?: ReceiveEnvelopeBatchOptions): Promise<ReceiveEnvelopeResult[]>;
52
- export declare class SessionTransport {
53
- private readonly options;
54
- constructor(options?: Omit<ReceiveEnvelopeOptions, 'replayCache'> & {
55
- replayCache?: ReplayCache;
56
- });
57
- receive(input: WireEnvelope | ProtocolEnvelope, nowMs?: number): Promise<ReceiveEnvelopeResult>;
58
- receiveBatch(input: string | Array<WireEnvelope | ProtocolEnvelope>, nowMs?: number): Promise<ReceiveEnvelopeResult[]>;
59
- }
60
- export declare function createSignedMessage(input: {
61
- sender: string;
62
- recipient?: string;
63
- intent: IntentKind;
64
- content: string;
65
- capability?: string;
66
- correlationId?: string;
67
- ttlMs?: number;
68
- messageId?: string;
69
- nonce?: string;
70
- nowMs?: number;
71
- secret: string;
72
- keyId?: string;
73
- }): Promise<ProtocolEnvelope>;
package/redisClient.d.ts DELETED
@@ -1,49 +0,0 @@
1
- /**
2
- * Minimal Redis command surface the AIP stores depend on.
3
- *
4
- * The library stays client-agnostic: any Redis client (ioredis, node-redis,
5
- * Upstash, a cluster proxy, ...) can be adapted to this interface, so
6
- * `@7h3/protocol` ships with no Redis dependency of its own.
7
- */
8
- export interface RedisSetOptions {
9
- /** Only set when the key does not already exist (Redis `NX`). */
10
- nx?: boolean;
11
- /** Expire the key after this many milliseconds (Redis `PX`). */
12
- pxMs?: number;
13
- }
14
- /** A queued, chainable batch of `set` commands flushed in a single round-trip. */
15
- export interface RedisPipelineLike {
16
- set(key: string, value: string, options?: RedisSetOptions): RedisPipelineLike;
17
- exec(): Promise<Array<'OK' | null>>;
18
- }
19
- export interface RedisLikeClient {
20
- /** Returns `'OK'` when the value was written, or `null` when `NX` prevented it. */
21
- set(key: string, value: string, options?: RedisSetOptions): Promise<'OK' | null>;
22
- /** Truthy when the key exists and has not expired. */
23
- get?(key: string): Promise<string | null>;
24
- /** Removes a key; returns the number of keys removed. */
25
- del?(key: string): Promise<number>;
26
- /** Optional batch pipeline; when present, batch reserves use a single round-trip. */
27
- pipeline?(): RedisPipelineLike;
28
- }
29
- /**
30
- * In-memory reference implementation of {@link RedisLikeClient}.
31
- *
32
- * It is a faithful stand-in for a single Redis node's `SET NX PX` / `GET` /
33
- * `DEL` semantics — useful for tests, local development, and as the default
34
- * degraded-mode fallback. It is NOT a distributed store: it provides no
35
- * cross-process guarantees and must not be used as a production replay store
36
- * for a horizontally scaled deployment.
37
- */
38
- export declare class InMemoryRedisLikeClient implements RedisLikeClient {
39
- private readonly entries;
40
- private readonly now;
41
- constructor(options?: {
42
- now?: () => number;
43
- });
44
- private live;
45
- set(key: string, value: string, options?: RedisSetOptions): Promise<'OK' | null>;
46
- get(key: string): Promise<string | null>;
47
- del(key: string): Promise<number>;
48
- pipeline(): RedisPipelineLike;
49
- }
package/replayStores.d.ts DELETED
@@ -1,32 +0,0 @@
1
- import type { DistributedReplayStore } from './protocolReplay';
2
- import { type RedisLikeClient } from './redisClient';
3
- /**
4
- * What to do when the Redis client throws (network blip, server down).
5
- *
6
- * - `fallback` (default): degrade to a local in-memory store so traffic keeps
7
- * flowing with single-node replay protection still in force. Quality +
8
- * reliability + scalability: Redis is never a fleet-wide kill switch.
9
- * - `reject`: fail closed — deny the message because uniqueness cannot be confirmed.
10
- * - `allow`: fail open — accept the message (skip the check) to maximise uptime.
11
- */
12
- export type ReplayErrorBehavior = 'fallback' | 'reject' | 'allow';
13
- export interface RedisReplayStoreOptions {
14
- /** Key namespace in Redis. Default `aip:replay:`. */
15
- keyPrefix?: string;
16
- /** Behavior when the Redis client throws. Default `fallback`. */
17
- errorBehavior?: ReplayErrorBehavior;
18
- /** Local store used when `errorBehavior` is `fallback`. Defaults to an in-memory-backed store. */
19
- fallback?: DistributedReplayStore;
20
- /** Observability hook fired whenever a Redis error forces degraded handling. */
21
- onDegraded?: (error: unknown, context: {
22
- key: string;
23
- behavior: ReplayErrorBehavior;
24
- }) => void;
25
- }
26
- /**
27
- * Creates a {@link DistributedReplayStore} backed by Redis-style `SET NX PX`.
28
- *
29
- * Drop the returned store into `new DistributedReplayCache(store)` (or pass a
30
- * `DistributedReplayCache` as the transport `replayCache`).
31
- */
32
- export declare function createRedisReplayStore(client: RedisLikeClient, options?: RedisReplayStoreOptions): DistributedReplayStore;