@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
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Fuzz harness: wire decoder resilience.
3
+ *
4
+ * Invariant: decodeEnvelope must NEVER throw on any input — arbitrary strings
5
+ * and arbitrary bytes both. On garbage it must return {ok: false}.
6
+ *
7
+ * Strategy: start from the conformance corpus, apply mutations, run N rounds.
8
+ */
9
+
10
+ import { readFileSync } from 'node:fs'
11
+ import { join, dirname } from 'node:path'
12
+ import { fileURLToPath } from 'node:url'
13
+ import { decodeEnvelope } from '../../src/index.js'
14
+
15
+ const __dir = dirname(fileURLToPath(import.meta.url))
16
+ const VECTORS_PATH = join(__dir, '../../conformance/7h3_v0_1.json')
17
+ const ROUNDS = parseInt(process.env.FUZZ_ROUNDS ?? '50000', 10)
18
+
19
+ const { vectors, ed25519Vectors = [] } = JSON.parse(readFileSync(VECTORS_PATH, 'utf-8'))
20
+
21
+ // --- corpus: valid JSON and compact encodings from conformance vectors ---
22
+ const corpus: (string | Uint8Array)[] = []
23
+ for (const v of [...vectors, ...ed25519Vectors]) {
24
+ const env = v.envelope
25
+ corpus.push(JSON.stringify(env))
26
+ // compact encoding
27
+ corpus.push(
28
+ JSON.stringify({
29
+ v: env.header?.version,
30
+ mid: env.header?.messageId,
31
+ ts: env.header?.timestampMs,
32
+ ttl: env.header?.ttlMs,
33
+ s: env.header?.sender,
34
+ n: env.header?.nonce,
35
+ i: env.body?.intent,
36
+ c: env.body?.content,
37
+ }),
38
+ )
39
+ }
40
+ // seed with known-bad corpus
41
+ corpus.push('', '{}', '[]', 'null', '"string"', '{', '{"header":{}}', '{"header":{},"body":{}}')
42
+
43
+ // --- mutators ---
44
+ type Mutator = (input: string, rand: () => number) => string
45
+
46
+ const mutators: Mutator[] = [
47
+ // bit flip a byte
48
+ (s, r) => {
49
+ const buf = Buffer.from(s, 'utf-8')
50
+ if (!buf.length) return s
51
+ buf[Math.floor(r() * buf.length)] ^= 1 << Math.floor(r() * 8)
52
+ return buf.toString('utf-8')
53
+ },
54
+ // insert random byte
55
+ (s, r) => {
56
+ const buf = Buffer.from(s, 'utf-8')
57
+ const idx = Math.floor(r() * (buf.length + 1))
58
+ const b = Math.floor(r() * 256)
59
+ return Buffer.concat([buf.subarray(0, idx), Buffer.from([b]), buf.subarray(idx)]).toString('utf-8')
60
+ },
61
+ // delete a byte
62
+ (s, r) => {
63
+ const buf = Buffer.from(s, 'utf-8')
64
+ if (!buf.length) return s
65
+ const idx = Math.floor(r() * buf.length)
66
+ return Buffer.concat([buf.subarray(0, idx), buf.subarray(idx + 1)]).toString('utf-8')
67
+ },
68
+ // truncate
69
+ (s, r) => {
70
+ const buf = Buffer.from(s, 'utf-8')
71
+ return buf.subarray(0, Math.floor(r() * buf.length)).toString('utf-8')
72
+ },
73
+ // mutate a JSON field
74
+ (s, r) => {
75
+ try {
76
+ const obj = JSON.parse(s) as Record<string, unknown>
77
+ const keys = Object.keys(obj)
78
+ if (!keys.length) return s
79
+ const key = keys[Math.floor(r() * keys.length)]
80
+ const replacement = [null, 0, 1, -1, '', [], {}, true, false][Math.floor(r() * 9)]
81
+ obj[key] = replacement
82
+ return JSON.stringify(obj)
83
+ } catch {
84
+ return s
85
+ }
86
+ },
87
+ // replace a known token with another
88
+ (s, r) => {
89
+ const tokens = ['7h3/0.1', 'TASK', 'PING', 'RESULT', 'HS256', 'ED25519', '"sender"', '"body"']
90
+ const replacements = ['aip/0.2', 'INVALID', '', '0', 'NONE', 'RSA', '"SENDER"', '"Body"']
91
+ const i = Math.floor(r() * tokens.length)
92
+ return s.split(tokens[i]).join(replacements[i])
93
+ },
94
+ ]
95
+
96
+ // --- runner ---
97
+ let crashes = 0
98
+ let okFalse = 0
99
+ let okTrue = 0
100
+
101
+ function rand(): number {
102
+ return Math.random()
103
+ }
104
+
105
+ let current = corpus[0] as string
106
+
107
+ for (let i = 0; i < ROUNDS; i++) {
108
+ // pick a mutator and apply it
109
+ const mutator = mutators[Math.floor(rand() * mutators.length)]
110
+ current = mutator(current, rand)
111
+
112
+ // occasionally reset to a fresh corpus item
113
+ if (i % 500 === 0) {
114
+ current = corpus[Math.floor(rand() * corpus.length)] as string
115
+ }
116
+
117
+ try {
118
+ const result = decodeEnvelope(current)
119
+ if (result.ok) {
120
+ okTrue++
121
+ } else {
122
+ okFalse++
123
+ }
124
+ } catch (err) {
125
+ crashes++
126
+ console.error(`\nCRASH at round ${i}:`)
127
+ console.error(' Input (first 200 chars):', JSON.stringify(current.slice(0, 200)))
128
+ console.error(' Error:', err)
129
+ }
130
+ }
131
+
132
+ console.log(`[harness-decode] rounds=${ROUNDS} ok=${okTrue} ok:false=${okFalse} crashes=${crashes}`)
133
+ if (crashes > 0) {
134
+ console.error(`FAIL: ${crashes} crash(es) detected`)
135
+ process.exit(1)
136
+ }
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Fuzz harness: signature verification with tampered envelopes.
3
+ *
4
+ * Invariants:
5
+ * 1. verifyEnvelopeHmac must NEVER throw — tampered or malformed envelopes
6
+ * must return false, not crash.
7
+ * 2. A valid envelope always verifies as true (regression check).
8
+ * 3. Single-byte tampering of any signed field must make verification fail.
9
+ *
10
+ * Strategy: start from valid signed envelopes, apply structural and byte mutations.
11
+ */
12
+
13
+ import { readFileSync } from 'node:fs'
14
+ import { join, dirname } from 'node:path'
15
+ import { fileURLToPath } from 'node:url'
16
+ import { createEnvelope, signEnvelopeHmac, verifyEnvelopeHmac } from '../../src/index.js'
17
+
18
+ const __dir = dirname(fileURLToPath(import.meta.url))
19
+ const VECTORS_PATH = join(__dir, '../../conformance/7h3_v0_1.json')
20
+ const ROUNDS = parseInt(process.env.FUZZ_ROUNDS ?? '20000', 10)
21
+
22
+ const { vectors } = JSON.parse(readFileSync(VECTORS_PATH, 'utf-8'))
23
+
24
+ const SECRET = vectors[0].secret as string
25
+
26
+ // Build and sign a fresh envelope so we have a known-valid baseline
27
+ const BASE_ENVELOPE = await signEnvelopeHmac(
28
+ createEnvelope({ sender: 'fuzzer', recipient: 'target', intent: 'TASK', content: 'baseline' }),
29
+ SECRET,
30
+ )
31
+
32
+ // Regression: valid envelope must verify
33
+ const baseOk = await verifyEnvelopeHmac(BASE_ENVELOPE, SECRET)
34
+ if (!baseOk) {
35
+ console.error('FAIL: baseline verification returned false — test setup error')
36
+ process.exit(1)
37
+ }
38
+
39
+ // --- corpus of tampered envelopes ---
40
+ function deepClone<T>(x: T): T {
41
+ return JSON.parse(JSON.stringify(x)) as T
42
+ }
43
+
44
+ type Env = typeof BASE_ENVELOPE
45
+
46
+ async function tamper(env: Env, rand: () => number): Promise<Env> {
47
+ const e = deepClone(env)
48
+ const target = rand() < 0.5 ? 'header' : 'body'
49
+ const obj = e[target] as unknown as Record<string, unknown>
50
+ const keys = Object.keys(obj)
51
+ const key = keys[Math.floor(rand() * keys.length)]
52
+ const v = obj[key]
53
+ // Mutate the value
54
+ if (typeof v === 'string') {
55
+ if (v.length === 0) {
56
+ obj[key] = 'mutated'
57
+ } else {
58
+ const buf = Buffer.from(v, 'utf-8')
59
+ const idx = Math.floor(rand() * buf.length)
60
+ buf[idx] ^= 1 << Math.floor(rand() * 8)
61
+ obj[key] = buf.toString('utf-8')
62
+ }
63
+ } else if (typeof v === 'number') {
64
+ // Ensure delta is non-zero: map [0, 999] → [-500, -1] ∪ [1, 500]
65
+ const raw = Math.floor(rand() * 1000)
66
+ const delta = raw < 500 ? raw - 500 : raw - 499 // skips 0
67
+ obj[key] = v + delta
68
+ } else {
69
+ obj[key] = null
70
+ }
71
+
72
+ // Guard: if the mutation produced no net change (e.g. bit flip round-tripped
73
+ // through invalid UTF-8 to the same replacement character), force a known change.
74
+ if (JSON.stringify(e) === JSON.stringify(env)) {
75
+ const guard = e.body as unknown as Record<string, unknown>
76
+ guard['content'] = '__forced_tamper__'
77
+ }
78
+
79
+ return e
80
+ }
81
+
82
+ // --- runner ---
83
+ let crashes = 0
84
+ let tamperFalsePositive = 0
85
+
86
+ for (let i = 0; i < ROUNDS; i++) {
87
+ const rand = () => Math.random()
88
+ const tampered = await tamper(BASE_ENVELOPE, rand)
89
+
90
+ try {
91
+ const result = await verifyEnvelopeHmac(tampered, SECRET)
92
+ if (result === true) {
93
+ tamperFalsePositive++
94
+ console.error(`\nFAIL false positive at round ${i} — tampered envelope verified as ok`)
95
+ console.error(' Tampered:', JSON.stringify(tampered).slice(0, 300))
96
+ }
97
+ } catch (err) {
98
+ crashes++
99
+ console.error(`\nCRASH at round ${i}:`)
100
+ console.error(' Input:', JSON.stringify(tampered).slice(0, 300))
101
+ console.error(' Error:', err)
102
+ }
103
+
104
+ // Occasionally test with a structurally broken envelope (missing fields)
105
+ if (i % 200 === 0) {
106
+ const broken = { header: {}, body: {}, signature: BASE_ENVELOPE.signature } as unknown as Env
107
+ try {
108
+ await verifyEnvelopeHmac(broken, SECRET)
109
+ } catch (err) {
110
+ crashes++
111
+ console.error(`\nCRASH (broken envelope) at round ${i}:`, err)
112
+ }
113
+ }
114
+ }
115
+
116
+ console.log(
117
+ `[harness-verify] rounds=${ROUNDS} tamper-false-positives=${tamperFalsePositive} crashes=${crashes}`,
118
+ )
119
+ if (crashes > 0 || tamperFalsePositive > 0) {
120
+ process.exit(1)
121
+ }
package/fuzz/ts/run.ts ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Fuzz campaign runner — executes all TypeScript harnesses in sequence.
3
+ *
4
+ * Usage:
5
+ * npm run fuzz:ts # default 50k/20k rounds
6
+ * FUZZ_ROUNDS=200000 npm run fuzz:ts
7
+ */
8
+
9
+ import { spawnSync } from 'node:child_process'
10
+ import { dirname, join } from 'node:path'
11
+ import { fileURLToPath } from 'node:url'
12
+
13
+ const __dir = dirname(fileURLToPath(import.meta.url))
14
+
15
+ const HARNESSES = ['harness-decode.ts', 'harness-verify.ts']
16
+
17
+ let failed = false
18
+ for (const harness of HARNESSES) {
19
+ process.stdout.write(`Running ${harness} ... `)
20
+ const result = spawnSync('npx', ['tsx', join(__dir, harness)], {
21
+ stdio: ['ignore', 'pipe', 'pipe'],
22
+ env: { ...process.env },
23
+ })
24
+ const out = result.stdout.toString().trim()
25
+ const err = result.stderr.toString().trim()
26
+ if (result.status !== 0) {
27
+ console.error(`FAIL\n${out}\n${err}`)
28
+ failed = true
29
+ } else {
30
+ console.log(`PASS ${out}`)
31
+ if (err) console.error(err)
32
+ }
33
+ }
34
+
35
+ process.exit(failed ? 1 : 0)
@@ -0,0 +1,38 @@
1
+ # @7h3/protocol-mcp
2
+
3
+ MCP server for [@7h3/protocol](https://github.com/IceMasterT/7h3-protocol-aip) — install into Claude to generate AIP secrets, keypairs, and server boilerplate.
4
+
5
+ ## Install into Claude Code
6
+
7
+ ```bash
8
+ claude mcp add aip -- npx @7h3/protocol-mcp
9
+ ```
10
+
11
+ ## Install into Claude Desktop
12
+
13
+ Add to your `claude_desktop_config.json`:
14
+
15
+ ```json
16
+ {
17
+ "mcpServers": {
18
+ "aip": {
19
+ "command": "npx",
20
+ "args": ["@7h3/protocol-mcp"]
21
+ }
22
+ }
23
+ }
24
+ ```
25
+
26
+ ## Tools
27
+
28
+ | Tool | What it does |
29
+ |---|---|
30
+ | `aip_generate_secret` | Generates a 32-byte HMAC secret — store as `AIP_SECRET` |
31
+ | `aip_generate_keypair` | Generates an Ed25519 keypair — store keys as env vars |
32
+ | `aip_wrap_mcp_server` | Outputs ready-to-paste boilerplate for your MCP server |
33
+ | `aip_sign` | Signs a test envelope (debugging / fixture generation) |
34
+ | `aip_verify` | Verifies an envelope signature and shape |
35
+
36
+ ## License
37
+
38
+ MIT