bla-agents 1.1.0 → 1.5.3

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 (276) hide show
  1. package/.agents/skills/blind-llm-agents/SKILL.md +20 -14
  2. package/DISCLAIMER.md +15 -7
  3. package/README.md +153 -198
  4. package/dist/bundler/index.d.ts +19 -2
  5. package/dist/bundler/index.d.ts.map +1 -1
  6. package/dist/bundler/index.js +47 -4
  7. package/dist/bundler/index.js.map +1 -1
  8. package/dist/cli.d.ts +5 -0
  9. package/dist/cli.d.ts.map +1 -1
  10. package/dist/cli.js +123 -18
  11. package/dist/cli.js.map +1 -1
  12. package/dist/core/config.d.ts +54 -0
  13. package/dist/core/config.d.ts.map +1 -0
  14. package/dist/core/config.js +160 -0
  15. package/dist/core/config.js.map +1 -0
  16. package/dist/core/coverage-contract.d.ts +97 -0
  17. package/dist/core/coverage-contract.d.ts.map +1 -0
  18. package/dist/core/coverage-contract.js +164 -0
  19. package/dist/core/coverage-contract.js.map +1 -0
  20. package/dist/core/debug-posture.d.ts +40 -0
  21. package/dist/core/debug-posture.d.ts.map +1 -0
  22. package/dist/core/debug-posture.js +197 -0
  23. package/dist/core/debug-posture.js.map +1 -0
  24. package/dist/core/detector.d.ts.map +1 -1
  25. package/dist/core/detector.js +58 -6
  26. package/dist/core/detector.js.map +1 -1
  27. package/dist/core/identifiers.d.ts +32 -0
  28. package/dist/core/identifiers.d.ts.map +1 -0
  29. package/dist/core/identifiers.js +263 -0
  30. package/dist/core/identifiers.js.map +1 -0
  31. package/dist/core/llm-directives.d.ts +12 -0
  32. package/dist/core/llm-directives.d.ts.map +1 -0
  33. package/dist/core/llm-directives.js +23 -0
  34. package/dist/core/llm-directives.js.map +1 -0
  35. package/dist/core/prng.d.ts +10 -1
  36. package/dist/core/prng.d.ts.map +1 -1
  37. package/dist/core/prng.js +27 -2
  38. package/dist/core/prng.js.map +1 -1
  39. package/dist/core/release-plan.d.ts +68 -0
  40. package/dist/core/release-plan.d.ts.map +1 -0
  41. package/dist/core/release-plan.js +235 -0
  42. package/dist/core/release-plan.js.map +1 -0
  43. package/dist/core/sarif.d.ts +53 -0
  44. package/dist/core/sarif.d.ts.map +1 -0
  45. package/dist/core/sarif.js +91 -0
  46. package/dist/core/sarif.js.map +1 -0
  47. package/dist/core/sqlite-runtime.d.ts +13 -0
  48. package/dist/core/sqlite-runtime.d.ts.map +1 -1
  49. package/dist/core/sqlite-runtime.js +38 -8
  50. package/dist/core/sqlite-runtime.js.map +1 -1
  51. package/dist/core/types.d.ts +7 -2
  52. package/dist/core/types.d.ts.map +1 -1
  53. package/dist/engine/auditor.d.ts.map +1 -1
  54. package/dist/engine/auditor.js +251 -8
  55. package/dist/engine/auditor.js.map +1 -1
  56. package/dist/engine/benchmark.d.ts +1 -1
  57. package/dist/engine/benchmark.d.ts.map +1 -1
  58. package/dist/engine/benchmark.js +121 -41
  59. package/dist/engine/benchmark.js.map +1 -1
  60. package/dist/engine/defender.d.ts +1 -0
  61. package/dist/engine/defender.d.ts.map +1 -1
  62. package/dist/engine/defender.js +7 -1
  63. package/dist/engine/defender.js.map +1 -1
  64. package/dist/engine/harden.d.ts +61 -0
  65. package/dist/engine/harden.d.ts.map +1 -0
  66. package/dist/engine/harden.js +292 -0
  67. package/dist/engine/harden.js.map +1 -0
  68. package/dist/engine/protector.d.ts.map +1 -1
  69. package/dist/engine/protector.js +162 -21
  70. package/dist/engine/protector.js.map +1 -1
  71. package/dist/identity.d.ts +112 -2
  72. package/dist/identity.d.ts.map +1 -1
  73. package/dist/identity.js +112 -2
  74. package/dist/identity.js.map +1 -1
  75. package/dist/index.d.ts +26 -9
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +26 -9
  78. package/dist/index.js.map +1 -1
  79. package/dist/mcp/server.d.ts +59 -152
  80. package/dist/mcp/server.d.ts.map +1 -1
  81. package/dist/mcp/server.js +466 -50
  82. package/dist/mcp/server.js.map +1 -1
  83. package/dist/setup/clients.d.ts +49 -1
  84. package/dist/setup/clients.d.ts.map +1 -1
  85. package/dist/setup/clients.js +1193 -20
  86. package/dist/setup/clients.js.map +1 -1
  87. package/dist/setup/doctor.d.ts +58 -14
  88. package/dist/setup/doctor.d.ts.map +1 -1
  89. package/dist/setup/doctor.js +316 -22
  90. package/dist/setup/doctor.js.map +1 -1
  91. package/dist/setup/setup.d.ts +77 -7
  92. package/dist/setup/setup.d.ts.map +1 -1
  93. package/dist/setup/setup.js +591 -62
  94. package/dist/setup/setup.js.map +1 -1
  95. package/dist/shields/chaff/chaff-generator.d.ts.map +1 -1
  96. package/dist/shields/chaff/chaff-generator.js +12 -3
  97. package/dist/shields/chaff/chaff-generator.js.map +1 -1
  98. package/dist/shields/deception/architecture-mirage.js +1 -1
  99. package/dist/shields/deception/architecture-mirage.js.map +1 -1
  100. package/dist/shields/deception/canary-honeypot.d.ts +33 -0
  101. package/dist/shields/deception/canary-honeypot.d.ts.map +1 -0
  102. package/dist/shields/deception/canary-honeypot.js +95 -0
  103. package/dist/shields/deception/canary-honeypot.js.map +1 -0
  104. package/dist/shields/deception/cognitive-armor-trigger.d.ts +43 -0
  105. package/dist/shields/deception/cognitive-armor-trigger.d.ts.map +1 -0
  106. package/dist/shields/deception/cognitive-armor-trigger.js +204 -0
  107. package/dist/shields/deception/cognitive-armor-trigger.js.map +1 -0
  108. package/dist/shields/deception/crash-trace-decoy.js +1 -1
  109. package/dist/shields/deception/crash-trace-decoy.js.map +1 -1
  110. package/dist/shields/deception/decompiler-illusion.js +1 -1
  111. package/dist/shields/deception/decompiler-illusion.js.map +1 -1
  112. package/dist/shields/deception/diff-noise-injector.js +1 -1
  113. package/dist/shields/deception/diff-noise-injector.js.map +1 -1
  114. package/dist/shields/deception/evidence-contract-poison.js +1 -1
  115. package/dist/shields/deception/evidence-contract-poison.js.map +1 -1
  116. package/dist/shields/deception/format-payloads.d.ts +21 -0
  117. package/dist/shields/deception/format-payloads.d.ts.map +1 -0
  118. package/dist/shields/deception/format-payloads.js +24 -0
  119. package/dist/shields/deception/format-payloads.js.map +1 -0
  120. package/dist/shields/deception/index.d.ts +10 -2
  121. package/dist/shields/deception/index.d.ts.map +1 -1
  122. package/dist/shields/deception/index.js +20 -3
  123. package/dist/shields/deception/index.js.map +1 -1
  124. package/dist/shields/deception/prompt-completion-poison.d.ts +3 -2
  125. package/dist/shields/deception/prompt-completion-poison.d.ts.map +1 -1
  126. package/dist/shields/deception/prompt-completion-poison.js +6 -3
  127. package/dist/shields/deception/prompt-completion-poison.js.map +1 -1
  128. package/dist/shields/deception/shadow-business-logic.js +4 -4
  129. package/dist/shields/deception/shadow-business-logic.js.map +1 -1
  130. package/dist/shields/deception/system-diagnostic-decoy.d.ts +36 -0
  131. package/dist/shields/deception/system-diagnostic-decoy.d.ts.map +1 -0
  132. package/dist/shields/deception/system-diagnostic-decoy.js +101 -0
  133. package/dist/shields/deception/system-diagnostic-decoy.js.map +1 -0
  134. package/dist/shields/exhaustion/asar-header-amplifier.d.ts +12 -3
  135. package/dist/shields/exhaustion/asar-header-amplifier.d.ts.map +1 -1
  136. package/dist/shields/exhaustion/asar-header-amplifier.js +30 -8
  137. package/dist/shields/exhaustion/asar-header-amplifier.js.map +1 -1
  138. package/dist/shields/exhaustion/bpe-token-amplifier.js +2 -2
  139. package/dist/shields/exhaustion/bpe-token-amplifier.js.map +1 -1
  140. package/dist/shields/exhaustion/callgraph-labyrinth.js +2 -2
  141. package/dist/shields/exhaustion/callgraph-labyrinth.js.map +1 -1
  142. package/dist/shields/exhaustion/cdp-shape-budget-breaker.js +1 -1
  143. package/dist/shields/exhaustion/cdp-shape-budget-breaker.js.map +1 -1
  144. package/dist/shields/exhaustion/frida-capture-saturation.d.ts +10 -5
  145. package/dist/shields/exhaustion/frida-capture-saturation.d.ts.map +1 -1
  146. package/dist/shields/exhaustion/frida-capture-saturation.js +21 -8
  147. package/dist/shields/exhaustion/frida-capture-saturation.js.map +1 -1
  148. package/dist/shields/exhaustion/index.d.ts +2 -2
  149. package/dist/shields/exhaustion/index.d.ts.map +1 -1
  150. package/dist/shields/exhaustion/index.js +2 -2
  151. package/dist/shields/exhaustion/index.js.map +1 -1
  152. package/dist/shields/exhaustion/obligation-flooder.d.ts +17 -5
  153. package/dist/shields/exhaustion/obligation-flooder.d.ts.map +1 -1
  154. package/dist/shields/exhaustion/obligation-flooder.js +20 -8
  155. package/dist/shields/exhaustion/obligation-flooder.js.map +1 -1
  156. package/dist/shields/exhaustion/rea-budget-matrix.d.ts +8 -2
  157. package/dist/shields/exhaustion/rea-budget-matrix.d.ts.map +1 -1
  158. package/dist/shields/exhaustion/rea-budget-matrix.js +139 -16
  159. package/dist/shields/exhaustion/rea-budget-matrix.js.map +1 -1
  160. package/dist/shields/exhaustion/regex-worker-tarpit.d.ts.map +1 -1
  161. package/dist/shields/exhaustion/regex-worker-tarpit.js +2 -1
  162. package/dist/shields/exhaustion/regex-worker-tarpit.js.map +1 -1
  163. package/dist/shields/exhaustion/wasm-interface-exhaustion.d.ts +7 -4
  164. package/dist/shields/exhaustion/wasm-interface-exhaustion.d.ts.map +1 -1
  165. package/dist/shields/exhaustion/wasm-interface-exhaustion.js +16 -7
  166. package/dist/shields/exhaustion/wasm-interface-exhaustion.js.map +1 -1
  167. package/dist/shields/formats/android-dex-xref.d.ts +19 -0
  168. package/dist/shields/formats/android-dex-xref.d.ts.map +1 -0
  169. package/dist/shields/formats/android-dex-xref.js +427 -0
  170. package/dist/shields/formats/android-dex-xref.js.map +1 -0
  171. package/dist/shields/formats/android-manifest.d.ts +44 -0
  172. package/dist/shields/formats/android-manifest.d.ts.map +1 -0
  173. package/dist/shields/formats/android-manifest.js +240 -0
  174. package/dist/shields/formats/android-manifest.js.map +1 -0
  175. package/dist/shields/formats/android-r8.d.ts +44 -0
  176. package/dist/shields/formats/android-r8.d.ts.map +1 -0
  177. package/dist/shields/formats/android-r8.js +246 -0
  178. package/dist/shields/formats/android-r8.js.map +1 -0
  179. package/dist/shields/formats/apple-plist.d.ts +15 -0
  180. package/dist/shields/formats/apple-plist.d.ts.map +1 -1
  181. package/dist/shields/formats/apple-plist.js +59 -1
  182. package/dist/shields/formats/apple-plist.js.map +1 -1
  183. package/dist/shields/formats/archive.d.ts +27 -6
  184. package/dist/shields/formats/archive.d.ts.map +1 -1
  185. package/dist/shields/formats/archive.js +247 -45
  186. package/dist/shields/formats/archive.js.map +1 -1
  187. package/dist/shields/formats/asar.d.ts +50 -10
  188. package/dist/shields/formats/asar.d.ts.map +1 -1
  189. package/dist/shields/formats/asar.js +265 -39
  190. package/dist/shields/formats/asar.js.map +1 -1
  191. package/dist/shields/formats/bun-standalone.d.ts +78 -0
  192. package/dist/shields/formats/bun-standalone.d.ts.map +1 -0
  193. package/dist/shields/formats/bun-standalone.js +272 -0
  194. package/dist/shields/formats/bun-standalone.js.map +1 -0
  195. package/dist/shields/formats/dotnet-managed.d.ts +9 -0
  196. package/dist/shields/formats/dotnet-managed.d.ts.map +1 -1
  197. package/dist/shields/formats/dotnet-managed.js +26 -1
  198. package/dist/shields/formats/dotnet-managed.js.map +1 -1
  199. package/dist/shields/formats/electron-fuses.d.ts +63 -8
  200. package/dist/shields/formats/electron-fuses.d.ts.map +1 -1
  201. package/dist/shields/formats/electron-fuses.js +297 -65
  202. package/dist/shields/formats/electron-fuses.js.map +1 -1
  203. package/dist/shields/formats/erlang-beam.d.ts +34 -0
  204. package/dist/shields/formats/erlang-beam.d.ts.map +1 -0
  205. package/dist/shields/formats/erlang-beam.js +319 -0
  206. package/dist/shields/formats/erlang-beam.js.map +1 -0
  207. package/dist/shields/formats/evm-bytecode.d.ts +28 -0
  208. package/dist/shields/formats/evm-bytecode.d.ts.map +1 -0
  209. package/dist/shields/formats/evm-bytecode.js +124 -0
  210. package/dist/shields/formats/evm-bytecode.js.map +1 -0
  211. package/dist/shields/formats/go-flutter-exhaustion.d.ts +55 -0
  212. package/dist/shields/formats/go-flutter-exhaustion.d.ts.map +1 -0
  213. package/dist/shields/formats/go-flutter-exhaustion.js +346 -0
  214. package/dist/shields/formats/go-flutter-exhaustion.js.map +1 -0
  215. package/dist/shields/formats/gpu-ptx.d.ts +40 -0
  216. package/dist/shields/formats/gpu-ptx.d.ts.map +1 -0
  217. package/dist/shields/formats/gpu-ptx.js +62 -0
  218. package/dist/shields/formats/gpu-ptx.js.map +1 -0
  219. package/dist/shields/formats/headers.d.ts.map +1 -1
  220. package/dist/shields/formats/headers.js +54 -14
  221. package/dist/shields/formats/headers.js.map +1 -1
  222. package/dist/shields/formats/jvm-bytecode.d.ts +20 -0
  223. package/dist/shields/formats/jvm-bytecode.d.ts.map +1 -0
  224. package/dist/shields/formats/jvm-bytecode.js +134 -0
  225. package/dist/shields/formats/jvm-bytecode.js.map +1 -0
  226. package/dist/shields/formats/mobile-game.d.ts +4 -0
  227. package/dist/shields/formats/mobile-game.d.ts.map +1 -1
  228. package/dist/shields/formats/mobile-game.js +16 -0
  229. package/dist/shields/formats/mobile-game.js.map +1 -1
  230. package/dist/shields/formats/model.d.ts +22 -8
  231. package/dist/shields/formats/model.d.ts.map +1 -1
  232. package/dist/shields/formats/model.js +231 -59
  233. package/dist/shields/formats/model.js.map +1 -1
  234. package/dist/shields/formats/native.d.ts +65 -11
  235. package/dist/shields/formats/native.d.ts.map +1 -1
  236. package/dist/shields/formats/native.js +413 -108
  237. package/dist/shields/formats/native.js.map +1 -1
  238. package/dist/shields/formats/pcap-capture.d.ts +27 -0
  239. package/dist/shields/formats/pcap-capture.d.ts.map +1 -0
  240. package/dist/shields/formats/pcap-capture.js +201 -0
  241. package/dist/shields/formats/pcap-capture.js.map +1 -0
  242. package/dist/shields/formats/python.d.ts +22 -1
  243. package/dist/shields/formats/python.d.ts.map +1 -1
  244. package/dist/shields/formats/python.js +568 -27
  245. package/dist/shields/formats/python.js.map +1 -1
  246. package/dist/shields/formats/sourcemap.d.ts.map +1 -1
  247. package/dist/shields/formats/sourcemap.js +2 -0
  248. package/dist/shields/formats/sourcemap.js.map +1 -1
  249. package/dist/shields/formats/sqlite.d.ts +87 -15
  250. package/dist/shields/formats/sqlite.d.ts.map +1 -1
  251. package/dist/shields/formats/sqlite.js +377 -42
  252. package/dist/shields/formats/sqlite.js.map +1 -1
  253. package/dist/shields/formats/wasm.d.ts +6 -0
  254. package/dist/shields/formats/wasm.d.ts.map +1 -1
  255. package/dist/shields/formats/wasm.js +118 -3
  256. package/dist/shields/formats/wasm.js.map +1 -1
  257. package/dist/shields/javascript/ast-shield.d.ts +25 -5
  258. package/dist/shields/javascript/ast-shield.d.ts.map +1 -1
  259. package/dist/shields/javascript/ast-shield.js +428 -58
  260. package/dist/shields/javascript/ast-shield.js.map +1 -1
  261. package/dist/shields/runtime/memory-diff-shield.d.ts +56 -0
  262. package/dist/shields/runtime/memory-diff-shield.d.ts.map +1 -0
  263. package/dist/shields/runtime/memory-diff-shield.js +170 -0
  264. package/dist/shields/runtime/memory-diff-shield.js.map +1 -0
  265. package/dist/shields/runtime/runtime-shield.d.ts +12 -16
  266. package/dist/shields/runtime/runtime-shield.d.ts.map +1 -1
  267. package/dist/shields/runtime/runtime-shield.js +30 -24
  268. package/dist/shields/runtime/runtime-shield.js.map +1 -1
  269. package/dist/shields/tarpit/opaque-predicates.d.ts.map +1 -1
  270. package/dist/shields/tarpit/opaque-predicates.js +3 -3
  271. package/dist/shields/tarpit/opaque-predicates.js.map +1 -1
  272. package/dist/shields/tarpit/tarpit-generator.d.ts +9 -4
  273. package/dist/shields/tarpit/tarpit-generator.d.ts.map +1 -1
  274. package/dist/shields/tarpit/tarpit-generator.js +30 -23
  275. package/dist/shields/tarpit/tarpit-generator.js.map +1 -1
  276. package/package.json +13 -6
@@ -1,12 +1,62 @@
1
1
  import { BLA_IDENTITY } from "../identity.js";
2
+ import { initBlaConfig } from "../core/config.js";
3
+ import { inspectReleaseExposure } from "../core/release-exposure.js";
2
4
  import { auditTarget } from "../engine/auditor.js";
3
5
  import { protectTarget } from "../engine/protector.js";
4
6
  import { verifyTarget } from "../engine/verifier.js";
5
7
  import { defendTarget } from "../engine/defender.js";
8
+ import { hardenProject } from "../engine/harden.js";
6
9
  import { runShowcaseBenchmark } from "../engine/benchmark.js";
7
10
  import { emitCompileTimeNativeHeader, } from "../shields/formats/headers.js";
8
11
  import { runDoctor } from "../setup/doctor.js";
12
+ const DEFAULT_ENGINE_HANDLERS = Object.freeze({
13
+ hardenProject,
14
+ defendTarget,
15
+ auditTarget,
16
+ protectTarget,
17
+ verifyTarget,
18
+ runShowcaseBenchmark,
19
+ emitCompileTimeNativeHeader,
20
+ runDoctor,
21
+ inspectReleaseExposure,
22
+ initBlaConfig,
23
+ });
24
+ export const SUPPORTED_MCP_PROTOCOL_VERSIONS = Object.freeze([
25
+ "2024-11-05",
26
+ "2025-03-26",
27
+ ]);
9
28
  export const BLA_MCP_TOOLS = Object.freeze([
29
+ {
30
+ name: "bla_harden",
31
+ description: "DEFAULT one-sentence Counter-REA hardening. Auto-discovers build outputs (dist/, build/, out/, release/, .asar, native binaries, .wasm, .py/.pyc, .sqlite, .safetensors/.gguf, .dex, .class, etc.), detects each artifact's format, and runs the full audit→defend→verify pipeline with the bankrupt profile. Pass just a project or build directory (default: cwd). Prefer this over bla_defend when the user says 'harden my software' without naming a specific file.",
32
+ inputSchema: {
33
+ type: "object",
34
+ properties: {
35
+ directory: {
36
+ type: "string",
37
+ description: "Project or build directory to harden (default: current working directory)",
38
+ },
39
+ intensity: {
40
+ type: "string",
41
+ enum: ["stealth", "balanced", "maximum", "bankrupt"],
42
+ description: "Protection intensity preset (default: bankrupt)",
43
+ },
44
+ emit_manifest: {
45
+ type: "boolean",
46
+ description: "Opt-in: emit an unsigned .bla-manifest.json attestation (not ed25519-signed) per artifact. Default false.",
47
+ },
48
+ llm_directives: {
49
+ type: "boolean",
50
+ description: "Opt-in risky LLM directive layers (fake COPPA/medical notices, dual-use imitation, AI chat markers). Default false.",
51
+ },
52
+ seed: {
53
+ type: "string",
54
+ description: "Optional deterministic seed; when omitted, BLA uses/persists a per-project random seed in .blarc",
55
+ },
56
+ },
57
+ additionalProperties: false,
58
+ },
59
+ },
10
60
  {
11
61
  name: "bla_defend",
12
62
  description: "One-click Counter-REA full defense hardening pipeline. Runs release source-map exposure inspection, 16-vector REA vulnerability audit, Resource-Exhaustion + Model-Misjudgment shield injection (default: bankrupt preset), and mathematical invariant verification in a single call.",
@@ -28,10 +78,19 @@ export const BLA_MCP_TOOLS = Object.freeze([
28
78
  },
29
79
  emit_manifest: {
30
80
  type: "boolean",
31
- description: "Emit a signed .bla-manifest.json alongside the hardened artifact",
81
+ description: "Opt-in: emit an unsigned .bla-manifest.json attestation (not ed25519-signed) next to the hardened artifact. Default false.",
82
+ },
83
+ llm_directives: {
84
+ type: "boolean",
85
+ description: "Opt-in risky LLM directive layers (fake COPPA/medical notices, dual-use imitation, AI chat markers). Default false.",
86
+ },
87
+ seed: {
88
+ type: "string",
89
+ description: "Optional deterministic seed; when omitted, BLA uses/persists a per-project random seed in .blarc",
32
90
  },
33
91
  },
34
92
  required: ["input_path"],
93
+ additionalProperties: false,
35
94
  },
36
95
  },
37
96
  {
@@ -46,6 +105,7 @@ export const BLA_MCP_TOOLS = Object.freeze([
46
105
  },
47
106
  },
48
107
  required: ["path"],
108
+ additionalProperties: false,
49
109
  },
50
110
  },
51
111
  {
@@ -69,10 +129,15 @@ export const BLA_MCP_TOOLS = Object.freeze([
69
129
  },
70
130
  seed: {
71
131
  type: "string",
72
- description: "Optional deterministic seed for reproducible builds",
132
+ description: "Optional deterministic seed; when omitted, BLA mints an ephemeral random seed (prefer project .blarc via CLI)",
133
+ },
134
+ llm_directives: {
135
+ type: "boolean",
136
+ description: "Opt-in risky LLM directive layers. Default false.",
73
137
  },
74
138
  },
75
139
  required: ["input_path"],
140
+ additionalProperties: false,
76
141
  },
77
142
  },
78
143
  {
@@ -91,14 +156,16 @@ export const BLA_MCP_TOOLS = Object.freeze([
91
156
  },
92
157
  },
93
158
  required: ["target_path"],
159
+ additionalProperties: false,
94
160
  },
95
161
  },
96
162
  {
97
163
  name: "bla_benchmark",
98
- description: "Runs the 5-target Counter-REA Showcase Benchmark (DX-Ball Sound-Pan, Notion Electron Clipboard ASAR, Enterprise License Guard, WebAssembly Crypto Core, and Native ELF64 Binary) and returns Before vs. After metrics.",
164
+ description: "Runs the Counter-REA Showcase Benchmark suite and returns Before vs. After metrics.",
99
165
  inputSchema: {
100
166
  type: "object",
101
167
  properties: {},
168
+ additionalProperties: false,
102
169
  },
103
170
  },
104
171
  {
@@ -118,6 +185,7 @@ export const BLA_MCP_TOOLS = Object.freeze([
118
185
  },
119
186
  },
120
187
  required: ["language"],
188
+ additionalProperties: false,
121
189
  },
122
190
  },
123
191
  {
@@ -125,23 +193,269 @@ export const BLA_MCP_TOOLS = Object.freeze([
125
193
  description: "Checks readiness of all BLA protection engines and agent MCP registrations.",
126
194
  inputSchema: {
127
195
  type: "object",
128
- properties: {},
196
+ properties: {
197
+ home_dir: {
198
+ type: "string",
199
+ description: "Optional home directory path to inspect",
200
+ },
201
+ },
202
+ additionalProperties: false,
203
+ },
204
+ },
205
+ {
206
+ name: "bla_inspect_release",
207
+ description: "Read-only local source-map and symbol exposure scan for build directories and release artifacts.",
208
+ inputSchema: {
209
+ type: "object",
210
+ properties: {
211
+ path: {
212
+ type: "string",
213
+ description: "Path to the build directory or artifact to inspect",
214
+ },
215
+ max_files: {
216
+ type: "number",
217
+ description: "Optional maximum number of files to scan",
218
+ },
219
+ max_total_bytes: {
220
+ type: "number",
221
+ description: "Optional maximum total bytes to scan",
222
+ },
223
+ },
224
+ required: ["path"],
225
+ additionalProperties: false,
129
226
  },
130
227
  },
228
+ {
229
+ name: "bla_init",
230
+ description: "Creates a starter bla.config.json in a project directory for zero-argument `bla defend` workflows.",
231
+ inputSchema: {
232
+ type: "object",
233
+ properties: {
234
+ directory: {
235
+ type: "string",
236
+ description: "Target project directory (pass '.' explicitly for current directory)",
237
+ },
238
+ overwrite: {
239
+ type: "boolean",
240
+ description: "Overwrite an existing bla.config.json if present",
241
+ },
242
+ },
243
+ required: ["directory"],
244
+ additionalProperties: false,
245
+ },
246
+ },
247
+ ]);
248
+ export const BLA_MCP_PROMPTS = Object.freeze([
249
+ {
250
+ name: "bla-harden-project",
251
+ description: "One-sentence Counter-REA hardening: discover every protectable build artifact under a project directory and run bla_harden (audit→defend→verify, bankrupt profile).",
252
+ arguments: [
253
+ {
254
+ name: "directory",
255
+ description: "Project or build directory (default: .)",
256
+ required: false,
257
+ },
258
+ ],
259
+ },
260
+ {
261
+ name: "shield-against-rea",
262
+ description: "Audit a build artifact for REA exposure, apply BLA's adversarial shield, and verify the token bankruptcy factor.",
263
+ arguments: [
264
+ {
265
+ name: "target_path",
266
+ description: "Path to the build artifact or directory",
267
+ required: true,
268
+ },
269
+ ],
270
+ },
271
+ {
272
+ name: "bla-hardening-workflow",
273
+ description: "Step-by-step release hardening checklist using bla_inspect_release, bla_audit, bla_protect, and bla_verify.",
274
+ arguments: [
275
+ {
276
+ name: "target_path",
277
+ description: "Path to the build artifact or directory",
278
+ required: true,
279
+ },
280
+ ],
281
+ },
282
+ {
283
+ name: "bla-counter-rea",
284
+ description: "Evaluate REA reverse-engineering exposure and plan defensive hardening for a software artifact.",
285
+ arguments: [
286
+ {
287
+ name: "target_path",
288
+ description: "Path to the build artifact or directory",
289
+ required: true,
290
+ },
291
+ ],
292
+ },
131
293
  ]);
132
- export async function handleMcpRequest(req) {
294
+ function isPlainObject(value) {
295
+ return typeof value === "object" && value !== null && !Array.isArray(value);
296
+ }
297
+ export function validateMcpToolCall(params) {
298
+ if (!isPlainObject(params)) {
299
+ return {
300
+ ok: false,
301
+ code: -32602,
302
+ message: "Invalid params: tool call params must be a JSON object",
303
+ };
304
+ }
305
+ if (typeof params.name !== "string" || params.name.trim().length === 0) {
306
+ return {
307
+ ok: false,
308
+ code: -32602,
309
+ message: "Invalid params: tool 'name' must be a non-empty string",
310
+ };
311
+ }
312
+ const tool = BLA_MCP_TOOLS.find((t) => t.name === params.name);
313
+ if (!tool) {
314
+ return {
315
+ ok: false,
316
+ code: -32602,
317
+ message: `Invalid params: unknown BLA MCP tool '${params.name}'`,
318
+ };
319
+ }
320
+ const rawArgs = params.arguments;
321
+ const requiredFields = tool.inputSchema.required ?? [];
322
+ if (rawArgs === undefined) {
323
+ if (requiredFields.length > 0) {
324
+ return {
325
+ ok: false,
326
+ code: -32602,
327
+ message: `Invalid params for '${tool.name}': missing required arguments (${requiredFields.join(", ")})`,
328
+ };
329
+ }
330
+ return { ok: true, tool, args: {} };
331
+ }
332
+ if (!isPlainObject(rawArgs)) {
333
+ return {
334
+ ok: false,
335
+ code: -32602,
336
+ message: `Invalid params for '${tool.name}': 'arguments' must be a JSON object`,
337
+ };
338
+ }
339
+ // Reject unexpected properties when additionalProperties is false
340
+ const allowedProps = tool.inputSchema.properties;
341
+ for (const key of Object.keys(rawArgs)) {
342
+ if (!(key in allowedProps)) {
343
+ return {
344
+ ok: false,
345
+ code: -32602,
346
+ message: `Invalid params for '${tool.name}': unknown argument '${key}'`,
347
+ };
348
+ }
349
+ }
350
+ // Validate required properties
351
+ for (const reqKey of requiredFields) {
352
+ if (!(reqKey in rawArgs) || rawArgs[reqKey] === undefined || rawArgs[reqKey] === null) {
353
+ return {
354
+ ok: false,
355
+ code: -32602,
356
+ message: `Invalid params for '${tool.name}': missing required argument '${reqKey}'`,
357
+ };
358
+ }
359
+ }
360
+ // Validate types, non-empty strings, numbers, booleans, and enums
361
+ for (const [key, val] of Object.entries(rawArgs)) {
362
+ if (val === undefined)
363
+ continue;
364
+ const propSchema = allowedProps[key];
365
+ if (!propSchema)
366
+ continue;
367
+ if (propSchema.type === "string") {
368
+ if (typeof val !== "string") {
369
+ return {
370
+ ok: false,
371
+ code: -32602,
372
+ message: `Invalid params for '${tool.name}': argument '${key}' must be a string, received ${val === null ? "null" : typeof val}`,
373
+ };
374
+ }
375
+ if (val.trim().length === 0) {
376
+ return {
377
+ ok: false,
378
+ code: -32602,
379
+ message: `Invalid params for '${tool.name}': argument '${key}' must be a non-empty string`,
380
+ };
381
+ }
382
+ if (propSchema.enum && !propSchema.enum.includes(val)) {
383
+ return {
384
+ ok: false,
385
+ code: -32602,
386
+ message: `Invalid params for '${tool.name}': argument '${key}' must be one of [${propSchema.enum.join(", ")}], received '${val}'`,
387
+ };
388
+ }
389
+ }
390
+ else if (propSchema.type === "boolean") {
391
+ if (typeof val !== "boolean") {
392
+ return {
393
+ ok: false,
394
+ code: -32602,
395
+ message: `Invalid params for '${tool.name}': argument '${key}' must be a boolean`,
396
+ };
397
+ }
398
+ }
399
+ else if (propSchema.type === "number") {
400
+ if (typeof val !== "number" || !Number.isFinite(val) || val <= 0) {
401
+ return {
402
+ ok: false,
403
+ code: -32602,
404
+ message: `Invalid params for '${tool.name}': argument '${key}' must be a positive finite number`,
405
+ };
406
+ }
407
+ }
408
+ }
409
+ return { ok: true, tool, args: rawArgs };
410
+ }
411
+ export async function handleMcpRequest(req, handlers = DEFAULT_ENGINE_HANDLERS) {
412
+ if (!isPlainObject(req) || req.jsonrpc !== "2.0" || typeof req.method !== "string") {
413
+ return {
414
+ jsonrpc: "2.0",
415
+ id: isPlainObject(req) && (typeof req.id === "string" || typeof req.id === "number") ? req.id : null,
416
+ error: {
417
+ code: -32600,
418
+ message: "Invalid Request: expected JSON-RPC 2.0 request object",
419
+ },
420
+ };
421
+ }
133
422
  // Notifications without an `id` do not produce a response
134
423
  if (req.id === undefined) {
135
424
  return null;
136
425
  }
137
426
  try {
138
427
  switch (req.method) {
139
- case "initialize":
428
+ case "initialize": {
429
+ if (req.params !== undefined && !isPlainObject(req.params)) {
430
+ return {
431
+ jsonrpc: "2.0",
432
+ id: req.id,
433
+ error: {
434
+ code: -32602,
435
+ message: "Invalid params: initialize params must be an object",
436
+ },
437
+ };
438
+ }
439
+ const requestedVersion = req.params?.protocolVersion;
440
+ if (requestedVersion !== undefined && typeof requestedVersion !== "string") {
441
+ return {
442
+ jsonrpc: "2.0",
443
+ id: req.id,
444
+ error: {
445
+ code: -32602,
446
+ message: "Invalid params: protocolVersion must be a string",
447
+ },
448
+ };
449
+ }
450
+ const negotiatedVersion = typeof requestedVersion === "string" &&
451
+ SUPPORTED_MCP_PROTOCOL_VERSIONS.includes(requestedVersion)
452
+ ? requestedVersion
453
+ : "2024-11-05";
140
454
  return {
141
455
  jsonrpc: "2.0",
142
456
  id: req.id,
143
457
  result: {
144
- protocolVersion: "2024-11-05",
458
+ protocolVersion: negotiatedVersion,
145
459
  capabilities: {
146
460
  tools: {},
147
461
  prompts: {},
@@ -152,6 +466,7 @@ export async function handleMcpRequest(req) {
152
466
  },
153
467
  },
154
468
  };
469
+ }
155
470
  case "ping":
156
471
  return {
157
472
  jsonrpc: "2.0",
@@ -171,29 +486,120 @@ export async function handleMcpRequest(req) {
171
486
  jsonrpc: "2.0",
172
487
  id: req.id,
173
488
  result: {
174
- prompts: [
489
+ prompts: BLA_MCP_PROMPTS,
490
+ },
491
+ };
492
+ case "prompts/get": {
493
+ if (!isPlainObject(req.params) || typeof req.params.name !== "string") {
494
+ return {
495
+ jsonrpc: "2.0",
496
+ id: req.id,
497
+ error: {
498
+ code: -32602,
499
+ message: "Invalid params: prompts/get requires a string 'name'",
500
+ },
501
+ };
502
+ }
503
+ const promptDef = BLA_MCP_PROMPTS.find((p) => p.name === req.params.name);
504
+ if (!promptDef) {
505
+ return {
506
+ jsonrpc: "2.0",
507
+ id: req.id,
508
+ error: {
509
+ code: -32602,
510
+ message: `Invalid params: unknown prompt '${req.params.name}'`,
511
+ },
512
+ };
513
+ }
514
+ const promptArgs = req.params.arguments;
515
+ if (!isPlainObject(promptArgs)) {
516
+ return {
517
+ jsonrpc: "2.0",
518
+ id: req.id,
519
+ error: {
520
+ code: -32602,
521
+ message: `Invalid params: prompt '${promptDef.name}' requires an 'arguments' object`,
522
+ },
523
+ };
524
+ }
525
+ for (const argSpec of promptDef.arguments) {
526
+ if (argSpec.required) {
527
+ const val = promptArgs[argSpec.name];
528
+ if (typeof val !== "string" || val.trim().length === 0) {
529
+ return {
530
+ jsonrpc: "2.0",
531
+ id: req.id,
532
+ error: {
533
+ code: -32602,
534
+ message: `Invalid params: prompt '${promptDef.name}' requires non-empty string argument '${argSpec.name}'`,
535
+ },
536
+ };
537
+ }
538
+ }
539
+ }
540
+ let promptText;
541
+ if (promptDef.name === "bla-harden-project") {
542
+ const directory = typeof promptArgs.directory === "string" && promptArgs.directory.trim().length > 0
543
+ ? String(promptArgs.directory)
544
+ : ".";
545
+ promptText =
546
+ `Harden my software against REA in one step: call bla_harden with { "directory": "${directory}" }. ` +
547
+ `It auto-discovers build outputs, runs audit→defend→verify with the bankrupt profile on every artifact, and returns a per-artifact summary. ` +
548
+ `Do not ask which files to protect — discover them.`;
549
+ }
550
+ else {
551
+ const targetPath = String(promptArgs.target_path ?? ".");
552
+ promptText =
553
+ `Inspect and audit '${targetPath}' using bla_inspect_release and bla_audit, then review findings before applying bla_protect or bla_defend and verifying with bla_verify.`;
554
+ }
555
+ return {
556
+ jsonrpc: "2.0",
557
+ id: req.id,
558
+ result: {
559
+ description: promptDef.description,
560
+ messages: [
175
561
  {
176
- name: "shield-against-rea",
177
- description: "Audit a build artifact for REA exposure, apply BLA's adversarial shield, and verify the token bankruptcy factor.",
178
- arguments: [
179
- {
180
- name: "target_path",
181
- description: "Path to the build artifact or directory",
182
- required: true,
183
- },
184
- ],
562
+ role: "user",
563
+ content: {
564
+ type: "text",
565
+ text: promptText,
566
+ },
185
567
  },
186
568
  ],
187
569
  },
188
570
  };
571
+ }
189
572
  case "tools/call": {
190
- const params = req.params ?? {};
191
- const name = String(params.name ?? "");
192
- const args = params.arguments ?? {};
573
+ const validated = validateMcpToolCall(req.params);
574
+ if (!validated.ok) {
575
+ return {
576
+ jsonrpc: "2.0",
577
+ id: req.id,
578
+ error: {
579
+ code: validated.code,
580
+ message: validated.message,
581
+ },
582
+ };
583
+ }
584
+ const { tool, args } = validated;
585
+ const name = tool.name;
193
586
  let payload;
194
- if (name === "bla_defend") {
195
- payload = defendTarget({
196
- inputPath: String(args.input_path ?? ""),
587
+ if (name === "bla_harden") {
588
+ payload = handlers.hardenProject({
589
+ directory: typeof args.directory === "string" && args.directory.trim().length > 0
590
+ ? args.directory
591
+ : process.cwd(),
592
+ intensity: typeof args.intensity === "string"
593
+ ? args.intensity
594
+ : "bankrupt",
595
+ emitManifest: Boolean(args.emit_manifest),
596
+ llmDirectives: Boolean(args.llm_directives),
597
+ ...(typeof args.seed === "string" ? { seed: args.seed } : {}),
598
+ });
599
+ }
600
+ else if (name === "bla_defend") {
601
+ payload = handlers.defendTarget({
602
+ inputPath: args.input_path,
197
603
  ...(typeof args.output_path === "string"
198
604
  ? { outputPath: args.output_path }
199
605
  : {}),
@@ -201,46 +607,45 @@ export async function handleMcpRequest(req) {
201
607
  ? args.intensity
202
608
  : "bankrupt",
203
609
  emitManifest: Boolean(args.emit_manifest),
610
+ llmDirectives: Boolean(args.llm_directives),
611
+ ...(typeof args.seed === "string" ? { seed: args.seed } : {}),
204
612
  });
205
613
  }
206
614
  else if (name === "bla_audit") {
207
- payload = auditTarget(String(args.path ?? ""));
615
+ payload = handlers.auditTarget(args.path);
208
616
  }
209
617
  else if (name === "bla_protect") {
210
- payload = protectTarget({
211
- inputPath: String(args.input_path ?? ""),
618
+ payload = handlers.protectTarget({
619
+ inputPath: args.input_path,
212
620
  ...(typeof args.output_path === "string" ? { outputPath: args.output_path } : {}),
213
621
  ...(typeof args.intensity === "string"
214
622
  ? { intensity: args.intensity }
215
623
  : {}),
216
624
  ...(typeof args.seed === "string" ? { seed: args.seed } : {}),
625
+ llmDirectives: Boolean(args.llm_directives),
217
626
  });
218
627
  }
219
628
  else if (name === "bla_verify") {
220
- payload = verifyTarget(String(args.target_path ?? ""), typeof args.original_path === "string" ? args.original_path : undefined);
629
+ payload = handlers.verifyTarget(args.target_path, typeof args.original_path === "string" ? args.original_path : undefined);
221
630
  }
222
631
  else if (name === "bla_benchmark") {
223
- payload = await runShowcaseBenchmark();
632
+ payload = await handlers.runShowcaseBenchmark();
224
633
  }
225
634
  else if (name === "bla_emit_headers") {
226
- payload = emitCompileTimeNativeHeader(args.language ?? "c", {
635
+ payload = handlers.emitCompileTimeNativeHeader(args.language, {
227
636
  ...(typeof args.intensity === "string"
228
637
  ? { intensity: args.intensity }
229
638
  : {}),
230
639
  });
231
640
  }
232
641
  else if (name === "bla_doctor") {
233
- payload = runDoctor();
642
+ payload = handlers.runDoctor(typeof args.home_dir === "string" ? args.home_dir : undefined);
234
643
  }
235
- else {
236
- return {
237
- jsonrpc: "2.0",
238
- id: req.id,
239
- error: {
240
- code: -32601,
241
- message: `Unknown BLA MCP tool: ${name}`,
242
- },
243
- };
644
+ else if (name === "bla_inspect_release") {
645
+ payload = handlers.inspectReleaseExposure(args.path);
646
+ }
647
+ else if (name === "bla_init") {
648
+ payload = handlers.initBlaConfig(args.directory, Boolean(args.overwrite));
244
649
  }
245
650
  return {
246
651
  jsonrpc: "2.0",
@@ -285,12 +690,13 @@ export async function handleMcpRequest(req) {
285
690
  }
286
691
  }
287
692
  /**
288
- * Starts the BLA MCP server over stdio (supporting newline-delimited JSON-RPC).
693
+ * Starts the BLA MCP server over stdio (supporting newline-delimited JSON-RPC 2.0).
289
694
  */
290
695
  export function startMcpStdioServer() {
291
696
  let buffer = "";
697
+ let processingQueue = Promise.resolve();
292
698
  process.stdin.setEncoding("utf8");
293
- process.stdin.on("data", async (chunk) => {
699
+ process.stdin.on("data", (chunk) => {
294
700
  buffer += chunk;
295
701
  let newlineIdx;
296
702
  while ((newlineIdx = buffer.indexOf("\n")) >= 0) {
@@ -298,16 +704,26 @@ export function startMcpStdioServer() {
298
704
  buffer = buffer.slice(newlineIdx + 1);
299
705
  if (!line || line.startsWith("Content-Length:"))
300
706
  continue;
301
- try {
302
- const req = JSON.parse(line);
303
- const res = await handleMcpRequest(req);
304
- if (res !== null) {
305
- process.stdout.write(JSON.stringify(res) + "\n");
707
+ processingQueue = processingQueue.then(async () => {
708
+ try {
709
+ const req = JSON.parse(line);
710
+ const res = await handleMcpRequest(req);
711
+ if (res !== null) {
712
+ process.stdout.write(JSON.stringify(res) + "\n");
713
+ }
306
714
  }
307
- }
308
- catch {
309
- // Ignore unparseable line
310
- }
715
+ catch {
716
+ const parseErr = {
717
+ jsonrpc: "2.0",
718
+ id: null,
719
+ error: {
720
+ code: -32700,
721
+ message: "Parse error",
722
+ },
723
+ };
724
+ process.stdout.write(JSON.stringify(parseErr) + "\n");
725
+ }
726
+ });
311
727
  }
312
728
  });
313
729
  }