feat(p9): Capability Broker — governed egress + fail-closed gate + obligations

Tasks 9.1+9.2: contracts (CapabilityRequest/Result/Provider, PolicyObligation) +
service CapabilityBroker that fails closed via opa (PolicyDeniedError, nothing sent),
enforces obligations before any provider call (DENY_OUTBOUND/REVIEW → BLOCKED;
MASK/REDACT → mask payload field), then routes to a CapabilityProviderRegistry
(SandboxProvider default; env-gated HttpProvider overrides per channel; unknown
channel fails closed). 5 tests: allow/deny/block/redact/unknown-channel.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-01 19:58:25 +05:30
parent e11964b8bc
commit c50a501f32
9 changed files with 455 additions and 0 deletions
@@ -0,0 +1,14 @@
import { Module } from '@nestjs/common';
import { CapabilityProviderRegistry } from './capability.registry';
import { CapabilityBroker } from './capability.broker';
/**
* The governed egress boundary (P9 slice 1). Exports the broker + registry so the
* outbound layer routes all sends through policy + obligations + a pluggable
* provider. PLATFORM_PORTS (for the opa gate) comes from the @Global PlatformModule.
*/
@Module({
providers: [CapabilityProviderRegistry, CapabilityBroker],
exports: [CapabilityBroker, CapabilityProviderRegistry],
})
export class CapabilityModule {}