@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.
- package/.claude/helpers/helpers.manifest.json +2 -2
- package/catalog-manifest.json +2 -2
- package/dist/src/autopilot-state.d.ts +10 -0
- package/dist/src/autopilot-state.js +16 -0
- package/dist/src/commands/autopilot.js +10 -4
- package/dist/src/init/claudemd-generator.js +53 -2
- package/dist/src/mcp-tools/autopilot-tools.js +18 -3
- package/dist/src/mcp-tools/capability-brain.js +22 -22
- package/dist/src/mcp-tools/guidance-tools.js +1 -1
- package/dist/src/services/harness-flywheel-runtime.d.ts +21 -1
- package/dist/src/services/harness-flywheel-runtime.js +46 -24
- package/node_modules/@claude-flow/codex/.agents/skills/memory-management/SKILL.md +45 -0
- package/node_modules/@claude-flow/codex/.agents/skills/security-audit/SKILL.md +46 -0
- package/node_modules/@claude-flow/codex/.agents/skills/sparc-methodology/SKILL.md +46 -0
- package/node_modules/@claude-flow/codex/.agents/skills/swarm-orchestration/SKILL.md +53 -0
- package/node_modules/@claude-flow/codex/README.md +1044 -0
- package/node_modules/@claude-flow/codex/dist/cli.d.ts +9 -0
- package/node_modules/@claude-flow/codex/dist/cli.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/cli.js +686 -0
- package/node_modules/@claude-flow/codex/dist/cli.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/dual-mode/cli.d.ts +17 -0
- package/node_modules/@claude-flow/codex/dist/dual-mode/cli.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/dual-mode/cli.js +278 -0
- package/node_modules/@claude-flow/codex/dist/dual-mode/cli.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/dual-mode/index.d.ts +8 -0
- package/node_modules/@claude-flow/codex/dist/dual-mode/index.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/dual-mode/index.js +7 -0
- package/node_modules/@claude-flow/codex/dist/dual-mode/index.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/dual-mode/orchestrator.d.ts +143 -0
- package/node_modules/@claude-flow/codex/dist/dual-mode/orchestrator.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/dual-mode/orchestrator.js +621 -0
- package/node_modules/@claude-flow/codex/dist/dual-mode/orchestrator.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/generators/agents-md.d.ts +12 -0
- package/node_modules/@claude-flow/codex/dist/generators/agents-md.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/generators/agents-md.js +730 -0
- package/node_modules/@claude-flow/codex/dist/generators/agents-md.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/generators/config-toml.d.ts +74 -0
- package/node_modules/@claude-flow/codex/dist/generators/config-toml.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/generators/config-toml.js +922 -0
- package/node_modules/@claude-flow/codex/dist/generators/config-toml.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/generators/index.d.ts +9 -0
- package/node_modules/@claude-flow/codex/dist/generators/index.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/generators/index.js +9 -0
- package/node_modules/@claude-flow/codex/dist/generators/index.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/generators/skill-md.d.ts +20 -0
- package/node_modules/@claude-flow/codex/dist/generators/skill-md.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/generators/skill-md.js +951 -0
- package/node_modules/@claude-flow/codex/dist/generators/skill-md.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/build-evidence.d.ts +46 -0
- package/node_modules/@claude-flow/codex/dist/harness/build-evidence.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/build-evidence.js +126 -0
- package/node_modules/@claude-flow/codex/dist/harness/build-evidence.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/contract.d.ts +153 -0
- package/node_modules/@claude-flow/codex/dist/harness/contract.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/contract.js +44 -0
- package/node_modules/@claude-flow/codex/dist/harness/contract.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/in-memory-fenced-lease-reference.d.ts +33 -0
- package/node_modules/@claude-flow/codex/dist/harness/in-memory-fenced-lease-reference.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/in-memory-fenced-lease-reference.js +175 -0
- package/node_modules/@claude-flow/codex/dist/harness/in-memory-fenced-lease-reference.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/in-memory-inbox-reference.d.ts +42 -0
- package/node_modules/@claude-flow/codex/dist/harness/in-memory-inbox-reference.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/in-memory-inbox-reference.js +140 -0
- package/node_modules/@claude-flow/codex/dist/harness/in-memory-inbox-reference.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/in-memory-run-receipt-reference.d.ts +19 -0
- package/node_modules/@claude-flow/codex/dist/harness/in-memory-run-receipt-reference.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/in-memory-run-receipt-reference.js +79 -0
- package/node_modules/@claude-flow/codex/dist/harness/in-memory-run-receipt-reference.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/index.d.ts +9 -0
- package/node_modules/@claude-flow/codex/dist/harness/index.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/index.js +9 -0
- package/node_modules/@claude-flow/codex/dist/harness/index.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/portable-case-fold.d.ts +8 -0
- package/node_modules/@claude-flow/codex/dist/harness/portable-case-fold.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/portable-case-fold.js +10 -0
- package/node_modules/@claude-flow/codex/dist/harness/portable-case-fold.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/repository-state.d.ts +68 -0
- package/node_modules/@claude-flow/codex/dist/harness/repository-state.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/repository-state.js +403 -0
- package/node_modules/@claude-flow/codex/dist/harness/repository-state.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/unsigned-integer.d.ts +3 -0
- package/node_modules/@claude-flow/codex/dist/harness/unsigned-integer.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/harness/unsigned-integer.js +14 -0
- package/node_modules/@claude-flow/codex/dist/harness/unsigned-integer.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/index.d.ts +53 -0
- package/node_modules/@claude-flow/codex/dist/index.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/index.js +54 -0
- package/node_modules/@claude-flow/codex/dist/index.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/initializer.d.ts +98 -0
- package/node_modules/@claude-flow/codex/dist/initializer.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/initializer.js +795 -0
- package/node_modules/@claude-flow/codex/dist/initializer.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/loop/cli.d.ts +3 -0
- package/node_modules/@claude-flow/codex/dist/loop/cli.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/loop/cli.js +123 -0
- package/node_modules/@claude-flow/codex/dist/loop/cli.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/loop/index.d.ts +58 -0
- package/node_modules/@claude-flow/codex/dist/loop/index.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/loop/index.js +230 -0
- package/node_modules/@claude-flow/codex/dist/loop/index.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/mcp-config.d.ts +28 -0
- package/node_modules/@claude-flow/codex/dist/mcp-config.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/mcp-config.js +121 -0
- package/node_modules/@claude-flow/codex/dist/mcp-config.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/migrations/index.d.ts +114 -0
- package/node_modules/@claude-flow/codex/dist/migrations/index.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/migrations/index.js +880 -0
- package/node_modules/@claude-flow/codex/dist/migrations/index.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/templates/index.d.ts +92 -0
- package/node_modules/@claude-flow/codex/dist/templates/index.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/templates/index.js +284 -0
- package/node_modules/@claude-flow/codex/dist/templates/index.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/types.d.ts +240 -0
- package/node_modules/@claude-flow/codex/dist/types.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/types.js +8 -0
- package/node_modules/@claude-flow/codex/dist/types.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/validators/index.d.ts +42 -0
- package/node_modules/@claude-flow/codex/dist/validators/index.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/validators/index.js +929 -0
- package/node_modules/@claude-flow/codex/dist/validators/index.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/worktrees/coordinator.d.ts +37 -0
- package/node_modules/@claude-flow/codex/dist/worktrees/coordinator.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/worktrees/coordinator.js +137 -0
- package/node_modules/@claude-flow/codex/dist/worktrees/coordinator.js.map +1 -0
- package/node_modules/@claude-flow/codex/dist/worktrees/index.d.ts +2 -0
- package/node_modules/@claude-flow/codex/dist/worktrees/index.d.ts.map +1 -0
- package/node_modules/@claude-flow/codex/dist/worktrees/index.js +2 -0
- package/node_modules/@claude-flow/codex/dist/worktrees/index.js.map +1 -0
- package/node_modules/@claude-flow/codex/package.json +122 -0
- package/node_modules/@claude-flow/plugin-agent-federation/README.md +49 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/agent-card.d.ts +130 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/agent-card.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/agent-card.js +239 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/agent-card.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/consume.d.ts +34 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/consume.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/consume.js +69 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/consume.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/well-known.d.ts +46 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/well-known.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/well-known.js +84 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/well-known.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/claim-checker.d.ts +27 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/claim-checker.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/claim-checker.js +46 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/claim-checker.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-breaker-service.d.ts +192 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-breaker-service.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-breaker-service.js +253 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-breaker-service.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-coordinator.d.ts +211 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-coordinator.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-coordinator.js +501 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/federation-coordinator.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/inbound-dispatcher.d.ts +114 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/inbound-dispatcher.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/inbound-dispatcher.js +356 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/inbound-dispatcher.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/policy-engine.d.ts +41 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/policy-engine.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/policy-engine.js +184 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/policy-engine.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/spend-reporter.d.ts +150 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/spend-reporter.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/spend-reporter.js +128 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/spend-reporter.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/trust-evaluator.d.ts +74 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/trust-evaluator.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/trust-evaluator.js +179 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/application/trust-evaluator.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.d.ts +13 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.js +189 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/cli-commands.d.ts +7 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/cli-commands.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/cli-commands.js +317 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/cli-commands.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-envelope.d.ts +45 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-envelope.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-envelope.js +71 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-envelope.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-node.d.ts +104 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-node.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-node.js +152 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-node.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-session.d.ts +55 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-session.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-session.js +105 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/federation-session.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/trust-level.d.ts +17 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/trust-level.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/trust-level.js +35 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/entities/trust-level.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/audit-service.d.ts +69 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/audit-service.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/audit-service.js +149 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/audit-service.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/discovery-service.d.ts +68 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/discovery-service.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/discovery-service.js +161 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/discovery-service.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/handshake-service.d.ts +58 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/handshake-service.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/handshake-service.js +122 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/handshake-service.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/pii-pipeline-service.d.ts +65 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/pii-pipeline-service.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/pii-pipeline-service.js +208 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/pii-pipeline-service.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/routing-service.d.ts +51 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/routing-service.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/routing-service.js +147 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/routing-service.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-firewall-service.d.ts +71 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-firewall-service.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-firewall-service.js +194 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-firewall-service.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-mesh-service.d.ts +156 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-mesh-service.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-mesh-service.js +292 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-mesh-service.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-witness-service.d.ts +98 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-witness-service.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-witness-service.js +122 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/services/wg-witness-service.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/federation-budget.d.ts +89 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/federation-budget.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/federation-budget.js +165 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/federation-budget.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/federation-node-state.d.ts +92 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/federation-node-state.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/federation-node-state.js +100 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/federation-node-state.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/wg-config.d.ts +70 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/wg-config.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/wg-config.js +104 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/domain/value-objects/wg-config.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/index.d.ts +23 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/index.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/index.js +24 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/index.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/mcp-tools.d.ts +10 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/mcp-tools.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/mcp-tools.js +439 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/mcp-tools.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/plugin.d.ts +19 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/plugin.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/plugin.js +515 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/plugin.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/transport/midstream-aware-loader.d.ts +72 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/transport/midstream-aware-loader.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/transport/midstream-aware-loader.js +269 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/transport/midstream-aware-loader.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/version.d.ts +3 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/version.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/version.js +3 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/version.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/package.json +64 -0
- package/node_modules/@claude-flow/security/README.md +292 -0
- package/node_modules/@claude-flow/security/dist/CVE-REMEDIATION.d.ts +97 -0
- package/node_modules/@claude-flow/security/dist/CVE-REMEDIATION.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/CVE-REMEDIATION.js +537 -0
- package/node_modules/@claude-flow/security/dist/CVE-REMEDIATION.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/application/index.d.ts +7 -0
- package/node_modules/@claude-flow/security/dist/application/index.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/application/index.js +7 -0
- package/node_modules/@claude-flow/security/dist/application/index.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/application/services/security-application-service.d.ts +71 -0
- package/node_modules/@claude-flow/security/dist/application/services/security-application-service.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/application/services/security-application-service.js +153 -0
- package/node_modules/@claude-flow/security/dist/application/services/security-application-service.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/authorization/propagator.d.ts +148 -0
- package/node_modules/@claude-flow/security/dist/authorization/propagator.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/authorization/propagator.js +182 -0
- package/node_modules/@claude-flow/security/dist/authorization/propagator.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/credential-generator.d.ts +176 -0
- package/node_modules/@claude-flow/security/dist/credential-generator.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/credential-generator.js +272 -0
- package/node_modules/@claude-flow/security/dist/credential-generator.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/domain/entities/security-context.d.ts +68 -0
- package/node_modules/@claude-flow/security/dist/domain/entities/security-context.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/domain/entities/security-context.js +132 -0
- package/node_modules/@claude-flow/security/dist/domain/entities/security-context.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/domain/index.d.ts +8 -0
- package/node_modules/@claude-flow/security/dist/domain/index.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/domain/index.js +8 -0
- package/node_modules/@claude-flow/security/dist/domain/index.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/domain/services/security-domain-service.d.ts +71 -0
- package/node_modules/@claude-flow/security/dist/domain/services/security-domain-service.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/domain/services/security-domain-service.js +237 -0
- package/node_modules/@claude-flow/security/dist/domain/services/security-domain-service.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/index.d.ts +129 -0
- package/node_modules/@claude-flow/security/dist/index.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/index.js +176 -0
- package/node_modules/@claude-flow/security/dist/index.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/input-validator.d.ts +306 -0
- package/node_modules/@claude-flow/security/dist/input-validator.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/input-validator.js +393 -0
- package/node_modules/@claude-flow/security/dist/input-validator.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/keychain-adapter.d.ts +48 -0
- package/node_modules/@claude-flow/security/dist/keychain-adapter.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/keychain-adapter.js +0 -0
- package/node_modules/@claude-flow/security/dist/keychain-adapter.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/mcp-composition-inspector.d.ts +133 -0
- package/node_modules/@claude-flow/security/dist/mcp-composition-inspector.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/mcp-composition-inspector.js +254 -0
- package/node_modules/@claude-flow/security/dist/mcp-composition-inspector.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/oauth/browser.d.ts +31 -0
- package/node_modules/@claude-flow/security/dist/oauth/browser.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/oauth/browser.js +55 -0
- package/node_modules/@claude-flow/security/dist/oauth/browser.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/oauth/callback-server.d.ts +37 -0
- package/node_modules/@claude-flow/security/dist/oauth/callback-server.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/oauth/callback-server.js +86 -0
- package/node_modules/@claude-flow/security/dist/oauth/callback-server.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/oauth/client.d.ts +57 -0
- package/node_modules/@claude-flow/security/dist/oauth/client.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/oauth/client.js +120 -0
- package/node_modules/@claude-flow/security/dist/oauth/client.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/oauth/pkce.d.ts +25 -0
- package/node_modules/@claude-flow/security/dist/oauth/pkce.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/oauth/pkce.js +36 -0
- package/node_modules/@claude-flow/security/dist/oauth/pkce.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/password-hasher.d.ts +128 -0
- package/node_modules/@claude-flow/security/dist/password-hasher.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/password-hasher.js +190 -0
- package/node_modules/@claude-flow/security/dist/password-hasher.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/path-validator.d.ts +148 -0
- package/node_modules/@claude-flow/security/dist/path-validator.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/path-validator.js +421 -0
- package/node_modules/@claude-flow/security/dist/path-validator.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/plugins/integrity-verifier.d.ts +125 -0
- package/node_modules/@claude-flow/security/dist/plugins/integrity-verifier.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/plugins/integrity-verifier.js +186 -0
- package/node_modules/@claude-flow/security/dist/plugins/integrity-verifier.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/policy/canonical.d.ts +5 -0
- package/node_modules/@claude-flow/security/dist/policy/canonical.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/policy/canonical.js +30 -0
- package/node_modules/@claude-flow/security/dist/policy/canonical.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/policy/engine.d.ts +34 -0
- package/node_modules/@claude-flow/security/dist/policy/engine.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/policy/engine.js +285 -0
- package/node_modules/@claude-flow/security/dist/policy/engine.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/policy/envelope.d.ts +9 -0
- package/node_modules/@claude-flow/security/dist/policy/envelope.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/policy/envelope.js +90 -0
- package/node_modules/@claude-flow/security/dist/policy/envelope.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/policy/evaluator.d.ts +4 -0
- package/node_modules/@claude-flow/security/dist/policy/evaluator.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/policy/evaluator.js +119 -0
- package/node_modules/@claude-flow/security/dist/policy/evaluator.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/policy/index.d.ts +7 -0
- package/node_modules/@claude-flow/security/dist/policy/index.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/policy/index.js +7 -0
- package/node_modules/@claude-flow/security/dist/policy/index.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/policy/product-plane.d.ts +238 -0
- package/node_modules/@claude-flow/security/dist/policy/product-plane.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/policy/product-plane.js +1022 -0
- package/node_modules/@claude-flow/security/dist/policy/product-plane.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/policy/types.d.ts +169 -0
- package/node_modules/@claude-flow/security/dist/policy/types.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/policy/types.js +2 -0
- package/node_modules/@claude-flow/security/dist/policy/types.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/safe-executor.d.ts +180 -0
- package/node_modules/@claude-flow/security/dist/safe-executor.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/safe-executor.js +390 -0
- package/node_modules/@claude-flow/security/dist/safe-executor.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/token-generator.d.ts +224 -0
- package/node_modules/@claude-flow/security/dist/token-generator.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/token-generator.js +351 -0
- package/node_modules/@claude-flow/security/dist/token-generator.js.map +1 -0
- package/node_modules/@claude-flow/security/dist/tool-output-guardrail.d.ts +126 -0
- package/node_modules/@claude-flow/security/dist/tool-output-guardrail.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/tool-output-guardrail.js +257 -0
- package/node_modules/@claude-flow/security/dist/tool-output-guardrail.js.map +1 -0
- package/node_modules/@claude-flow/security/package.json +44 -0
- 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":"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"}
|
|
@@ -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
|