@claude-flow/cli 3.32.29 → 3.32.32

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 (378) hide show
  1. package/.claude/helpers/helpers.manifest.json +2 -2
  2. package/catalog-manifest.json +2 -2
  3. package/dist/src/autopilot-state.d.ts +10 -0
  4. package/dist/src/autopilot-state.js +16 -0
  5. package/dist/src/commands/autopilot.js +10 -4
  6. package/dist/src/init/claudemd-generator.js +53 -2
  7. package/dist/src/mcp-tools/autopilot-tools.js +18 -3
  8. package/dist/src/mcp-tools/capability-brain.js +22 -22
  9. package/dist/src/mcp-tools/guidance-tools.js +1 -1
  10. package/dist/src/services/harness-flywheel-runtime.d.ts +21 -1
  11. package/dist/src/services/harness-flywheel-runtime.js +46 -24
  12. package/node_modules/@claude-flow/codex/.agents/skills/memory-management/SKILL.md +45 -0
  13. package/node_modules/@claude-flow/codex/.agents/skills/security-audit/SKILL.md +46 -0
  14. package/node_modules/@claude-flow/codex/.agents/skills/sparc-methodology/SKILL.md +46 -0
  15. package/node_modules/@claude-flow/codex/.agents/skills/swarm-orchestration/SKILL.md +53 -0
  16. package/node_modules/@claude-flow/codex/README.md +1044 -0
  17. package/node_modules/@claude-flow/codex/dist/cli.d.ts +9 -0
  18. package/node_modules/@claude-flow/codex/dist/cli.d.ts.map +1 -0
  19. package/node_modules/@claude-flow/codex/dist/cli.js +686 -0
  20. package/node_modules/@claude-flow/codex/dist/cli.js.map +1 -0
  21. package/node_modules/@claude-flow/codex/dist/dual-mode/cli.d.ts +17 -0
  22. package/node_modules/@claude-flow/codex/dist/dual-mode/cli.d.ts.map +1 -0
  23. package/node_modules/@claude-flow/codex/dist/dual-mode/cli.js +278 -0
  24. package/node_modules/@claude-flow/codex/dist/dual-mode/cli.js.map +1 -0
  25. package/node_modules/@claude-flow/codex/dist/dual-mode/index.d.ts +8 -0
  26. package/node_modules/@claude-flow/codex/dist/dual-mode/index.d.ts.map +1 -0
  27. package/node_modules/@claude-flow/codex/dist/dual-mode/index.js +7 -0
  28. package/node_modules/@claude-flow/codex/dist/dual-mode/index.js.map +1 -0
  29. package/node_modules/@claude-flow/codex/dist/dual-mode/orchestrator.d.ts +143 -0
  30. package/node_modules/@claude-flow/codex/dist/dual-mode/orchestrator.d.ts.map +1 -0
  31. package/node_modules/@claude-flow/codex/dist/dual-mode/orchestrator.js +621 -0
  32. package/node_modules/@claude-flow/codex/dist/dual-mode/orchestrator.js.map +1 -0
  33. package/node_modules/@claude-flow/codex/dist/generators/agents-md.d.ts +12 -0
  34. package/node_modules/@claude-flow/codex/dist/generators/agents-md.d.ts.map +1 -0
  35. package/node_modules/@claude-flow/codex/dist/generators/agents-md.js +730 -0
  36. package/node_modules/@claude-flow/codex/dist/generators/agents-md.js.map +1 -0
  37. package/node_modules/@claude-flow/codex/dist/generators/config-toml.d.ts +74 -0
  38. package/node_modules/@claude-flow/codex/dist/generators/config-toml.d.ts.map +1 -0
  39. package/node_modules/@claude-flow/codex/dist/generators/config-toml.js +922 -0
  40. package/node_modules/@claude-flow/codex/dist/generators/config-toml.js.map +1 -0
  41. package/node_modules/@claude-flow/codex/dist/generators/index.d.ts +9 -0
  42. package/node_modules/@claude-flow/codex/dist/generators/index.d.ts.map +1 -0
  43. package/node_modules/@claude-flow/codex/dist/generators/index.js +9 -0
  44. package/node_modules/@claude-flow/codex/dist/generators/index.js.map +1 -0
  45. package/node_modules/@claude-flow/codex/dist/generators/skill-md.d.ts +20 -0
  46. package/node_modules/@claude-flow/codex/dist/generators/skill-md.d.ts.map +1 -0
  47. package/node_modules/@claude-flow/codex/dist/generators/skill-md.js +951 -0
  48. package/node_modules/@claude-flow/codex/dist/generators/skill-md.js.map +1 -0
  49. package/node_modules/@claude-flow/codex/dist/harness/build-evidence.d.ts +46 -0
  50. package/node_modules/@claude-flow/codex/dist/harness/build-evidence.d.ts.map +1 -0
  51. package/node_modules/@claude-flow/codex/dist/harness/build-evidence.js +126 -0
  52. package/node_modules/@claude-flow/codex/dist/harness/build-evidence.js.map +1 -0
  53. package/node_modules/@claude-flow/codex/dist/harness/contract.d.ts +153 -0
  54. package/node_modules/@claude-flow/codex/dist/harness/contract.d.ts.map +1 -0
  55. package/node_modules/@claude-flow/codex/dist/harness/contract.js +44 -0
  56. package/node_modules/@claude-flow/codex/dist/harness/contract.js.map +1 -0
  57. package/node_modules/@claude-flow/codex/dist/harness/in-memory-fenced-lease-reference.d.ts +33 -0
  58. package/node_modules/@claude-flow/codex/dist/harness/in-memory-fenced-lease-reference.d.ts.map +1 -0
  59. package/node_modules/@claude-flow/codex/dist/harness/in-memory-fenced-lease-reference.js +175 -0
  60. package/node_modules/@claude-flow/codex/dist/harness/in-memory-fenced-lease-reference.js.map +1 -0
  61. package/node_modules/@claude-flow/codex/dist/harness/in-memory-inbox-reference.d.ts +42 -0
  62. package/node_modules/@claude-flow/codex/dist/harness/in-memory-inbox-reference.d.ts.map +1 -0
  63. package/node_modules/@claude-flow/codex/dist/harness/in-memory-inbox-reference.js +140 -0
  64. package/node_modules/@claude-flow/codex/dist/harness/in-memory-inbox-reference.js.map +1 -0
  65. package/node_modules/@claude-flow/codex/dist/harness/in-memory-run-receipt-reference.d.ts +19 -0
  66. package/node_modules/@claude-flow/codex/dist/harness/in-memory-run-receipt-reference.d.ts.map +1 -0
  67. package/node_modules/@claude-flow/codex/dist/harness/in-memory-run-receipt-reference.js +79 -0
  68. package/node_modules/@claude-flow/codex/dist/harness/in-memory-run-receipt-reference.js.map +1 -0
  69. package/node_modules/@claude-flow/codex/dist/harness/index.d.ts +9 -0
  70. package/node_modules/@claude-flow/codex/dist/harness/index.d.ts.map +1 -0
  71. package/node_modules/@claude-flow/codex/dist/harness/index.js +9 -0
  72. package/node_modules/@claude-flow/codex/dist/harness/index.js.map +1 -0
  73. package/node_modules/@claude-flow/codex/dist/harness/portable-case-fold.d.ts +8 -0
  74. package/node_modules/@claude-flow/codex/dist/harness/portable-case-fold.d.ts.map +1 -0
  75. package/node_modules/@claude-flow/codex/dist/harness/portable-case-fold.js +10 -0
  76. package/node_modules/@claude-flow/codex/dist/harness/portable-case-fold.js.map +1 -0
  77. package/node_modules/@claude-flow/codex/dist/harness/repository-state.d.ts +68 -0
  78. package/node_modules/@claude-flow/codex/dist/harness/repository-state.d.ts.map +1 -0
  79. package/node_modules/@claude-flow/codex/dist/harness/repository-state.js +403 -0
  80. package/node_modules/@claude-flow/codex/dist/harness/repository-state.js.map +1 -0
  81. package/node_modules/@claude-flow/codex/dist/harness/unsigned-integer.d.ts +3 -0
  82. package/node_modules/@claude-flow/codex/dist/harness/unsigned-integer.d.ts.map +1 -0
  83. package/node_modules/@claude-flow/codex/dist/harness/unsigned-integer.js +14 -0
  84. package/node_modules/@claude-flow/codex/dist/harness/unsigned-integer.js.map +1 -0
  85. package/node_modules/@claude-flow/codex/dist/index.d.ts +53 -0
  86. package/node_modules/@claude-flow/codex/dist/index.d.ts.map +1 -0
  87. package/node_modules/@claude-flow/codex/dist/index.js +54 -0
  88. package/node_modules/@claude-flow/codex/dist/index.js.map +1 -0
  89. package/node_modules/@claude-flow/codex/dist/initializer.d.ts +98 -0
  90. package/node_modules/@claude-flow/codex/dist/initializer.d.ts.map +1 -0
  91. package/node_modules/@claude-flow/codex/dist/initializer.js +795 -0
  92. package/node_modules/@claude-flow/codex/dist/initializer.js.map +1 -0
  93. package/node_modules/@claude-flow/codex/dist/loop/cli.d.ts +3 -0
  94. package/node_modules/@claude-flow/codex/dist/loop/cli.d.ts.map +1 -0
  95. package/node_modules/@claude-flow/codex/dist/loop/cli.js +123 -0
  96. package/node_modules/@claude-flow/codex/dist/loop/cli.js.map +1 -0
  97. package/node_modules/@claude-flow/codex/dist/loop/index.d.ts +58 -0
  98. package/node_modules/@claude-flow/codex/dist/loop/index.d.ts.map +1 -0
  99. package/node_modules/@claude-flow/codex/dist/loop/index.js +230 -0
  100. package/node_modules/@claude-flow/codex/dist/loop/index.js.map +1 -0
  101. package/node_modules/@claude-flow/codex/dist/mcp-config.d.ts +28 -0
  102. package/node_modules/@claude-flow/codex/dist/mcp-config.d.ts.map +1 -0
  103. package/node_modules/@claude-flow/codex/dist/mcp-config.js +121 -0
  104. package/node_modules/@claude-flow/codex/dist/mcp-config.js.map +1 -0
  105. package/node_modules/@claude-flow/codex/dist/migrations/index.d.ts +114 -0
  106. package/node_modules/@claude-flow/codex/dist/migrations/index.d.ts.map +1 -0
  107. package/node_modules/@claude-flow/codex/dist/migrations/index.js +880 -0
  108. package/node_modules/@claude-flow/codex/dist/migrations/index.js.map +1 -0
  109. package/node_modules/@claude-flow/codex/dist/templates/index.d.ts +92 -0
  110. package/node_modules/@claude-flow/codex/dist/templates/index.d.ts.map +1 -0
  111. package/node_modules/@claude-flow/codex/dist/templates/index.js +284 -0
  112. package/node_modules/@claude-flow/codex/dist/templates/index.js.map +1 -0
  113. package/node_modules/@claude-flow/codex/dist/types.d.ts +240 -0
  114. package/node_modules/@claude-flow/codex/dist/types.d.ts.map +1 -0
  115. package/node_modules/@claude-flow/codex/dist/types.js +8 -0
  116. package/node_modules/@claude-flow/codex/dist/types.js.map +1 -0
  117. package/node_modules/@claude-flow/codex/dist/validators/index.d.ts +42 -0
  118. package/node_modules/@claude-flow/codex/dist/validators/index.d.ts.map +1 -0
  119. package/node_modules/@claude-flow/codex/dist/validators/index.js +929 -0
  120. package/node_modules/@claude-flow/codex/dist/validators/index.js.map +1 -0
  121. package/node_modules/@claude-flow/codex/dist/worktrees/coordinator.d.ts +37 -0
  122. package/node_modules/@claude-flow/codex/dist/worktrees/coordinator.d.ts.map +1 -0
  123. package/node_modules/@claude-flow/codex/dist/worktrees/coordinator.js +137 -0
  124. package/node_modules/@claude-flow/codex/dist/worktrees/coordinator.js.map +1 -0
  125. package/node_modules/@claude-flow/codex/dist/worktrees/index.d.ts +2 -0
  126. package/node_modules/@claude-flow/codex/dist/worktrees/index.d.ts.map +1 -0
  127. package/node_modules/@claude-flow/codex/dist/worktrees/index.js +2 -0
  128. package/node_modules/@claude-flow/codex/dist/worktrees/index.js.map +1 -0
  129. package/node_modules/@claude-flow/codex/package.json +122 -0
  130. package/node_modules/@claude-flow/plugin-agent-federation/README.md +49 -0
  131. package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/agent-card.d.ts +130 -0
  132. package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/agent-card.d.ts.map +1 -0
  133. package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/agent-card.js +239 -0
  134. package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/agent-card.js.map +1 -0
  135. package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/consume.d.ts +34 -0
  136. package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/consume.d.ts.map +1 -0
  137. package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/consume.js +69 -0
  138. package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/consume.js.map +1 -0
  139. package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/well-known.d.ts +46 -0
  140. package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/well-known.d.ts.map +1 -0
  141. package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/well-known.js +84 -0
  142. package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/well-known.js.map +1 -0
  143. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/claim-checker.d.ts +27 -0
  144. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/claim-checker.d.ts.map +1 -0
  145. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/claim-checker.js +46 -0
  146. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/claim-checker.js.map +1 -0
  147. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-breaker-service.d.ts +192 -0
  148. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-breaker-service.d.ts.map +1 -0
  149. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-breaker-service.js +253 -0
  150. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-breaker-service.js.map +1 -0
  151. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-coordinator.d.ts +211 -0
  152. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-coordinator.d.ts.map +1 -0
  153. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-coordinator.js +501 -0
  154. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-coordinator.js.map +1 -0
  155. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/inbound-dispatcher.d.ts +114 -0
  156. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/inbound-dispatcher.d.ts.map +1 -0
  157. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/inbound-dispatcher.js +356 -0
  158. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/inbound-dispatcher.js.map +1 -0
  159. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/policy-engine.d.ts +41 -0
  160. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/policy-engine.d.ts.map +1 -0
  161. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/policy-engine.js +184 -0
  162. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/policy-engine.js.map +1 -0
  163. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/spend-reporter.d.ts +150 -0
  164. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/spend-reporter.d.ts.map +1 -0
  165. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/spend-reporter.js +128 -0
  166. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/spend-reporter.js.map +1 -0
  167. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/trust-evaluator.d.ts +74 -0
  168. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/trust-evaluator.d.ts.map +1 -0
  169. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/trust-evaluator.js +179 -0
  170. package/node_modules/@claude-flow/plugin-agent-federation/dist/application/trust-evaluator.js.map +1 -0
  171. package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.d.ts +13 -0
  172. package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.d.ts.map +1 -0
  173. package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.js +189 -0
  174. package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.js.map +1 -0
  175. package/node_modules/@claude-flow/plugin-agent-federation/dist/cli-commands.d.ts +7 -0
  176. package/node_modules/@claude-flow/plugin-agent-federation/dist/cli-commands.d.ts.map +1 -0
  177. package/node_modules/@claude-flow/plugin-agent-federation/dist/cli-commands.js +317 -0
  178. package/node_modules/@claude-flow/plugin-agent-federation/dist/cli-commands.js.map +1 -0
  179. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-envelope.d.ts +45 -0
  180. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-envelope.d.ts.map +1 -0
  181. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-envelope.js +71 -0
  182. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-envelope.js.map +1 -0
  183. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-node.d.ts +104 -0
  184. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-node.d.ts.map +1 -0
  185. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-node.js +152 -0
  186. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-node.js.map +1 -0
  187. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-session.d.ts +55 -0
  188. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-session.d.ts.map +1 -0
  189. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-session.js +105 -0
  190. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-session.js.map +1 -0
  191. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/trust-level.d.ts +17 -0
  192. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/trust-level.d.ts.map +1 -0
  193. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/trust-level.js +35 -0
  194. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/trust-level.js.map +1 -0
  195. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/audit-service.d.ts +69 -0
  196. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/audit-service.d.ts.map +1 -0
  197. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/audit-service.js +149 -0
  198. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/audit-service.js.map +1 -0
  199. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/discovery-service.d.ts +68 -0
  200. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/discovery-service.d.ts.map +1 -0
  201. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/discovery-service.js +161 -0
  202. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/discovery-service.js.map +1 -0
  203. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/handshake-service.d.ts +58 -0
  204. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/handshake-service.d.ts.map +1 -0
  205. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/handshake-service.js +122 -0
  206. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/handshake-service.js.map +1 -0
  207. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/pii-pipeline-service.d.ts +65 -0
  208. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/pii-pipeline-service.d.ts.map +1 -0
  209. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/pii-pipeline-service.js +208 -0
  210. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/pii-pipeline-service.js.map +1 -0
  211. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/routing-service.d.ts +51 -0
  212. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/routing-service.d.ts.map +1 -0
  213. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/routing-service.js +147 -0
  214. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/routing-service.js.map +1 -0
  215. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-firewall-service.d.ts +71 -0
  216. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-firewall-service.d.ts.map +1 -0
  217. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-firewall-service.js +194 -0
  218. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-firewall-service.js.map +1 -0
  219. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-mesh-service.d.ts +156 -0
  220. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-mesh-service.d.ts.map +1 -0
  221. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-mesh-service.js +292 -0
  222. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-mesh-service.js.map +1 -0
  223. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-witness-service.d.ts +98 -0
  224. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-witness-service.d.ts.map +1 -0
  225. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-witness-service.js +122 -0
  226. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-witness-service.js.map +1 -0
  227. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/federation-budget.d.ts +89 -0
  228. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/federation-budget.d.ts.map +1 -0
  229. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/federation-budget.js +165 -0
  230. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/federation-budget.js.map +1 -0
  231. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/federation-node-state.d.ts +92 -0
  232. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/federation-node-state.d.ts.map +1 -0
  233. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/federation-node-state.js +100 -0
  234. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/federation-node-state.js.map +1 -0
  235. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/wg-config.d.ts +70 -0
  236. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/wg-config.d.ts.map +1 -0
  237. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/wg-config.js +104 -0
  238. package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/wg-config.js.map +1 -0
  239. package/node_modules/@claude-flow/plugin-agent-federation/dist/index.d.ts +23 -0
  240. package/node_modules/@claude-flow/plugin-agent-federation/dist/index.d.ts.map +1 -0
  241. package/node_modules/@claude-flow/plugin-agent-federation/dist/index.js +24 -0
  242. package/node_modules/@claude-flow/plugin-agent-federation/dist/index.js.map +1 -0
  243. package/node_modules/@claude-flow/plugin-agent-federation/dist/mcp-tools.d.ts +10 -0
  244. package/node_modules/@claude-flow/plugin-agent-federation/dist/mcp-tools.d.ts.map +1 -0
  245. package/node_modules/@claude-flow/plugin-agent-federation/dist/mcp-tools.js +439 -0
  246. package/node_modules/@claude-flow/plugin-agent-federation/dist/mcp-tools.js.map +1 -0
  247. package/node_modules/@claude-flow/plugin-agent-federation/dist/plugin.d.ts +19 -0
  248. package/node_modules/@claude-flow/plugin-agent-federation/dist/plugin.d.ts.map +1 -0
  249. package/node_modules/@claude-flow/plugin-agent-federation/dist/plugin.js +515 -0
  250. package/node_modules/@claude-flow/plugin-agent-federation/dist/plugin.js.map +1 -0
  251. package/node_modules/@claude-flow/plugin-agent-federation/dist/transport/midstream-aware-loader.d.ts +72 -0
  252. package/node_modules/@claude-flow/plugin-agent-federation/dist/transport/midstream-aware-loader.d.ts.map +1 -0
  253. package/node_modules/@claude-flow/plugin-agent-federation/dist/transport/midstream-aware-loader.js +269 -0
  254. package/node_modules/@claude-flow/plugin-agent-federation/dist/transport/midstream-aware-loader.js.map +1 -0
  255. package/node_modules/@claude-flow/plugin-agent-federation/dist/version.d.ts +3 -0
  256. package/node_modules/@claude-flow/plugin-agent-federation/dist/version.d.ts.map +1 -0
  257. package/node_modules/@claude-flow/plugin-agent-federation/dist/version.js +3 -0
  258. package/node_modules/@claude-flow/plugin-agent-federation/dist/version.js.map +1 -0
  259. package/node_modules/@claude-flow/plugin-agent-federation/package.json +64 -0
  260. package/node_modules/@claude-flow/security/README.md +292 -0
  261. package/node_modules/@claude-flow/security/dist/CVE-REMEDIATION.d.ts +97 -0
  262. package/node_modules/@claude-flow/security/dist/CVE-REMEDIATION.d.ts.map +1 -0
  263. package/node_modules/@claude-flow/security/dist/CVE-REMEDIATION.js +537 -0
  264. package/node_modules/@claude-flow/security/dist/CVE-REMEDIATION.js.map +1 -0
  265. package/node_modules/@claude-flow/security/dist/application/index.d.ts +7 -0
  266. package/node_modules/@claude-flow/security/dist/application/index.d.ts.map +1 -0
  267. package/node_modules/@claude-flow/security/dist/application/index.js +7 -0
  268. package/node_modules/@claude-flow/security/dist/application/index.js.map +1 -0
  269. package/node_modules/@claude-flow/security/dist/application/services/security-application-service.d.ts +71 -0
  270. package/node_modules/@claude-flow/security/dist/application/services/security-application-service.d.ts.map +1 -0
  271. package/node_modules/@claude-flow/security/dist/application/services/security-application-service.js +153 -0
  272. package/node_modules/@claude-flow/security/dist/application/services/security-application-service.js.map +1 -0
  273. package/node_modules/@claude-flow/security/dist/authorization/propagator.d.ts +148 -0
  274. package/node_modules/@claude-flow/security/dist/authorization/propagator.d.ts.map +1 -0
  275. package/node_modules/@claude-flow/security/dist/authorization/propagator.js +182 -0
  276. package/node_modules/@claude-flow/security/dist/authorization/propagator.js.map +1 -0
  277. package/node_modules/@claude-flow/security/dist/credential-generator.d.ts +176 -0
  278. package/node_modules/@claude-flow/security/dist/credential-generator.d.ts.map +1 -0
  279. package/node_modules/@claude-flow/security/dist/credential-generator.js +272 -0
  280. package/node_modules/@claude-flow/security/dist/credential-generator.js.map +1 -0
  281. package/node_modules/@claude-flow/security/dist/domain/entities/security-context.d.ts +68 -0
  282. package/node_modules/@claude-flow/security/dist/domain/entities/security-context.d.ts.map +1 -0
  283. package/node_modules/@claude-flow/security/dist/domain/entities/security-context.js +132 -0
  284. package/node_modules/@claude-flow/security/dist/domain/entities/security-context.js.map +1 -0
  285. package/node_modules/@claude-flow/security/dist/domain/index.d.ts +8 -0
  286. package/node_modules/@claude-flow/security/dist/domain/index.d.ts.map +1 -0
  287. package/node_modules/@claude-flow/security/dist/domain/index.js +8 -0
  288. package/node_modules/@claude-flow/security/dist/domain/index.js.map +1 -0
  289. package/node_modules/@claude-flow/security/dist/domain/services/security-domain-service.d.ts +71 -0
  290. package/node_modules/@claude-flow/security/dist/domain/services/security-domain-service.d.ts.map +1 -0
  291. package/node_modules/@claude-flow/security/dist/domain/services/security-domain-service.js +237 -0
  292. package/node_modules/@claude-flow/security/dist/domain/services/security-domain-service.js.map +1 -0
  293. package/node_modules/@claude-flow/security/dist/index.d.ts +129 -0
  294. package/node_modules/@claude-flow/security/dist/index.d.ts.map +1 -0
  295. package/node_modules/@claude-flow/security/dist/index.js +176 -0
  296. package/node_modules/@claude-flow/security/dist/index.js.map +1 -0
  297. package/node_modules/@claude-flow/security/dist/input-validator.d.ts +306 -0
  298. package/node_modules/@claude-flow/security/dist/input-validator.d.ts.map +1 -0
  299. package/node_modules/@claude-flow/security/dist/input-validator.js +393 -0
  300. package/node_modules/@claude-flow/security/dist/input-validator.js.map +1 -0
  301. package/node_modules/@claude-flow/security/dist/keychain-adapter.d.ts +48 -0
  302. package/node_modules/@claude-flow/security/dist/keychain-adapter.d.ts.map +1 -0
  303. package/node_modules/@claude-flow/security/dist/keychain-adapter.js +0 -0
  304. package/node_modules/@claude-flow/security/dist/keychain-adapter.js.map +1 -0
  305. package/node_modules/@claude-flow/security/dist/mcp-composition-inspector.d.ts +133 -0
  306. package/node_modules/@claude-flow/security/dist/mcp-composition-inspector.d.ts.map +1 -0
  307. package/node_modules/@claude-flow/security/dist/mcp-composition-inspector.js +254 -0
  308. package/node_modules/@claude-flow/security/dist/mcp-composition-inspector.js.map +1 -0
  309. package/node_modules/@claude-flow/security/dist/oauth/browser.d.ts +31 -0
  310. package/node_modules/@claude-flow/security/dist/oauth/browser.d.ts.map +1 -0
  311. package/node_modules/@claude-flow/security/dist/oauth/browser.js +55 -0
  312. package/node_modules/@claude-flow/security/dist/oauth/browser.js.map +1 -0
  313. package/node_modules/@claude-flow/security/dist/oauth/callback-server.d.ts +37 -0
  314. package/node_modules/@claude-flow/security/dist/oauth/callback-server.d.ts.map +1 -0
  315. package/node_modules/@claude-flow/security/dist/oauth/callback-server.js +86 -0
  316. package/node_modules/@claude-flow/security/dist/oauth/callback-server.js.map +1 -0
  317. package/node_modules/@claude-flow/security/dist/oauth/client.d.ts +57 -0
  318. package/node_modules/@claude-flow/security/dist/oauth/client.d.ts.map +1 -0
  319. package/node_modules/@claude-flow/security/dist/oauth/client.js +120 -0
  320. package/node_modules/@claude-flow/security/dist/oauth/client.js.map +1 -0
  321. package/node_modules/@claude-flow/security/dist/oauth/pkce.d.ts +25 -0
  322. package/node_modules/@claude-flow/security/dist/oauth/pkce.d.ts.map +1 -0
  323. package/node_modules/@claude-flow/security/dist/oauth/pkce.js +36 -0
  324. package/node_modules/@claude-flow/security/dist/oauth/pkce.js.map +1 -0
  325. package/node_modules/@claude-flow/security/dist/password-hasher.d.ts +128 -0
  326. package/node_modules/@claude-flow/security/dist/password-hasher.d.ts.map +1 -0
  327. package/node_modules/@claude-flow/security/dist/password-hasher.js +190 -0
  328. package/node_modules/@claude-flow/security/dist/password-hasher.js.map +1 -0
  329. package/node_modules/@claude-flow/security/dist/path-validator.d.ts +148 -0
  330. package/node_modules/@claude-flow/security/dist/path-validator.d.ts.map +1 -0
  331. package/node_modules/@claude-flow/security/dist/path-validator.js +421 -0
  332. package/node_modules/@claude-flow/security/dist/path-validator.js.map +1 -0
  333. package/node_modules/@claude-flow/security/dist/plugins/integrity-verifier.d.ts +125 -0
  334. package/node_modules/@claude-flow/security/dist/plugins/integrity-verifier.d.ts.map +1 -0
  335. package/node_modules/@claude-flow/security/dist/plugins/integrity-verifier.js +186 -0
  336. package/node_modules/@claude-flow/security/dist/plugins/integrity-verifier.js.map +1 -0
  337. package/node_modules/@claude-flow/security/dist/policy/canonical.d.ts +5 -0
  338. package/node_modules/@claude-flow/security/dist/policy/canonical.d.ts.map +1 -0
  339. package/node_modules/@claude-flow/security/dist/policy/canonical.js +30 -0
  340. package/node_modules/@claude-flow/security/dist/policy/canonical.js.map +1 -0
  341. package/node_modules/@claude-flow/security/dist/policy/engine.d.ts +34 -0
  342. package/node_modules/@claude-flow/security/dist/policy/engine.d.ts.map +1 -0
  343. package/node_modules/@claude-flow/security/dist/policy/engine.js +285 -0
  344. package/node_modules/@claude-flow/security/dist/policy/engine.js.map +1 -0
  345. package/node_modules/@claude-flow/security/dist/policy/envelope.d.ts +9 -0
  346. package/node_modules/@claude-flow/security/dist/policy/envelope.d.ts.map +1 -0
  347. package/node_modules/@claude-flow/security/dist/policy/envelope.js +90 -0
  348. package/node_modules/@claude-flow/security/dist/policy/envelope.js.map +1 -0
  349. package/node_modules/@claude-flow/security/dist/policy/evaluator.d.ts +4 -0
  350. package/node_modules/@claude-flow/security/dist/policy/evaluator.d.ts.map +1 -0
  351. package/node_modules/@claude-flow/security/dist/policy/evaluator.js +119 -0
  352. package/node_modules/@claude-flow/security/dist/policy/evaluator.js.map +1 -0
  353. package/node_modules/@claude-flow/security/dist/policy/index.d.ts +7 -0
  354. package/node_modules/@claude-flow/security/dist/policy/index.d.ts.map +1 -0
  355. package/node_modules/@claude-flow/security/dist/policy/index.js +7 -0
  356. package/node_modules/@claude-flow/security/dist/policy/index.js.map +1 -0
  357. package/node_modules/@claude-flow/security/dist/policy/product-plane.d.ts +238 -0
  358. package/node_modules/@claude-flow/security/dist/policy/product-plane.d.ts.map +1 -0
  359. package/node_modules/@claude-flow/security/dist/policy/product-plane.js +1022 -0
  360. package/node_modules/@claude-flow/security/dist/policy/product-plane.js.map +1 -0
  361. package/node_modules/@claude-flow/security/dist/policy/types.d.ts +169 -0
  362. package/node_modules/@claude-flow/security/dist/policy/types.d.ts.map +1 -0
  363. package/node_modules/@claude-flow/security/dist/policy/types.js +2 -0
  364. package/node_modules/@claude-flow/security/dist/policy/types.js.map +1 -0
  365. package/node_modules/@claude-flow/security/dist/safe-executor.d.ts +180 -0
  366. package/node_modules/@claude-flow/security/dist/safe-executor.d.ts.map +1 -0
  367. package/node_modules/@claude-flow/security/dist/safe-executor.js +390 -0
  368. package/node_modules/@claude-flow/security/dist/safe-executor.js.map +1 -0
  369. package/node_modules/@claude-flow/security/dist/token-generator.d.ts +224 -0
  370. package/node_modules/@claude-flow/security/dist/token-generator.d.ts.map +1 -0
  371. package/node_modules/@claude-flow/security/dist/token-generator.js +351 -0
  372. package/node_modules/@claude-flow/security/dist/token-generator.js.map +1 -0
  373. package/node_modules/@claude-flow/security/dist/tool-output-guardrail.d.ts +126 -0
  374. package/node_modules/@claude-flow/security/dist/tool-output-guardrail.d.ts.map +1 -0
  375. package/node_modules/@claude-flow/security/dist/tool-output-guardrail.js +257 -0
  376. package/node_modules/@claude-flow/security/dist/tool-output-guardrail.js.map +1 -0
  377. package/node_modules/@claude-flow/security/package.json +44 -0
  378. package/package.json +24 -8
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Federation circuit breaker service (ADR-097 Phase 2.b).
3
+ *
4
+ * Phase 2.a shipped the FederationNode state machine + canTransition table.
5
+ * This service is what drives transitions: it records per-peer send outcomes
6
+ * (success/failure + spend), evaluates thresholds against the configured
7
+ * policy, and calls suspend()/evict()/reactivate() on the entity.
8
+ *
9
+ * Architecture is two-layer to keep the policy testable in isolation:
10
+ *
11
+ * 1. **evaluatePolicy** (pure function) — given rolling samples for a peer
12
+ * + the policy + now, returns a BreakerDecision describing what should
13
+ * happen. No I/O, no clock, no entity mutation.
14
+ * 2. **FederationBreakerService** — owns the rolling-sample buffer,
15
+ * wraps evaluatePolicy with the entity mutation step, and exposes
16
+ * `recordOutcome` (called by the coordinator on each send completion)
17
+ * + `tick` (called periodically to drive cooldown/auto-evict).
18
+ *
19
+ * The cost-tracker integration (Phase 3 upstream — emits federation_spend
20
+ * events when sends complete) is *not* wired here; this service holds its
21
+ * own in-memory rolling buffer. When Phase 3 upstream lands, the consumer
22
+ * can call `recordOutcome` from the bus subscriber and the buffer becomes
23
+ * a transparent cache. This keeps Phase 2 deliverable without a hard
24
+ * cost-tracker dependency.
25
+ *
26
+ * Security invariants:
27
+ *
28
+ * 1. Negative tokens/usd are clamped to 0 — a malicious receive-side
29
+ * reporter cannot drive an "unsuspend" through credit inflation.
30
+ * 2. Sample buffer is bounded per-peer (DEFAULT_MAX_SAMPLES_PER_PEER) so
31
+ * a high-throughput peer cannot exhaust memory.
32
+ * 3. Policy evaluation is order-independent for SUSPEND triggers —
33
+ * cost OR failure-ratio fires the same SUSPEND. The reason field
34
+ * records which one tripped.
35
+ * 4. evaluatePolicy is pure & deterministic given (samples, policy, now)
36
+ * — no Date.now() calls inside, no random IDs, no hidden state.
37
+ * 5. Auto-eviction only runs from SUSPENDED state and only after the
38
+ * grace age. Cannot skip SUSPENDED for an ACTIVE → EVICTED jump.
39
+ */
40
+ import { FederationNode } from '../domain/entities/federation-node.js';
41
+ import { SuspensionReason } from '../domain/value-objects/federation-node-state.js';
42
+ /** A single send outcome recorded by the coordinator. */
43
+ export interface SendOutcome {
44
+ readonly nodeId: string;
45
+ readonly success: boolean;
46
+ /** Tokens consumed by this leg. Negative values are treated as 0. */
47
+ readonly tokensUsed?: number;
48
+ /** USD spent on this leg. Negative values are treated as 0. */
49
+ readonly usdSpent?: number;
50
+ /** Caller-supplied timestamp (for testability). Defaults to recordOutcome's `now`. */
51
+ readonly at?: Date;
52
+ }
53
+ /** Configurable thresholds. All defaults come from ADR-097 Part 2. */
54
+ export interface BreakerPolicy {
55
+ /** 24h spend cap per peer. Default $5.00. */
56
+ readonly costSuspensionUsd: number;
57
+ /** Window for the cost cap. Default 24h. */
58
+ readonly costWindowMs: number;
59
+ /** Failure ratio that trips the breaker. Default 0.5 (50%). */
60
+ readonly failureRatioThreshold: number;
61
+ /** Window for failure-ratio computation. Default 1h. */
62
+ readonly failureWindowMs: number;
63
+ /** Minimum samples in the failure window before evaluating (anti-noise). Default 10. */
64
+ readonly failureMinSamples: number;
65
+ /** Cooldown before SUSPENDED → reactivate-eligible. Default 30min. */
66
+ readonly cooldownMs: number;
67
+ /** Continuous suspension age before auto-evict. Default 24h. */
68
+ readonly autoEvictionAgeMs: number;
69
+ }
70
+ export declare const DEFAULT_BREAKER_POLICY: BreakerPolicy;
71
+ /** Per-peer sample buffer cap. ~24h of 1-Hz traffic. */
72
+ export declare const DEFAULT_MAX_SAMPLES_PER_PEER = 100000;
73
+ /** A normalized, time-stamped outcome (negatives clamped, `at` resolved). */
74
+ interface NormalizedSample {
75
+ readonly success: boolean;
76
+ readonly tokensUsed: number;
77
+ readonly usdSpent: number;
78
+ readonly at: Date;
79
+ }
80
+ /**
81
+ * What the breaker decided for a peer at evaluation time. The service then
82
+ * applies the action (calls node.suspend()/evict()/reactivate()) but the
83
+ * decision itself is a pure return so tests can assert it without checking
84
+ * mutated state.
85
+ */
86
+ export type BreakerDecision = {
87
+ readonly action: 'NONE';
88
+ readonly nodeId: string;
89
+ } | {
90
+ readonly action: 'SUSPEND';
91
+ readonly nodeId: string;
92
+ readonly reason: SuspensionReason;
93
+ } | {
94
+ readonly action: 'EVICT';
95
+ readonly nodeId: string;
96
+ readonly reason: SuspensionReason;
97
+ } | {
98
+ readonly action: 'REACTIVATE_ELIGIBLE';
99
+ readonly nodeId: string;
100
+ };
101
+ /**
102
+ * Pure policy evaluator. Returns the decision the breaker should apply.
103
+ * No I/O, no clock, no entity mutation — given the same inputs, returns the
104
+ * same output. The service layer is responsible for calling node.suspend()
105
+ * / evict() / reactivate() based on this.
106
+ *
107
+ * Decision rules:
108
+ *
109
+ * For ACTIVE peers:
110
+ * - 24h cost > policy.costSuspensionUsd → SUSPEND/COST_THRESHOLD_EXCEEDED
111
+ * - 1h failure ratio > policy.failureRatioThreshold (≥ failureMinSamples
112
+ * in window) → SUSPEND/FAILURE_RATIO_EXCEEDED
113
+ * - else NONE
114
+ *
115
+ * For SUSPENDED peers:
116
+ * - suspended ≥ autoEvictionAgeMs → EVICT/GRACE_PERIOD_EXPIRED
117
+ * - cooldown elapsed → REACTIVATE_ELIGIBLE (caller probes + reactivates)
118
+ * - else NONE
119
+ *
120
+ * For EVICTED peers: always NONE (terminal under breaker flow).
121
+ *
122
+ * Cost takes priority over failure-ratio when both trip, because cost is
123
+ * the more conservative signal (a malicious peer can manufacture failures
124
+ * by trickling errors but cannot manufacture spend without actually
125
+ * burning budget).
126
+ */
127
+ export declare function evaluatePolicy(samples: readonly NormalizedSample[], node: FederationNode, policy: BreakerPolicy, now: Date): BreakerDecision;
128
+ /**
129
+ * Stateful service: owns the per-peer sample buffer, applies decisions to
130
+ * entities, and exposes the breaker control surface to the coordinator.
131
+ *
132
+ * Construct once per federation coordinator. Inject the policy if you need
133
+ * non-default thresholds (Phase 4 doctor surface will let users tune them).
134
+ */
135
+ /**
136
+ * ADR-111 Phase 3 — callback invoked after the breaker applies a successful
137
+ * state transition. Used by the coordinator to propagate suspends to the
138
+ * WG mesh layer (clearing AllowedIPs). Not invoked for `apply=false` dry runs
139
+ * or `NONE` / `REACTIVATE_ELIGIBLE` decisions. Errors thrown from the callback
140
+ * are swallowed at the breaker — the entity transition has already happened,
141
+ * and side-effect failures shouldn't unwind the breaker's internal state.
142
+ */
143
+ export type BreakerTransitionListener = (node: FederationNode, decision: BreakerDecision) => void | Promise<void>;
144
+ export declare class FederationBreakerService {
145
+ private readonly policy;
146
+ private readonly samples;
147
+ private readonly maxSamplesPerPeer;
148
+ private readonly onTransition?;
149
+ constructor(policy?: BreakerPolicy, maxSamplesPerPeer?: number, onTransition?: BreakerTransitionListener);
150
+ /** Read the active policy (handy for tests + doctor surface). */
151
+ getPolicy(): BreakerPolicy;
152
+ /**
153
+ * Record a send outcome for a peer. Called by the coordinator after each
154
+ * `routing.send` completion. Returns a BreakerDecision describing what,
155
+ * if anything, the breaker would do for this peer right now — but does
156
+ * NOT apply it (the caller asks `evaluate(node)` if they want the action
157
+ * to actually happen). This split lets the coordinator decide whether to
158
+ * apply on every outcome or batch via tick.
159
+ *
160
+ * Negative tokens/usd are clamped to 0. A peer cannot inflate its own
161
+ * remaining cost ceiling by reporting credits.
162
+ */
163
+ recordOutcome(outcome: SendOutcome, now?: Date): void;
164
+ /**
165
+ * Evaluate the breaker for one peer and apply the resulting transition
166
+ * to the entity. Returns the decision so callers can observe the outcome.
167
+ *
168
+ * `apply` defaults to true — set to false to get the dry-run decision
169
+ * without mutating the entity (useful for the doctor surface).
170
+ */
171
+ evaluate(node: FederationNode, now?: Date, apply?: boolean): BreakerDecision;
172
+ /**
173
+ * Periodic tick — evaluate all known peers. Intended to be called from a
174
+ * timer or after each batch of outcomes. Returns the decisions for
175
+ * observability.
176
+ */
177
+ tick(nodes: readonly FederationNode[], now?: Date): BreakerDecision[];
178
+ /** Drop a peer's sample buffer (e.g. after reactivate or evict). */
179
+ forget(nodeId: string): void;
180
+ /**
181
+ * Snapshot of per-peer aggregates for the doctor surface. Pure read —
182
+ * does not mutate the buffer.
183
+ */
184
+ snapshot(nodeId: string, now?: Date): {
185
+ readonly nodeId: string;
186
+ readonly sampleCount: number;
187
+ readonly cumUsdInWindow: number;
188
+ readonly failureRatioInWindow: number | null;
189
+ };
190
+ }
191
+ export {};
192
+ //# sourceMappingURL=federation-breaker-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"federation-breaker-service.d.ts","sourceRoot":"","sources":["../../src/application/federation-breaker-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,253 @@
1
+ /**
2
+ * Federation circuit breaker service (ADR-097 Phase 2.b).
3
+ *
4
+ * Phase 2.a shipped the FederationNode state machine + canTransition table.
5
+ * This service is what drives transitions: it records per-peer send outcomes
6
+ * (success/failure + spend), evaluates thresholds against the configured
7
+ * policy, and calls suspend()/evict()/reactivate() on the entity.
8
+ *
9
+ * Architecture is two-layer to keep the policy testable in isolation:
10
+ *
11
+ * 1. **evaluatePolicy** (pure function) — given rolling samples for a peer
12
+ * + the policy + now, returns a BreakerDecision describing what should
13
+ * happen. No I/O, no clock, no entity mutation.
14
+ * 2. **FederationBreakerService** — owns the rolling-sample buffer,
15
+ * wraps evaluatePolicy with the entity mutation step, and exposes
16
+ * `recordOutcome` (called by the coordinator on each send completion)
17
+ * + `tick` (called periodically to drive cooldown/auto-evict).
18
+ *
19
+ * The cost-tracker integration (Phase 3 upstream — emits federation_spend
20
+ * events when sends complete) is *not* wired here; this service holds its
21
+ * own in-memory rolling buffer. When Phase 3 upstream lands, the consumer
22
+ * can call `recordOutcome` from the bus subscriber and the buffer becomes
23
+ * a transparent cache. This keeps Phase 2 deliverable without a hard
24
+ * cost-tracker dependency.
25
+ *
26
+ * Security invariants:
27
+ *
28
+ * 1. Negative tokens/usd are clamped to 0 — a malicious receive-side
29
+ * reporter cannot drive an "unsuspend" through credit inflation.
30
+ * 2. Sample buffer is bounded per-peer (DEFAULT_MAX_SAMPLES_PER_PEER) so
31
+ * a high-throughput peer cannot exhaust memory.
32
+ * 3. Policy evaluation is order-independent for SUSPEND triggers —
33
+ * cost OR failure-ratio fires the same SUSPEND. The reason field
34
+ * records which one tripped.
35
+ * 4. evaluatePolicy is pure & deterministic given (samples, policy, now)
36
+ * — no Date.now() calls inside, no random IDs, no hidden state.
37
+ * 5. Auto-eviction only runs from SUSPENDED state and only after the
38
+ * grace age. Cannot skip SUSPENDED for an ACTIVE → EVICTED jump.
39
+ */
40
+ import { FederationNodeState, isCooldownElapsed, shouldAutoEvict, DEFAULT_SUSPENSION_COOLDOWN_MS, DEFAULT_AUTO_EVICTION_AGE_MS, } from '../domain/value-objects/federation-node-state.js';
41
+ export const DEFAULT_BREAKER_POLICY = Object.freeze({
42
+ costSuspensionUsd: 5.0,
43
+ costWindowMs: 24 * 60 * 60 * 1000,
44
+ failureRatioThreshold: 0.5,
45
+ failureWindowMs: 60 * 60 * 1000,
46
+ failureMinSamples: 10,
47
+ cooldownMs: DEFAULT_SUSPENSION_COOLDOWN_MS,
48
+ autoEvictionAgeMs: DEFAULT_AUTO_EVICTION_AGE_MS,
49
+ });
50
+ /** Per-peer sample buffer cap. ~24h of 1-Hz traffic. */
51
+ export const DEFAULT_MAX_SAMPLES_PER_PEER = 100_000;
52
+ /**
53
+ * Pure policy evaluator. Returns the decision the breaker should apply.
54
+ * No I/O, no clock, no entity mutation — given the same inputs, returns the
55
+ * same output. The service layer is responsible for calling node.suspend()
56
+ * / evict() / reactivate() based on this.
57
+ *
58
+ * Decision rules:
59
+ *
60
+ * For ACTIVE peers:
61
+ * - 24h cost > policy.costSuspensionUsd → SUSPEND/COST_THRESHOLD_EXCEEDED
62
+ * - 1h failure ratio > policy.failureRatioThreshold (≥ failureMinSamples
63
+ * in window) → SUSPEND/FAILURE_RATIO_EXCEEDED
64
+ * - else NONE
65
+ *
66
+ * For SUSPENDED peers:
67
+ * - suspended ≥ autoEvictionAgeMs → EVICT/GRACE_PERIOD_EXPIRED
68
+ * - cooldown elapsed → REACTIVATE_ELIGIBLE (caller probes + reactivates)
69
+ * - else NONE
70
+ *
71
+ * For EVICTED peers: always NONE (terminal under breaker flow).
72
+ *
73
+ * Cost takes priority over failure-ratio when both trip, because cost is
74
+ * the more conservative signal (a malicious peer can manufacture failures
75
+ * by trickling errors but cannot manufacture spend without actually
76
+ * burning budget).
77
+ */
78
+ export function evaluatePolicy(samples, node, policy, now) {
79
+ if (node.state === FederationNodeState.EVICTED) {
80
+ return { action: 'NONE', nodeId: node.nodeId };
81
+ }
82
+ if (node.state === FederationNodeState.SUSPENDED) {
83
+ if (shouldAutoEvict(node.stateChangedAt, now, policy.autoEvictionAgeMs)) {
84
+ return {
85
+ action: 'EVICT',
86
+ nodeId: node.nodeId,
87
+ reason: 'GRACE_PERIOD_EXPIRED',
88
+ };
89
+ }
90
+ if (isCooldownElapsed(node.stateChangedAt, now, policy.cooldownMs)) {
91
+ return { action: 'REACTIVATE_ELIGIBLE', nodeId: node.nodeId };
92
+ }
93
+ return { action: 'NONE', nodeId: node.nodeId };
94
+ }
95
+ // ACTIVE: check cost first, then failure ratio. Cost takes priority.
96
+ const costCutoff = now.getTime() - policy.costWindowMs;
97
+ let cumUsd = 0;
98
+ for (const s of samples) {
99
+ if (s.at.getTime() >= costCutoff)
100
+ cumUsd += s.usdSpent;
101
+ }
102
+ if (cumUsd > policy.costSuspensionUsd) {
103
+ return {
104
+ action: 'SUSPEND',
105
+ nodeId: node.nodeId,
106
+ reason: 'COST_THRESHOLD_EXCEEDED',
107
+ };
108
+ }
109
+ const failCutoff = now.getTime() - policy.failureWindowMs;
110
+ let total = 0;
111
+ let failures = 0;
112
+ for (const s of samples) {
113
+ if (s.at.getTime() < failCutoff)
114
+ continue;
115
+ total++;
116
+ if (!s.success)
117
+ failures++;
118
+ }
119
+ if (total >= policy.failureMinSamples) {
120
+ const ratio = failures / total;
121
+ if (ratio > policy.failureRatioThreshold) {
122
+ return {
123
+ action: 'SUSPEND',
124
+ nodeId: node.nodeId,
125
+ reason: 'FAILURE_RATIO_EXCEEDED',
126
+ };
127
+ }
128
+ }
129
+ return { action: 'NONE', nodeId: node.nodeId };
130
+ }
131
+ export class FederationBreakerService {
132
+ policy;
133
+ samples;
134
+ maxSamplesPerPeer;
135
+ onTransition;
136
+ constructor(policy = DEFAULT_BREAKER_POLICY, maxSamplesPerPeer = DEFAULT_MAX_SAMPLES_PER_PEER, onTransition) {
137
+ this.policy = policy;
138
+ this.samples = new Map();
139
+ this.maxSamplesPerPeer = maxSamplesPerPeer;
140
+ this.onTransition = onTransition;
141
+ }
142
+ /** Read the active policy (handy for tests + doctor surface). */
143
+ getPolicy() {
144
+ return this.policy;
145
+ }
146
+ /**
147
+ * Record a send outcome for a peer. Called by the coordinator after each
148
+ * `routing.send` completion. Returns a BreakerDecision describing what,
149
+ * if anything, the breaker would do for this peer right now — but does
150
+ * NOT apply it (the caller asks `evaluate(node)` if they want the action
151
+ * to actually happen). This split lets the coordinator decide whether to
152
+ * apply on every outcome or batch via tick.
153
+ *
154
+ * Negative tokens/usd are clamped to 0. A peer cannot inflate its own
155
+ * remaining cost ceiling by reporting credits.
156
+ */
157
+ recordOutcome(outcome, now = new Date()) {
158
+ const normalized = {
159
+ success: outcome.success,
160
+ tokensUsed: Math.max(0, outcome.tokensUsed ?? 0),
161
+ usdSpent: Math.max(0, outcome.usdSpent ?? 0),
162
+ at: outcome.at ?? now,
163
+ };
164
+ const buf = this.samples.get(outcome.nodeId) ?? [];
165
+ buf.push(normalized);
166
+ // Bounded buffer: drop oldest if over cap. Keeps memory bounded under
167
+ // sustained high traffic while preserving the most-recent window.
168
+ if (buf.length > this.maxSamplesPerPeer) {
169
+ buf.splice(0, buf.length - this.maxSamplesPerPeer);
170
+ }
171
+ this.samples.set(outcome.nodeId, buf);
172
+ }
173
+ /**
174
+ * Evaluate the breaker for one peer and apply the resulting transition
175
+ * to the entity. Returns the decision so callers can observe the outcome.
176
+ *
177
+ * `apply` defaults to true — set to false to get the dry-run decision
178
+ * without mutating the entity (useful for the doctor surface).
179
+ */
180
+ evaluate(node, now = new Date(), apply = true) {
181
+ const buf = this.samples.get(node.nodeId) ?? [];
182
+ const decision = evaluatePolicy(buf, node, this.policy, now);
183
+ if (!apply)
184
+ return decision;
185
+ let transitioned = false;
186
+ switch (decision.action) {
187
+ case 'SUSPEND': {
188
+ const reason = { reason: decision.reason };
189
+ transitioned = node.suspend(reason, now);
190
+ break;
191
+ }
192
+ case 'EVICT': {
193
+ const reason = { reason: decision.reason };
194
+ transitioned = node.evict(reason, now);
195
+ break;
196
+ }
197
+ case 'REACTIVATE_ELIGIBLE':
198
+ // The breaker does NOT auto-reactivate. The integrator's health
199
+ // probe is responsible for confirming the peer is healthy and
200
+ // calling node.reactivate() itself. We only signal eligibility.
201
+ break;
202
+ case 'NONE':
203
+ break;
204
+ }
205
+ if (transitioned && this.onTransition) {
206
+ // Side-effect listener (ADR-111 Phase 3). Errors are swallowed so a
207
+ // failing WG propagation can't unwind the entity transition that
208
+ // already succeeded — coordinator should log via its own audit trail.
209
+ Promise.resolve(this.onTransition(node, decision)).catch(() => { });
210
+ }
211
+ return decision;
212
+ }
213
+ /**
214
+ * Periodic tick — evaluate all known peers. Intended to be called from a
215
+ * timer or after each batch of outcomes. Returns the decisions for
216
+ * observability.
217
+ */
218
+ tick(nodes, now = new Date()) {
219
+ return nodes.map((n) => this.evaluate(n, now));
220
+ }
221
+ /** Drop a peer's sample buffer (e.g. after reactivate or evict). */
222
+ forget(nodeId) {
223
+ this.samples.delete(nodeId);
224
+ }
225
+ /**
226
+ * Snapshot of per-peer aggregates for the doctor surface. Pure read —
227
+ * does not mutate the buffer.
228
+ */
229
+ snapshot(nodeId, now = new Date()) {
230
+ const buf = this.samples.get(nodeId) ?? [];
231
+ const costCutoff = now.getTime() - this.policy.costWindowMs;
232
+ const failCutoff = now.getTime() - this.policy.failureWindowMs;
233
+ let cumUsd = 0;
234
+ let total = 0;
235
+ let failures = 0;
236
+ for (const s of buf) {
237
+ if (s.at.getTime() >= costCutoff)
238
+ cumUsd += s.usdSpent;
239
+ if (s.at.getTime() >= failCutoff) {
240
+ total++;
241
+ if (!s.success)
242
+ failures++;
243
+ }
244
+ }
245
+ return {
246
+ nodeId,
247
+ sampleCount: buf.length,
248
+ cumUsdInWindow: cumUsd,
249
+ failureRatioInWindow: total > 0 ? failures / total : null,
250
+ };
251
+ }
252
+ }
253
+ //# sourceMappingURL=federation-breaker-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"federation-breaker-service.js","sourceRoot":"","sources":["../../src/application/federation-breaker-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAGH,OAAO,EACL,mBAAmB,EAGnB,iBAAiB,EACjB,eAAe,EACf,8BAA8B,EAC9B,4BAA4B,GAC7B,MAAM,kDAAkD,CAAC;AAgC1D,MAAM,CAAC,MAAM,sBAAsB,GAAkB,MAAM,CAAC,MAAM,CAAC;IACjE,iBAAiB,EAAE,GAAG;IACtB,YAAY,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI;IACjC,qBAAqB,EAAE,GAAG;IAC1B,eAAe,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI;IAC/B,iBAAiB,EAAE,EAAE;IACrB,UAAU,EAAE,8BAA8B;IAC1C,iBAAiB,EAAE,4BAA4B;CAChD,CAAC,CAAC;AAEH,wDAAwD;AACxD,MAAM,CAAC,MAAM,4BAA4B,GAAG,OAAO,CAAC;AAiCpD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAoC,EACpC,IAAoB,EACpB,MAAqB,EACrB,GAAS;IAET,IAAI,IAAI,CAAC,KAAK,KAAK,mBAAmB,CAAC,OAAO,EAAE,CAAC;QAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;IACjD,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,KAAK,mBAAmB,CAAC,SAAS,EAAE,CAAC;QACjD,IAAI,eAAe,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,EAAE,MAAM,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACxE,OAAO;gBACL,MAAM,EAAE,OAAO;gBACf,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,MAAM,EAAE,sBAAsB;aAC/B,CAAC;QACJ,CAAC;QACD,IAAI,iBAAiB,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;YACnE,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;QAChE,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;IACjD,CAAC;IAED,qEAAqE;IACrE,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC;IACvD,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,UAAU;YAAE,MAAM,IAAI,CAAC,CAAC,QAAQ,CAAC;IACzD,CAAC;IACD,IAAI,MAAM,GAAG,MAAM,CAAC,iBAAiB,EAAE,CAAC;QACtC,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,yBAAyB;SAClC,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,eAAe,CAAC;IAC1D,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,UAAU;YAAE,SAAS;QAC1C,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,CAAC,CAAC,OAAO;YAAE,QAAQ,EAAE,CAAC;IAC7B,CAAC;IACD,IAAI,KAAK,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,QAAQ,GAAG,KAAK,CAAC;QAC/B,IAAI,KAAK,GAAG,MAAM,CAAC,qBAAqB,EAAE,CAAC;YACzC,OAAO;gBACL,MAAM,EAAE,SAAS;gBACjB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,MAAM,EAAE,wBAAwB;aACjC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;AACjD,CAAC;AAsBD,MAAM,OAAO,wBAAwB;IAClB,MAAM,CAAgB;IACtB,OAAO,CAAkC;IACzC,iBAAiB,CAAS;IAC1B,YAAY,CAA6B;IAE1D,YACE,SAAwB,sBAAsB,EAC9C,oBAA4B,4BAA4B,EACxD,YAAwC;QAExC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAC3C,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;IAED,iEAAiE;IACjE,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;;;;;;;;;OAUG;IACH,aAAa,CAAC,OAAoB,EAAE,MAAY,IAAI,IAAI,EAAE;QACxD,MAAM,UAAU,GAAqB;YACnC,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,IAAI,CAAC,CAAC;YAChD,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC;YAC5C,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,GAAG;SACtB,CAAC;QAEF,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACnD,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACrB,sEAAsE;QACtE,kEAAkE;QAClE,IAAI,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACxC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACrD,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACxC,CAAC;IAED;;;;;;OAMG;IACH,QAAQ,CACN,IAAoB,EACpB,MAAY,IAAI,IAAI,EAAE,EACtB,QAAiB,IAAI;QAErB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAChD,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAE7D,IAAI,CAAC,KAAK;YAAE,OAAO,QAAQ,CAAC;QAE5B,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAC;YACxB,KAAK,SAAS,CAAC,CAAC,CAAC;gBACf,MAAM,MAAM,GAAqB,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;gBAC7D,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;gBACzC,MAAM;YACR,CAAC;YACD,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,MAAM,MAAM,GAAqB,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;gBAC7D,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;gBACvC,MAAM;YACR,CAAC;YACD,KAAK,qBAAqB;gBACxB,gEAAgE;gBAChE,8DAA8D;gBAC9D,gEAAgE;gBAChE,MAAM;YACR,KAAK,MAAM;gBACT,MAAM;QACV,CAAC;QAED,IAAI,YAAY,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtC,oEAAoE;YACpE,iEAAiE;YACjE,sEAAsE;YACtE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAiB,CAAC,CAAC,CAAC;QACpF,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;;OAIG;IACH,IAAI,CAAC,KAAgC,EAAE,MAAY,IAAI,IAAI,EAAE;QAC3D,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,oEAAoE;IACpE,MAAM,CAAC,MAAc;QACnB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAED;;;OAGG;IACH,QAAQ,CAAC,MAAc,EAAE,MAAY,IAAI,IAAI,EAAE;QAM7C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC3C,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;QAC5D,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC;QAC/D,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;YACpB,IAAI,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,UAAU;gBAAE,MAAM,IAAI,CAAC,CAAC,QAAQ,CAAC;YACvD,IAAI,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,UAAU,EAAE,CAAC;gBACjC,KAAK,EAAE,CAAC;gBACR,IAAI,CAAC,CAAC,CAAC,OAAO;oBAAE,QAAQ,EAAE,CAAC;YAC7B,CAAC;QACH,CAAC;QACD,OAAO;YACL,MAAM;YACN,WAAW,EAAE,GAAG,CAAC,MAAM;YACvB,cAAc,EAAE,MAAM;YACtB,oBAAoB,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI;SAC1D,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,211 @@
1
+ import { FederationNode, type FederationNodeStateRecord } from '../domain/entities/federation-node.js';
2
+ import { FederationSession } from '../domain/entities/federation-session.js';
3
+ import { type FederationMessageType } from '../domain/entities/federation-envelope.js';
4
+ import { TrustLevel } from '../domain/entities/trust-level.js';
5
+ import { type SuspensionReason } from '../domain/value-objects/federation-node-state.js';
6
+ import { DiscoveryService, type FederationManifest } from '../domain/services/discovery-service.js';
7
+ import { HandshakeService } from '../domain/services/handshake-service.js';
8
+ import { RoutingService, type RoutingResult } from '../domain/services/routing-service.js';
9
+ import { AuditService } from '../domain/services/audit-service.js';
10
+ import { PIIPipelineService } from '../domain/services/pii-pipeline-service.js';
11
+ import { TrustEvaluator, type BootstrapElevationAuditEntry } from './trust-evaluator.js';
12
+ import { PolicyEngine } from './policy-engine.js';
13
+ import { enforceBudget, validateBudget } from '../domain/value-objects/federation-budget.js';
14
+ import type { FederationBreakerService } from './federation-breaker-service.js';
15
+ import type { SpendReporter } from './spend-reporter.js';
16
+ import type { WgMeshService, WgCommand } from '../domain/services/wg-mesh-service.js';
17
+ /**
18
+ * Optional per-call budget controls (ADR-097 Phase 1). All fields are
19
+ * optional; omitted means "no limit on that axis" (the default unbounded
20
+ * budget still has maxHops = 8 to defang recursive delegation loops).
21
+ */
22
+ export interface SendOptions {
23
+ readonly budget?: {
24
+ maxTokens?: number;
25
+ maxUsd?: number;
26
+ };
27
+ readonly maxHops?: number;
28
+ /**
29
+ * How many hops this message has already traveled (0 on the originator).
30
+ * Phase 1 enforces at the send side because there is no inbound dispatcher
31
+ * yet; callers re-forwarding a received message should pass the original
32
+ * envelope's hopCount here.
33
+ */
34
+ readonly hopCount?: number;
35
+ /** Caller-reported usage from the previous leg, for cumulative checks. */
36
+ readonly spent?: {
37
+ tokens?: number;
38
+ usd?: number;
39
+ };
40
+ }
41
+ export interface FederationCoordinatorConfig {
42
+ readonly nodeId: string;
43
+ readonly publicKey: string;
44
+ readonly endpoint: string;
45
+ readonly capabilities: readonly string[];
46
+ /** Wire protocols this runtime is prepared to advertise and negotiate. */
47
+ readonly supportedProtocols?: readonly string[];
48
+ readonly version?: string;
49
+ }
50
+ export interface FederationStatus {
51
+ readonly nodeId: string;
52
+ readonly activeSessions: number;
53
+ readonly knownPeers: number;
54
+ readonly trustLevels: Record<string, TrustLevel>;
55
+ readonly healthy: boolean;
56
+ }
57
+ /**
58
+ * Optional integrations (ADR-097 Phase 3 upstream + Phase 2.b breaker
59
+ * wiring). Both are constructor-injected; both default to no-op.
60
+ *
61
+ * - `spendReporter` — invoked by reportSpend() when present; persists
62
+ * the FederationSpendEvent to whatever backend the integrator wired
63
+ * (cost-tracker bus, ruflo memory federation-spend namespace, etc.)
64
+ * - `breakerService` — invoked by reportSpend() when present; calls
65
+ * recordOutcome() so the breaker's in-memory rolling buffer is fed
66
+ * without requiring the integrator to wire two parallel pipelines
67
+ */
68
+ export interface FederationCoordinatorIntegrations {
69
+ readonly spendReporter?: SpendReporter;
70
+ readonly breakerService?: FederationBreakerService;
71
+ /**
72
+ * ADR-111 Phase 3 — optional WG mesh service. When present, peer state
73
+ * transitions (evict/reactivate/breaker-suspend) emit `wg set` commands
74
+ * to a sink supplied by `wgCommandSink`. No-op for peers without a `wg`
75
+ * manifest block, so wiring the service is safe even in mixed deployments.
76
+ */
77
+ readonly wgMesh?: WgMeshService;
78
+ /**
79
+ * Where emitted WG commands go. Defaults to the audit log only. Integrators
80
+ * can plug in a shell executor here (after operator approval — bringing up
81
+ * a network interface is destructive). Commands include shell-ready
82
+ * `wg set <iface> ...` strings; the sink should still validate before exec.
83
+ */
84
+ readonly wgCommandSink?: (cmd: WgCommand) => void | Promise<void>;
85
+ }
86
+ export declare class FederationCoordinator {
87
+ private readonly config;
88
+ private readonly discovery;
89
+ private readonly handshake;
90
+ private readonly routing;
91
+ private readonly audit;
92
+ private readonly piiPipeline;
93
+ private readonly trustEvaluator;
94
+ private readonly policyEngine;
95
+ private readonly sessions;
96
+ private initialized;
97
+ private readonly spendReporter?;
98
+ private readonly breakerService?;
99
+ private readonly wgMesh?;
100
+ private readonly wgCommandSink?;
101
+ constructor(config: FederationCoordinatorConfig, discovery: DiscoveryService, handshake: HandshakeService, routing: RoutingService, audit: AuditService, piiPipeline: PIIPipelineService, trustEvaluator: TrustEvaluator, policyEngine: PolicyEngine, integrations?: FederationCoordinatorIntegrations);
102
+ /**
103
+ * ADR-111 Phase 3 — emit a WG command for an audited peer transition.
104
+ * No-op if no wgMesh is configured or the peer lacks a `wg` manifest
105
+ * block. Commands flow to `wgCommandSink` (if any) and always to the
106
+ * audit log so reactivation is fully traceable.
107
+ */
108
+ private emitWgCommand;
109
+ initialize(manifest: Omit<FederationManifest, 'signature'>): Promise<void>;
110
+ shutdown(): Promise<void>;
111
+ joinPeer(endpoint: string, manifest?: FederationManifest): Promise<FederationSession>;
112
+ leavePeer(nodeId: string): Promise<void>;
113
+ sendMessage<T>(targetNodeId: string, messageType: FederationMessageType, payload: T, options?: SendOptions): Promise<RoutingResult>;
114
+ /**
115
+ * Re-export the budget primitives so external callers (e.g. follow-up
116
+ * iterations adding receive-side decrement) can reuse them without
117
+ * dipping into domain/value-objects directly.
118
+ */
119
+ static readonly budget: {
120
+ validate: typeof validateBudget;
121
+ enforce: typeof enforceBudget;
122
+ };
123
+ broadcastMessage<T>(messageType: FederationMessageType, payload: T): Promise<RoutingResult[]>;
124
+ handleThreatDetection(nodeId: string): void;
125
+ handleHmacFailure(nodeId: string): void;
126
+ getStatus(): FederationStatus;
127
+ /**
128
+ * ADR-097 Phase 4: per-peer breaker state snapshot for the doctor
129
+ * surface and `federation_breaker_status` MCP tool.
130
+ *
131
+ * Returns one entry per known peer with the entity's stateRecord —
132
+ * what state, when it changed, why, and which caller's correlation
133
+ * key triggered it. Pure read; does not mutate.
134
+ */
135
+ getPeerStates(): readonly (FederationNodeStateRecord & {
136
+ readonly nodeId: string;
137
+ })[];
138
+ /**
139
+ * ADR-111 Phase 6: public read of the discovery peer list. Used by
140
+ * federation_wg_status MCP tool + WG firewall projection. Returns the
141
+ * full known-peer set (active + suspended + evicted) — filter via
142
+ * .isActive / state if you only want the live mesh members.
143
+ */
144
+ listPeers(): readonly FederationNode[];
145
+ /**
146
+ * Aggregated counts for the doctor surface — `{ active: N, suspended: M,
147
+ * evicted: K }`. Cheap O(peers) sweep; safe to call from a status line.
148
+ */
149
+ getPeerStateCounts(): {
150
+ readonly active: number;
151
+ readonly suspended: number;
152
+ readonly evicted: number;
153
+ };
154
+ /**
155
+ * Operator-initiated evict. Returns true on transition, false if the
156
+ * peer was already EVICTED or unknown. Logs to audit either way.
157
+ *
158
+ * Does NOT remove the peer from the discovery registry — `leavePeer`
159
+ * is the registry-removal API. Eviction is the breaker layer; the peer
160
+ * remains queryable so the operator can later reactivate.
161
+ */
162
+ evictPeer(nodeId: string, reason?: SuspensionReason, correlationId?: string): Promise<boolean>;
163
+ /**
164
+ * ADR-097 Phase 3 upstream: report the actual cost of a federated
165
+ * call. Federation doesn't own model pricing, so the integrator calls
166
+ * this after the downstream agent completes.
167
+ *
168
+ * Fans out to:
169
+ * - spendReporter (if injected) — persists to integrator's backend
170
+ * - breakerService.recordOutcome (if injected) — feeds the breaker's
171
+ * in-memory rolling buffer for cost/failure-ratio thresholds
172
+ *
173
+ * Both are no-ops if the corresponding integration isn't wired, so
174
+ * callers don't need to branch on configuration. Negative tokens/usd
175
+ * are clamped to 0 at the breaker layer (anti-credit-inflation); the
176
+ * spend reporter receives the raw values so backends can audit them.
177
+ *
178
+ * Auto-fills `ts` if the caller omits it.
179
+ */
180
+ reportSpend(input: {
181
+ readonly peerId: string;
182
+ readonly taskId?: string;
183
+ readonly tokensUsed: number;
184
+ readonly usdSpent: number;
185
+ readonly success: boolean;
186
+ readonly ts?: string;
187
+ }): Promise<void>;
188
+ /**
189
+ * Founder-bootstrap trust elevation (ADR-164 §3.5.4 — operator escape hatch
190
+ * used in the autopilot Day-1 scenario where a freshly-joined BBS peer
191
+ * needs TRUSTED before organic minInteractions thresholds can accrue).
192
+ *
193
+ * Refuses if the target node is not a registered federation peer (returns
194
+ * null). On success, writes a `trust_level_changed` audit entry tagged
195
+ * `bootstrap_elevation` with the operator-supplied reason, and returns
196
+ * the audit entry so the CLI / caller can print it to stdout.
197
+ */
198
+ bootstrapElevatePeer(nodeId: string, newLevel: TrustLevel, reason: string): Promise<BootstrapElevationAuditEntry | null>;
199
+ /**
200
+ * Operator-initiated reactivate. Used after an integrator-supplied
201
+ * health probe confirms a SUSPENDED peer is healthy, OR as an
202
+ * operator-override escape from EVICTED. Returns true on transition.
203
+ */
204
+ reactivatePeer(nodeId: string, correlationId?: string): Promise<boolean>;
205
+ getSession(sessionId: string): FederationSession | undefined;
206
+ getActiveSessions(): FederationSession[];
207
+ private establishSession;
208
+ private findSessionByNodeId;
209
+ private ensureInitialized;
210
+ }
211
+ //# sourceMappingURL=federation-coordinator.d.ts.map