/**
 * Platform ports contract — copied verbatim from the Bottom-Up Evolution Atlas
 * "Platform ports contract" TS block (the single source of truth).
 *
 * These describe the platform-governance fabric (Session/OPA/CMP/MDM/CRRE/SAS/
 * Capability) that OTHER teams own and that does not exist yet. IIOS consumes
 * them through this interface; in dev/test it binds to deterministic fakes
 * (@insignia/iios-testkit). In prod it binds to the real services. The kernel
 * never builds these — it only depends on the contract.
 */

export interface PlatformPrincipal {
  principalRef: string;
  accountSubject?: string;
  canonicalEntityId?: string;
  orgId: string;
  appId: string;
  tenantId?: string;
  workspaceId?: string;
  assurance: 'anonymous' | 'authenticated' | 'mfa' | 'service';
  delegationChain?: string[];
}

export interface PolicyDecision {
  decisionRef: string;
  allow: boolean;
  obligations: Array<{
    kind: 'MASK' | 'REVIEW' | 'AUDIT' | 'DENY_OUTBOUND' | 'REDACT';
    target?: string;
    reason: string;
  }>;
  ttlSeconds: number;
}

export interface ContextDecisionBundle {
  bundleRef: string;
  scopeHash: string;
  resourceSet: Array<{ type: string; id: string; relation?: string }>;
  constraints: Array<{ kind: string; value: unknown; sourceRule: string }>;
  routeHints?: Array<{ routeBindingId: string; mode: 'SIMULATION_ONLY' | 'MANUAL' | 'AUTOMATIC' }>;
}

export interface SourceHandleResolution {
  canonicalEntityId?: string;
  confidence: number;
  status: string;
}

export interface IiosPlatformPorts {
  session: { verify(token: string): Promise<PlatformPrincipal> };
  opa: { decide(input: unknown): Promise<PolicyDecision> };
  cmp: { checkPurpose(input: unknown): Promise<{ receiptRef?: string; status: 'ALLOW' | 'DENY' | 'NOT_REQUIRED' }> };
  mdm: { resolveSourceHandle(input: unknown): Promise<SourceHandleResolution> };
  crre: { resolve(input: unknown): Promise<ContextDecisionBundle> };
  sas: { tokenizeParts(parts: unknown[]): Promise<unknown[]> };
  capability: { invoke(input: unknown): Promise<{ providerRef: string; outcome: string }> };
}
