/**
 * Capability Broker contract (P9) — the single governed egress boundary.
 *
 * IIOS prepares idempotent outbound commands; the broker gates them through
 * policy, enforces the returned obligations, and routes to a provider. In dev the
 * provider is a sandbox (no network); a real provider is a binding/config swap.
 * This is the concrete realization of the `capability` platform port.
 */
import type { DataClass } from './events';
import type { PolicyDecision } from './ports';

/** One obligation the broker must enforce before/at egress. */
export type PolicyObligation = PolicyDecision['obligations'][number];

export type CapabilityOutcome = 'SENT' | 'BLOCKED' | 'FAILED' | 'RATE_LIMITED';

export interface CapabilityRequest {
  /** Dotted capability name, e.g. "channel.send". */
  capability: string;
  scopeId?: string;
  channelType: string;
  target: string;
  payload: Record<string, unknown>;
  idempotencyKey: string;
  /** CMP purpose code for the consent check (e.g. 'outbound_message', 'marketing'). */
  purpose?: string;
  dataClass?: DataClass;
}

export interface CapabilityResult {
  providerRef: string;
  outcome: CapabilityOutcome;
  errorCode?: string;
  latencyMs?: number;
  /** The CMP consent receipt this egress went out under (provenance). */
  consentReceiptRef?: string;
}

/** What a provider reports; the broker normalizes `outcome` into CapabilityResult. */
export interface ProviderResult {
  providerRef: string;
  outcome: string;
  errorCode?: string;
  latencyMs?: number;
}

/**
 * A pluggable egress provider. Sandbox (no network) by default; real providers
 * (WhatsApp/SMTP/HTTP webhook) implement the same shape. Must be idempotent and
 * must surface transport errors as FAILED rather than throwing.
 */
export interface CapabilityProvider {
  readonly name: string;
  readonly channelTypes: string[];
  readonly capabilities: { canSend: boolean; maxPayloadBytes?: number };
  send(req: CapabilityRequest): Promise<ProviderResult>;
}
