@7h3/protocol 0.5.0 → 0.5.1

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 (294) hide show
  1. package/README.md +6 -1317
  2. package/agentAdapter.d.ts +26 -0
  3. package/auditLog.d.ts +54 -0
  4. package/capability.d.ts +67 -0
  5. package/cborCodec.d.ts +34 -0
  6. package/conformanceVectors.d.ts +20 -0
  7. package/encryption.d.ts +85 -0
  8. package/envelopeCbor.d.ts +33 -0
  9. package/frameworkAdapters.d.ts +72 -0
  10. package/gateway.d.ts +53 -0
  11. package/grpcBinding.d.ts +29 -0
  12. package/httpBinding.d.ts +50 -0
  13. package/index.d.ts +39 -0
  14. package/index.js +3662 -0
  15. package/keyInfra.d.ts +64 -0
  16. package/keyRegistry.d.ts +9 -0
  17. package/keyRotation.d.ts +20 -0
  18. package/mcpGateway.d.ts +37 -0
  19. package/mcpTransports.d.ts +62 -0
  20. package/mcpWrapper.d.ts +83 -0
  21. package/otel.d.ts +65 -0
  22. package/package.json +13 -121
  23. package/policyEnforcer.d.ts +50 -0
  24. package/policyTelemetryFeedback.d.ts +11 -0
  25. package/{src/protocol.d.ts → protocol.d.ts} +1 -2
  26. package/protocolAgent.d.ts +58 -0
  27. package/protocolBinary.d.ts +8 -0
  28. package/protocolCapabilities.d.ts +24 -0
  29. package/protocolReplay.d.ts +35 -0
  30. package/protocolTransport.d.ts +73 -0
  31. package/queueBinding.d.ts +43 -0
  32. package/rateLimiter.d.ts +18 -0
  33. package/{src/redisClient.ts → redisClient.d.ts} +25 -75
  34. package/replayStores.d.ts +98 -0
  35. package/revocation.d.ts +71 -0
  36. package/routePolicy.d.ts +30 -0
  37. package/runtimePolicy.d.ts +24 -0
  38. package/runtimePolicyManager.d.ts +15 -0
  39. package/runtimePolicyPresets.d.ts +11 -0
  40. package/signedResponse.d.ts +21 -0
  41. package/stream.d.ts +59 -0
  42. package/telemetry.d.ts +79 -0
  43. package/webhookBinding.d.ts +30 -0
  44. package/wsBinding.d.ts +52 -0
  45. package/.dockerignore +0 -19
  46. package/.github/dependabot.yml +0 -32
  47. package/.github/workflows/ci.yml +0 -31
  48. package/.github/workflows/publish.yml +0 -59
  49. package/.github/workflows/scorecard.yml +0 -37
  50. package/7h3.example.yaml +0 -125
  51. package/CHANGELOG.md +0 -152
  52. package/CONTRIBUTING.md +0 -82
  53. package/Dockerfile +0 -73
  54. package/GOVERNANCE.md +0 -62
  55. package/SECURITY.md +0 -70
  56. package/bench-results/replay-cache-full-1777891033256.json +0 -10
  57. package/bench-results/replay-cache-full-1777896317488.json +0 -10
  58. package/bench-results/replay-cache-full-1777900993184.json +0 -10
  59. package/bench-results/replay-cache-full-1777901019285.json +0 -10
  60. package/bench-results/replay-cache-quick-1777870170126.json +0 -10
  61. package/bench-results/signature-profiles-quick-1775875160079.json +0 -85
  62. package/bench-results/signature-profiles-quick-1775983539716.json +0 -85
  63. package/bench-results/signature-profiles-quick-1776237913190.json +0 -85
  64. package/bench-results/wire-codecs-full-1777891019803.json +0 -93
  65. package/bench-results/wire-codecs-full-1777896260964.json +0 -93
  66. package/bench-results/wire-codecs-full-1777901004247.json +0 -93
  67. package/bench-results/wire-codecs-quick-1775972879056.json +0 -93
  68. package/bench-results/wire-codecs-quick-1775983541111.json +0 -93
  69. package/bench-results/wire-codecs-quick-1776237914299.json +0 -93
  70. package/bench-results/wire-codecs-quick-1777841285236.json +0 -93
  71. package/bench-results/wire-codecs-quick-1777841321772.json +0 -93
  72. package/bench-results/wire-codecs-quick-1777841330408.json +0 -93
  73. package/bench-results/wire-codecs-quick-1777852886082.json +0 -93
  74. package/bench-results/wire-codecs-quick-1777852988773.json +0 -93
  75. package/bench-results/wire-codecs-quick-1777870188095.json +0 -93
  76. package/bench-results/wire-codecs-quick-1777870263918.json +0 -93
  77. package/bench-results/wire-codecs-quick-1777870455034.json +0 -93
  78. package/bench-results/wire-codecs-quick-1778816163081.json +0 -93
  79. package/bench-results/wire-codecs-quick-1778843936130.json +0 -93
  80. package/bin/7h3.ts +0 -406
  81. package/conformance/7h3_v0_1.json +0 -77
  82. package/conformance/7h3_v0_1_binary.json +0 -20
  83. package/conformance/aip_v0_1_binary.json +0 -20
  84. package/docker-compose.yaml +0 -77
  85. package/docs/ADOPTION_PLAN.md +0 -120
  86. package/docs/AGENTS.md +0 -77
  87. package/docs/AIP_RFC_v0.1.md +0 -97
  88. package/docs/AI_DECISION_CARD.md +0 -122
  89. package/docs/AI_RUNTIME_POLICY.json +0 -126
  90. package/docs/AI_RUNTIME_POLICY.yaml +0 -110
  91. package/docs/BACKPRESSURE_TUNING.md +0 -65
  92. package/docs/BENCHMARK_CLAIM_MATRIX.md +0 -42
  93. package/docs/BENCHMARK_REPORT_TEMPLATE.md +0 -169
  94. package/docs/BINARY_CODEC_BENCH.md +0 -23
  95. package/docs/CLEAN_CLONE_RUNBOOK.md +0 -36
  96. package/docs/CLOCK_SKEW_POLICY.md +0 -30
  97. package/docs/DISTRIBUTED_REPLAY.md +0 -142
  98. package/docs/FUZZ_CAMPAIGN.md +0 -121
  99. package/docs/GATEWAY.md +0 -195
  100. package/docs/KEY_MANAGEMENT_POLICY.md +0 -53
  101. package/docs/KEY_REVOCATION.md +0 -69
  102. package/docs/MCP_WRAPPER.md +0 -159
  103. package/docs/MIGRATION_GUIDE.md +0 -40
  104. package/docs/OPERATORS.md +0 -184
  105. package/docs/PERF_REGRESSION_POLICY.md +0 -34
  106. package/docs/PROJECT_EXAMINATION_2026-05-31.md +0 -219
  107. package/docs/RELEASE_BENCHMARK_REPORT_2026-05-15.md +0 -135
  108. package/docs/RELEASE_GATE.md +0 -25
  109. package/docs/RELEASE_NOTES_v0.1.0.md +0 -54
  110. package/docs/SECURITY_REVIEW_2026-06-05.md +0 -165
  111. package/docs/TELEMETRY.md +0 -41
  112. package/docs/THREAT_MODEL.md +0 -89
  113. package/docs/VERSIONING_POLICY.md +0 -30
  114. package/docs/assets/banner-github.png +0 -0
  115. package/docs/assets/banner.png +0 -0
  116. package/docs/assets/banner.svg +0 -123
  117. package/eslint.config.js +0 -15
  118. package/fuzz/ts/harness-decode.ts +0 -136
  119. package/fuzz/ts/harness-verify.ts +0 -121
  120. package/fuzz/ts/run.ts +0 -35
  121. package/mcp-server/README.md +0 -38
  122. package/mcp-server/package-lock.json +0 -1187
  123. package/mcp-server/package.json +0 -35
  124. package/mcp-server/src/index.ts +0 -236
  125. package/mcp-server/tsconfig.json +0 -14
  126. package/scripts/aip-framework-quickstart.ts +0 -110
  127. package/scripts/aip-mcp-gateway.ts +0 -38
  128. package/scripts/aip-mcp-wrap-demo.ts +0 -72
  129. package/scripts/aip-quickstart.ts +0 -60
  130. package/scripts/bench-diff.ts +0 -118
  131. package/scripts/bench-protocol-e2e.ts +0 -937
  132. package/scripts/bench-protocol-openloop.ts +0 -1397
  133. package/scripts/bench-replay-cache.ts +0 -76
  134. package/scripts/bench-signature-profiles.ts +0 -180
  135. package/scripts/bench-wire-codecs.ts +0 -161
  136. package/scripts/build-binary-conformance.ts +0 -36
  137. package/scripts/build-release-dashboard.ts +0 -175
  138. package/scripts/canary-rollout.ts +0 -38
  139. package/scripts/mcpGatewayCli.test.ts +0 -116
  140. package/scripts/prepare-aip-package.ts +0 -88
  141. package/scripts/regen-conformance-sigs.ts +0 -18
  142. package/scripts/release-gate.ts +0 -19
  143. package/scripts/validate-runtime-policy.ts +0 -18
  144. package/sdk/browser/index.test.ts +0 -162
  145. package/sdk/browser/index.ts +0 -257
  146. package/sdk/browser/package.json +0 -13
  147. package/sdk/go/cbor.go +0 -551
  148. package/sdk/go/cbor_test.go +0 -232
  149. package/sdk/go/encryption.go +0 -280
  150. package/sdk/go/encryption_test.go +0 -318
  151. package/sdk/go/go.mod +0 -7
  152. package/sdk/go/go.sum +0 -4
  153. package/sdk/go/http.go +0 -135
  154. package/sdk/go/protocol.go +0 -324
  155. package/sdk/go/protocol_test.go +0 -334
  156. package/sdk/go/replay.go +0 -121
  157. package/sdk/go/replay_test.go +0 -149
  158. package/sdk/go/webhook.go +0 -136
  159. package/sdk/pq/package-lock.json +0 -1358
  160. package/sdk/pq/package.json +0 -42
  161. package/sdk/pq/src/index.test.ts +0 -143
  162. package/sdk/pq/src/index.ts +0 -166
  163. package/sdk/pq/tsconfig.json +0 -14
  164. package/sdk/pq/vitest.config.ts +0 -7
  165. package/sdk/python/README.md +0 -18
  166. package/sdk/python/protocol_7h3/__init__.py +0 -46
  167. package/sdk/python/protocol_7h3/encryption.py +0 -252
  168. package/sdk/python/protocol_7h3/http.py +0 -212
  169. package/sdk/python/protocol_7h3/keys.py +0 -149
  170. package/sdk/python/protocol_7h3/pq.py +0 -244
  171. package/sdk/python/protocol_7h3/protocol.py +0 -525
  172. package/sdk/python/protocol_7h3/queue.py +0 -118
  173. package/sdk/python/protocol_7h3/replay.py +0 -98
  174. package/sdk/python/protocol_7h3/webhook.py +0 -116
  175. package/sdk/python/pyproject.toml +0 -40
  176. package/sdk/python/tests/test_conformance.py +0 -110
  177. package/sdk/python/tests/test_encryption.py +0 -206
  178. package/sdk/python/tests/test_http.py +0 -305
  179. package/sdk/python/tests/test_keys.py +0 -417
  180. package/sdk/python/tests/test_queue.py +0 -120
  181. package/sdk/python/tests/test_webhook.py +0 -345
  182. package/sdk/rust/Cargo.lock +0 -371
  183. package/sdk/rust/Cargo.toml +0 -25
  184. package/sdk/rust/README.md +0 -31
  185. package/sdk/rust/fuzz/Cargo.toml +0 -29
  186. package/sdk/rust/fuzz/fuzz_targets/fuzz_canonicalize.rs +0 -46
  187. package/sdk/rust/fuzz/fuzz_targets/fuzz_decode.rs +0 -11
  188. package/sdk/rust/src/bin/aip_mcp_gateway.rs +0 -59
  189. package/sdk/rust/src/http.rs +0 -145
  190. package/sdk/rust/src/keys.rs +0 -161
  191. package/sdk/rust/src/lib.rs +0 -688
  192. package/sdk/rust/src/queue.rs +0 -79
  193. package/sdk/rust/src/webhook.rs +0 -86
  194. package/sdk/rust/tests/conformance.rs +0 -148
  195. package/sdk/rust/tests/gateway.rs +0 -130
  196. package/sdk/rust/tests/http_webhook_queue.rs +0 -201
  197. package/sdk/rust/tests/keys.rs +0 -189
  198. package/sdk/threshold/index.d.ts +0 -68
  199. package/sdk/threshold/index.d.ts.map +0 -1
  200. package/sdk/threshold/index.js +0 -254
  201. package/sdk/threshold/package-lock.json +0 -1361
  202. package/sdk/threshold/package.json +0 -39
  203. package/sdk/threshold/src/index.d.ts +0 -68
  204. package/sdk/threshold/src/index.d.ts.map +0 -1
  205. package/sdk/threshold/src/index.js +0 -254
  206. package/sdk/threshold/src/index.test.ts +0 -238
  207. package/sdk/threshold/src/index.ts +0 -355
  208. package/sdk/threshold/tsconfig.json +0 -19
  209. package/sdk/threshold/vitest.config.ts +0 -12
  210. package/src/agentAdapter.test.ts +0 -48
  211. package/src/agentAdapter.ts +0 -56
  212. package/src/auditLog.test.ts +0 -145
  213. package/src/auditLog.ts +0 -147
  214. package/src/capability.test.ts +0 -504
  215. package/src/capability.ts +0 -380
  216. package/src/cborCodec.test.ts +0 -263
  217. package/src/cborCodec.ts +0 -339
  218. package/src/conformance.test.ts +0 -136
  219. package/src/conformanceVectors.ts +0 -99
  220. package/src/encryption.test.ts +0 -206
  221. package/src/encryption.ts +0 -245
  222. package/src/envelopeCbor.ts +0 -140
  223. package/src/frameworkAdapters.test.ts +0 -290
  224. package/src/frameworkAdapters.ts +0 -261
  225. package/src/gateway.test.ts +0 -343
  226. package/src/gateway.ts +0 -246
  227. package/src/grpcBinding.test.ts +0 -211
  228. package/src/grpcBinding.ts +0 -103
  229. package/src/httpBinding.test.ts +0 -376
  230. package/src/httpBinding.ts +0 -189
  231. package/src/index.ts +0 -39
  232. package/src/keyInfra.test.ts +0 -278
  233. package/src/keyInfra.ts +0 -228
  234. package/src/keyRegistry.ts +0 -59
  235. package/src/keyRotation.test.ts +0 -78
  236. package/src/keyRotation.ts +0 -72
  237. package/src/mcpGateway.test.ts +0 -129
  238. package/src/mcpGateway.ts +0 -250
  239. package/src/mcpTransports.test.ts +0 -92
  240. package/src/mcpTransports.ts +0 -169
  241. package/src/mcpWrapper.test.ts +0 -179
  242. package/src/mcpWrapper.ts +0 -206
  243. package/src/otel.ts +0 -136
  244. package/src/policyEnforcer.test.ts +0 -99
  245. package/src/policyEnforcer.ts +0 -169
  246. package/src/policyTelemetryFeedback.test.ts +0 -25
  247. package/src/policyTelemetryFeedback.ts +0 -38
  248. package/src/protocol.bench.ts +0 -37
  249. package/src/protocol.d.ts.map +0 -1
  250. package/src/protocol.js +0 -294
  251. package/src/protocol.test.ts +0 -155
  252. package/src/protocol.ts +0 -414
  253. package/src/protocolAgent.test.ts +0 -105
  254. package/src/protocolAgent.ts +0 -169
  255. package/src/protocolBinary.test.ts +0 -165
  256. package/src/protocolBinary.ts +0 -312
  257. package/src/protocolCapabilities.ts +0 -70
  258. package/src/protocolFuzz.advanced.test.ts +0 -235
  259. package/src/protocolFuzz.test.ts +0 -111
  260. package/src/protocolNegative.test.ts +0 -97
  261. package/src/protocolReplay.test.ts +0 -71
  262. package/src/protocolReplay.ts +0 -194
  263. package/src/protocolTransport.test.ts +0 -556
  264. package/src/protocolTransport.ts +0 -483
  265. package/src/queueBinding.test.ts +0 -130
  266. package/src/queueBinding.ts +0 -102
  267. package/src/rateLimiter.test.ts +0 -96
  268. package/src/rateLimiter.ts +0 -46
  269. package/src/redisIntegration.test.ts +0 -134
  270. package/src/replayStores.test.ts +0 -273
  271. package/src/replayStores.ts +0 -215
  272. package/src/revocation.test.ts +0 -98
  273. package/src/revocation.ts +0 -0
  274. package/src/routePolicy.test.ts +0 -87
  275. package/src/routePolicy.ts +0 -72
  276. package/src/runtimePolicy.test.ts +0 -49
  277. package/src/runtimePolicy.ts +0 -81
  278. package/src/runtimePolicyManager.test.ts +0 -29
  279. package/src/runtimePolicyManager.ts +0 -50
  280. package/src/runtimePolicyPresets.ts +0 -43
  281. package/src/signedResponse.test.ts +0 -111
  282. package/src/signedResponse.ts +0 -83
  283. package/src/stream.test.ts +0 -254
  284. package/src/stream.ts +0 -417
  285. package/src/telemetry.test.ts +0 -251
  286. package/src/telemetry.ts +0 -299
  287. package/src/webhookBinding.test.ts +0 -144
  288. package/src/webhookBinding.ts +0 -115
  289. package/src/wsBinding.test.ts +0 -221
  290. package/src/wsBinding.ts +0 -200
  291. package/tsconfig.json +0 -15
  292. package/tsconfig.lib.json +0 -23
  293. package/vite.lib.config.ts +0 -16
  294. package/vitest.config.ts +0 -11
@@ -0,0 +1,35 @@
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
+ }
@@ -0,0 +1,73 @@
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>;
@@ -0,0 +1,43 @@
1
+ import { type ProtocolEnvelope } from './protocol';
2
+ export interface QueueSignOptions {
3
+ privateKey: string;
4
+ sender: string;
5
+ recipient?: string;
6
+ ttlMs?: number;
7
+ keyId?: string;
8
+ }
9
+ export interface QueueVerifyOptions {
10
+ publicKey: string;
11
+ }
12
+ export type SignedEnvelope = ProtocolEnvelope;
13
+ export interface QueueMessage<T> {
14
+ envelope: SignedEnvelope;
15
+ payload: T;
16
+ }
17
+ /**
18
+ * Signs a payload for queue transit (Kafka/SQS/Pub-Sub/RabbitMQ).
19
+ * Returns a JSON string: {"envelope": SignedEnvelope, "payload": T}
20
+ * Default TTL is 1 hour (3 600 000 ms).
21
+ */
22
+ export declare function signQueueMessage<T>(payload: T, opts: QueueSignOptions): Promise<string>;
23
+ /**
24
+ * Parses a queue message JSON string and verifies the envelope signature.
25
+ * Throws if the message is malformed or the signature is invalid.
26
+ */
27
+ export declare function verifyQueueMessage<T>(message: string, opts: QueueVerifyOptions): Promise<{
28
+ payload: T;
29
+ envelope: ProtocolEnvelope;
30
+ }>;
31
+ /**
32
+ * Verifies a batch of queue message strings.
33
+ * Never throws — returns per-message success/failure objects.
34
+ */
35
+ export declare function verifyQueueBatch<T>(messages: string[], opts: QueueVerifyOptions): Promise<Array<{
36
+ ok: true;
37
+ payload: T;
38
+ envelope: ProtocolEnvelope;
39
+ } | {
40
+ ok: false;
41
+ raw: string;
42
+ error: string;
43
+ }>>;
@@ -0,0 +1,18 @@
1
+ export type RateLimitPolicy = {
2
+ requests: number;
3
+ windowMs: number;
4
+ };
5
+ export type RateLimitResult = {
6
+ allowed: boolean;
7
+ remaining: number;
8
+ resetMs: number;
9
+ };
10
+ declare class SlidingWindowRateLimiter {
11
+ private windows;
12
+ check(key: string, policy: RateLimitPolicy, nowMs?: number): RateLimitResult;
13
+ consume(key: string, policy: RateLimitPolicy, nowMs?: number): RateLimitResult;
14
+ reset(key: string): void;
15
+ clear(): void;
16
+ }
17
+ export declare const globalRateLimiter: SlidingWindowRateLimiter;
18
+ export { SlidingWindowRateLimiter };
@@ -46,36 +46,27 @@
46
46
  * denial-of-service vector. Choose the posture that matches your threat model.
47
47
  * - See `docs/DISTRIBUTED_REPLAY.md` for full operational guidance.
48
48
  */
49
-
50
49
  export interface RedisSetOptions {
51
- /** Only set when the key does not already exist (Redis `NX`). */
52
- nx?: boolean
53
- /** Expire the key after this many milliseconds (Redis `PX`). */
54
- pxMs?: number
50
+ /** Only set when the key does not already exist (Redis `NX`). */
51
+ nx?: boolean;
52
+ /** Expire the key after this many milliseconds (Redis `PX`). */
53
+ pxMs?: number;
55
54
  }
56
-
57
55
  /** A queued, chainable batch of `set` commands flushed in a single round-trip. */
58
56
  export interface RedisPipelineLike {
59
- set(key: string, value: string, options?: RedisSetOptions): RedisPipelineLike
60
- exec(): Promise<Array<'OK' | null>>
57
+ set(key: string, value: string, options?: RedisSetOptions): RedisPipelineLike;
58
+ exec(): Promise<Array<'OK' | null>>;
61
59
  }
62
-
63
60
  export interface RedisLikeClient {
64
- /** Returns `'OK'` when the value was written, or `null` when `NX` prevented it. */
65
- set(key: string, value: string, options?: RedisSetOptions): Promise<'OK' | null>
66
- /** Truthy when the key exists and has not expired. */
67
- get?(key: string): Promise<string | null>
68
- /** Removes a key; returns the number of keys removed. */
69
- del?(key: string): Promise<number>
70
- /** Optional batch pipeline; when present, batch reserves use a single round-trip. */
71
- pipeline?(): RedisPipelineLike
61
+ /** Returns `'OK'` when the value was written, or `null` when `NX` prevented it. */
62
+ set(key: string, value: string, options?: RedisSetOptions): Promise<'OK' | null>;
63
+ /** Truthy when the key exists and has not expired. */
64
+ get?(key: string): Promise<string | null>;
65
+ /** Removes a key; returns the number of keys removed. */
66
+ del?(key: string): Promise<number>;
67
+ /** Optional batch pipeline; when present, batch reserves use a single round-trip. */
68
+ pipeline?(): RedisPipelineLike;
72
69
  }
73
-
74
- interface Entry {
75
- value: string
76
- expiresAt?: number
77
- }
78
-
79
70
  /**
80
71
  * In-memory reference implementation of {@link RedisLikeClient}.
81
72
  *
@@ -85,56 +76,15 @@ interface Entry {
85
76
  * cross-process guarantees and must not be used as a production replay store
86
77
  * for a horizontally scaled deployment.
87
78
  */
88
- export class InMemoryRedisLikeClient implements RedisLikeClient {
89
- private readonly entries = new Map<string, Entry>()
90
- private readonly now: () => number
91
-
92
- constructor(options: { now?: () => number } = {}) {
93
- this.now = options.now ?? (() => Date.now())
94
- }
95
-
96
- private live(key: string): Entry | undefined {
97
- const entry = this.entries.get(key)
98
- if (!entry) return undefined
99
- if (entry.expiresAt !== undefined && entry.expiresAt <= this.now()) {
100
- this.entries.delete(key)
101
- return undefined
102
- }
103
- return entry
104
- }
105
-
106
- async set(key: string, value: string, options: RedisSetOptions = {}): Promise<'OK' | null> {
107
- if (options.nx && this.live(key)) return null
108
- const expiresAt = options.pxMs !== undefined ? this.now() + options.pxMs : undefined
109
- this.entries.set(key, { value, expiresAt })
110
- return 'OK'
111
- }
112
-
113
- async get(key: string): Promise<string | null> {
114
- return this.live(key)?.value ?? null
115
- }
116
-
117
- async del(key: string): Promise<number> {
118
- const existed = this.live(key) !== undefined
119
- this.entries.delete(key)
120
- return existed ? 1 : 0
121
- }
122
-
123
- pipeline(): RedisPipelineLike {
124
- const commands: Array<{ key: string; value: string; options?: RedisSetOptions }> = []
125
- const pipeline: RedisPipelineLike = {
126
- set: (key: string, value: string, options?: RedisSetOptions) => {
127
- commands.push({ key, value, options })
128
- return pipeline
129
- },
130
- exec: async () => {
131
- const results: Array<'OK' | null> = []
132
- for (const command of commands) {
133
- results.push(await this.set(command.key, command.value, command.options))
134
- }
135
- return results
136
- },
137
- }
138
- return pipeline
139
- }
79
+ export declare class InMemoryRedisLikeClient implements RedisLikeClient {
80
+ private readonly entries;
81
+ private readonly now;
82
+ constructor(options?: {
83
+ now?: () => number;
84
+ });
85
+ private live;
86
+ set(key: string, value: string, options?: RedisSetOptions): Promise<'OK' | null>;
87
+ get(key: string): Promise<string | null>;
88
+ del(key: string): Promise<number>;
89
+ pipeline(): RedisPipelineLike;
140
90
  }
@@ -0,0 +1,98 @@
1
+ import type { DistributedReplayStore } from './protocolReplay';
2
+ import { type RedisLikeClient } from './redisClient';
3
+ /**
4
+ * Minimal Redis client surface required by RedisReplayStore.
5
+ *
6
+ * Distinct from the internal RedisLikeClient: this interface uses a `quit()`
7
+ * lifecycle method and does not require pipeline support, making it easy to
8
+ * adapt any Redis client (ioredis, node-redis, Upstash, etc.) without coupling
9
+ * to the internal pipeline abstraction.
10
+ */
11
+ export interface RedisClientLike {
12
+ set(key: string, value: string, opts?: {
13
+ nx?: boolean;
14
+ px?: number;
15
+ }): Promise<string | null>;
16
+ get(key: string): Promise<string | null>;
17
+ del(key: string): Promise<number | any>;
18
+ quit(): Promise<any>;
19
+ }
20
+ /**
21
+ * Gateway-facing replay store interface.
22
+ *
23
+ * `check()` atomically marks a key as seen and returns whether it was already
24
+ * present: `false` = fresh (first time seen), `true` = replay (already seen).
25
+ */
26
+ export interface ReplayStore {
27
+ check(key: string, ttlMs: number): Promise<boolean>;
28
+ }
29
+ /**
30
+ * Redis-backed implementation of {@link ReplayStore}.
31
+ *
32
+ * Uses SET … NX PX for an atomic "set if not exists with TTL" operation.
33
+ * The operation is single-round-trip and safe under concurrent access from
34
+ * multiple gateway instances.
35
+ */
36
+ export declare class RedisReplayStore implements ReplayStore {
37
+ private readonly keyPrefix;
38
+ private readonly client;
39
+ constructor(opts?: {
40
+ redisUrl?: string;
41
+ keyPrefix?: string;
42
+ client?: RedisClientLike;
43
+ });
44
+ /**
45
+ * Returns `false` if the key is fresh (first time seen — key was set in Redis),
46
+ * or `true` if the key is a replay (key already existed — SET NX returned null).
47
+ */
48
+ check(key: string, ttlMs: number): Promise<boolean>;
49
+ }
50
+ /**
51
+ * Cluster-aware replay store that wraps multiple {@link RedisReplayStore}
52
+ * instances — one per Redis shard / node.
53
+ *
54
+ * A message is treated as a replay if ANY node has already seen the nonce.
55
+ * All nodes are checked in parallel via Promise.all.
56
+ */
57
+ export declare class ClusterRedisReplayStore implements ReplayStore {
58
+ private readonly nodes;
59
+ constructor(nodes: RedisReplayStore[]);
60
+ check(key: string, ttlMs: number): Promise<boolean>;
61
+ }
62
+ /**
63
+ * Convenience factory that creates a {@link RedisReplayStore} from a URL
64
+ * or options object.
65
+ */
66
+ export declare function createRedisReplayStore(clientOrOpts: RedisLikeClient | {
67
+ redisUrl?: string;
68
+ keyPrefix?: string;
69
+ client?: RedisClientLike;
70
+ }, options?: RedisReplayStoreOptions): DistributedReplayStore;
71
+ /**
72
+ * Creates a {@link ClusterRedisReplayStore} from an array of Redis URLs.
73
+ * Each URL is used to create an independent {@link RedisReplayStore} node.
74
+ */
75
+ export declare function createClusterReplayStore(redisUrls: string[]): ClusterRedisReplayStore;
76
+ /**
77
+ * What to do when the Redis client throws (network blip, server down).
78
+ *
79
+ * - `fallback` (default): degrade to a local in-memory store so traffic keeps
80
+ * flowing with single-node replay protection still in force. Quality +
81
+ * reliability + scalability: Redis is never a fleet-wide kill switch.
82
+ * - `reject`: fail closed — deny the message because uniqueness cannot be confirmed.
83
+ * - `allow`: fail open — accept the message (skip the check) to maximise uptime.
84
+ */
85
+ export type ReplayErrorBehavior = 'fallback' | 'reject' | 'allow';
86
+ export interface RedisReplayStoreOptions {
87
+ /** Key namespace in Redis. Default `aip:replay:`. */
88
+ keyPrefix?: string;
89
+ /** Behavior when the Redis client throws. Default `fallback`. */
90
+ errorBehavior?: ReplayErrorBehavior;
91
+ /** Local store used when `errorBehavior` is `fallback`. Defaults to an in-memory-backed store. */
92
+ fallback?: DistributedReplayStore;
93
+ /** Observability hook fired whenever a Redis error forces degraded handling. */
94
+ onDegraded?: (error: unknown, context: {
95
+ key: string;
96
+ behavior: ReplayErrorBehavior;
97
+ }) => void;
98
+ }
@@ -0,0 +1,71 @@
1
+ import type { ProtocolEnvelope, SignatureVerificationMaterial } from './protocol';
2
+ import type { RedisLikeClient } from './redisClient';
3
+ /**
4
+ * A shared key-revocation list consulted on the verification hot path.
5
+ *
6
+ * `RollingKeyring` enforces revocation in-process; a `RevocationStore` makes a
7
+ * revocation effective fleet-wide: revoke a `(sender, keyId)` on one node and
8
+ * every node that consults the same store rejects it.
9
+ */
10
+ export interface RevocationStore {
11
+ isRevoked(sender: string, keyId: string, nowMs?: number): boolean | Promise<boolean>;
12
+ revoke(sender: string, keyId: string, options?: {
13
+ untilMs?: number;
14
+ }): void | Promise<void>;
15
+ }
16
+ /** Single-process revocation list (tests, local dev, single-node deployments). */
17
+ export declare class InMemoryRevocationStore implements RevocationStore {
18
+ /** keyId map value: revoked-until timestamp, or `Infinity` for permanent. */
19
+ private readonly revoked;
20
+ private readonly now;
21
+ constructor(options?: {
22
+ now?: () => number;
23
+ });
24
+ private makeKey;
25
+ isRevoked(sender: string, keyId: string, nowMs?: number): boolean;
26
+ revoke(sender: string, keyId: string, options?: {
27
+ untilMs?: number;
28
+ }): void;
29
+ }
30
+ /** Behavior when the Redis client throws while checking revocation. */
31
+ export type RevocationErrorBehavior = 'reject' | 'allow';
32
+ export interface RedisRevocationStoreOptions {
33
+ /** Key namespace in Redis. Default `aip:revoked:`. */
34
+ keyPrefix?: string;
35
+ /**
36
+ * Behavior when the Redis client throws.
37
+ * - `reject` (default): fail closed — treat the key as revoked. A revoked key
38
+ * is a compromised key; never accept on uncertainty.
39
+ * - `allow`: treat the key as not revoked (favor availability).
40
+ */
41
+ errorBehavior?: RevocationErrorBehavior;
42
+ /** Local cache freshness window in ms for `isRevoked` reads. Default 5000. */
43
+ cacheTtlMs?: number;
44
+ /** Observability hook fired whenever a Redis error forces degraded handling. */
45
+ onDegraded?: (error: unknown, context: {
46
+ sender: string;
47
+ keyId: string;
48
+ }) => void;
49
+ /** Clock override (testing). */
50
+ now?: () => number;
51
+ }
52
+ /**
53
+ * Creates a Redis-backed {@link RevocationStore}.
54
+ *
55
+ * Reads are served from a short-lived local cache so the verification hot path
56
+ * does not hit Redis on every message; known revocations therefore keep
57
+ * enforcing even through a brief Redis outage.
58
+ */
59
+ export declare function createRedisRevocationStore(client: Pick<RedisLikeClient, 'set' | 'get' | 'del'>, options?: RedisRevocationStoreOptions): RevocationStore;
60
+ type SignatureResolver = (signature: NonNullable<ProtocolEnvelope['signature']>, sender: string) => SignatureVerificationMaterial | undefined | Promise<SignatureVerificationMaterial | undefined>;
61
+ /**
62
+ * Wraps a signature resolver so that a revoked `(sender, keyId)` resolves to no
63
+ * material — which makes signature verification fail and the envelope is rejected.
64
+ *
65
+ * Compose over `createKeyringSignatureResolver` (or any resolver) and pass the
66
+ * result as the transport `signatureResolver`.
67
+ */
68
+ export declare function withRevocationCheck(resolver: SignatureResolver, store: RevocationStore, options?: {
69
+ nowMsProvider?: () => number;
70
+ }): SignatureResolver;
71
+ export {};
@@ -0,0 +1,30 @@
1
+ export type PolicyRequirement = 'ed25519' | 'hmac' | 'any' | 'none';
2
+ export interface RoutePolicy {
3
+ path: string;
4
+ require: PolicyRequirement;
5
+ rateLimit?: {
6
+ requests: number;
7
+ windowMs: number;
8
+ };
9
+ allowedSenders?: string[];
10
+ signResponse?: boolean;
11
+ }
12
+ /**
13
+ * Translate a glob pattern to a RegExp.
14
+ * Supported:
15
+ * - exact: '/health'
16
+ * - '?' → any single non-slash char
17
+ * - '*' → any chars within a single segment (no slash)
18
+ * - '**' → any chars at any depth (including slashes)
19
+ */
20
+ export declare function matchGlob(pattern: string, path: string): boolean;
21
+ /**
22
+ * Find the first matching policy for a given path.
23
+ * Returns null if no policy matches.
24
+ */
25
+ export declare function matchPolicy(policies: RoutePolicy[], path: string): RoutePolicy | null;
26
+ /**
27
+ * Check whether a sender is permitted by a policy.
28
+ * If allowedSenders is not set, all senders are allowed.
29
+ */
30
+ export declare function isAllowedSender(policy: RoutePolicy, sender: string): boolean;
@@ -0,0 +1,24 @@
1
+ export interface RuntimePolicy {
2
+ version: string;
3
+ name: string;
4
+ status: string;
5
+ owner?: string;
6
+ updated_at?: string;
7
+ hard_invariants?: Record<string, unknown>;
8
+ slo_defaults?: Record<string, unknown>;
9
+ mode_selection?: Record<string, unknown>;
10
+ guardrails?: Record<string, unknown>;
11
+ tuning?: Record<string, unknown>;
12
+ adaptive_flow?: Record<string, unknown>;
13
+ benchmark_policy?: Record<string, unknown>;
14
+ runtime_decision_tree?: unknown[];
15
+ operator_handoff_required_fields?: string[];
16
+ [key: string]: unknown;
17
+ }
18
+ export interface LoadRuntimePolicyOptions {
19
+ path?: string;
20
+ readTextFile?: (filePath: string) => Promise<string>;
21
+ }
22
+ export declare function validateRuntimePolicy(value: unknown): RuntimePolicy;
23
+ export declare function parseRuntimePolicyJson(jsonText: string): RuntimePolicy;
24
+ export declare function loadRuntimePolicy(options?: LoadRuntimePolicyOptions): Promise<RuntimePolicy>;
@@ -0,0 +1,15 @@
1
+ import { type BootstrapRuntimePolicyEnforcerOptions, type PolicyEnforcer } from './policyEnforcer';
2
+ import type { RuntimePolicy } from './runtimePolicy';
3
+ export interface RuntimePolicySnapshot {
4
+ policy: RuntimePolicy;
5
+ enforcer: PolicyEnforcer;
6
+ loadedAtMs: number;
7
+ }
8
+ export declare class RuntimePolicyManager {
9
+ private snapshot;
10
+ private readonly options;
11
+ constructor(options?: BootstrapRuntimePolicyEnforcerOptions);
12
+ loadInitial(): Promise<RuntimePolicySnapshot>;
13
+ current(): RuntimePolicySnapshot;
14
+ refresh(): Promise<RuntimePolicySnapshot>;
15
+ }
@@ -0,0 +1,11 @@
1
+ import type { RuntimeMode } from './policyEnforcer';
2
+ export type RuntimeEnvironment = 'dev' | 'staging' | 'prod';
3
+ export interface RuntimeTuningPreset {
4
+ environment: RuntimeEnvironment;
5
+ mode: RuntimeMode;
6
+ poolSize: number;
7
+ batchSize: number;
8
+ inflightCap: number;
9
+ retryMaxAttempts: number;
10
+ }
11
+ export declare function getRuntimeTuningPreset(environment: RuntimeEnvironment): RuntimeTuningPreset;
@@ -0,0 +1,21 @@
1
+ import { type ProtocolEnvelope } from './protocol';
2
+ export declare const RESPONSE_HEADER = "x-7h3-response";
3
+ export declare function signResponse(body: string, opts: {
4
+ privateKey: string;
5
+ sender: string;
6
+ recipient?: string;
7
+ correlationId?: string;
8
+ ttlMs?: number;
9
+ }): Promise<{
10
+ headers: {
11
+ 'x-7h3-response': string;
12
+ };
13
+ }>;
14
+ export declare function verifyResponse(body: string, headers: Record<string, string | string[] | undefined>, opts: {
15
+ publicKey: string;
16
+ maxAgeMs?: number;
17
+ }): Promise<{
18
+ ok: boolean;
19
+ envelope?: ProtocolEnvelope;
20
+ reason?: string;
21
+ }>;
package/stream.d.ts ADDED
@@ -0,0 +1,59 @@
1
+ export interface StreamChunk {
2
+ i: number;
3
+ d: string;
4
+ h: string;
5
+ f: boolean;
6
+ sig?: string;
7
+ kid?: string;
8
+ }
9
+ export interface StreamSignerOpts {
10
+ privateKey: string;
11
+ sender: string;
12
+ nonce?: string;
13
+ keyId?: string;
14
+ }
15
+ export interface StreamVerifierOpts {
16
+ publicKey: string;
17
+ maxChunks?: number;
18
+ }
19
+ export type StreamVerifyResult = {
20
+ ok: true;
21
+ totalBytes: number;
22
+ chunkCount: number;
23
+ } | {
24
+ ok: false;
25
+ reason: string;
26
+ chunkIndex?: number;
27
+ };
28
+ export declare const STREAM_HEADER = "x-7h3-stream";
29
+ export declare class SignedStreamWriter {
30
+ private readonly opts;
31
+ private seq;
32
+ private readonly accum;
33
+ private hmacKeyPromise;
34
+ constructor(opts: StreamSignerOpts);
35
+ get nonce(): string;
36
+ private getHmacKey;
37
+ private computeChunkHmac;
38
+ writeChunk(data: string): Promise<StreamChunk>;
39
+ finalize(): Promise<StreamChunk>;
40
+ }
41
+ export declare class SignedStreamReader {
42
+ private readonly opts;
43
+ private expectedSeq;
44
+ private readonly accum;
45
+ private totalBytes;
46
+ private done;
47
+ constructor(opts: StreamVerifierOpts);
48
+ receiveChunk(chunk: StreamChunk): Promise<{
49
+ ok: boolean;
50
+ reason?: string;
51
+ }>;
52
+ finalize(finalChunk: StreamChunk): Promise<StreamVerifyResult>;
53
+ }
54
+ export declare function createSignedStream(opts: StreamSignerOpts): SignedStreamWriter;
55
+ export declare function createStreamVerifier(opts: StreamVerifierOpts): SignedStreamReader;
56
+ export declare function signStream(chunks: AsyncIterable<string> | string[], opts: StreamSignerOpts): Promise<StreamChunk[]>;
57
+ export declare function verifyStream(chunks: StreamChunk[], opts: StreamVerifierOpts): Promise<StreamVerifyResult>;
58
+ export declare function encodeStreamChunk(chunk: StreamChunk): string;
59
+ export declare function decodeStreamChunk(raw: string): StreamChunk;