/**
 * TenantProviderAgreementRegistry -- Per-tenant, per-provider BAA/DPA/SCC/BCR tracking.
 *
 * Provider-level compliance (src/security/provider-compliance.ts) answers:
 *   "Does Anthropic offer a BAA product?"
 * This module answers:
 *   "Does tenant A have a signed, active BAA with Anthropic?"
 *
 * The two questions are distinct. HIPAA 45 CFR 164.308(b) requires a Business
 * Associate Agreement between a Covered Entity and each Business Associate. An
 * Anthropic BAA held by Org A does not transfer to Org B. Without per-tenant
 * tracking, the platform cannot assert "PHI flows only to providers with a
 * tenant-active BAA" for any individual customer -- every audit, every CCO
 * Q&A, every HIPAA assessment will identify this as a control gap.
 *
 * GDPR Art. 28 parallels this: each controller-processor relationship requires
 * its own Data Processing Agreement. Tenant-scoped DPA tracking is the only
 * compliant posture.
 *
 * Gate enforcement:
 *   1. Look up bound packs for the action.
 *   2. Union all `requiredAgreementKinds` across bound packs.
 *   3. Call requireActive(tenantId, providerId, unionKinds).
 *   4. Any missing kind: throw MissingTenantProviderAgreementError + emit
 *      TENANT_PROVIDER_AGREEMENT_MISSING severity ERROR; deny the action.
 *
 * v0 storage: in-memory map. State is rebuilt on process restart.
 * v1 plan: persist to the @connexum/database Prisma store (TenantProviderAgreement
 * model) so freeze state and agreement records survive pod restarts. The v0
 * in-memory store is correct for single-process deployments; production
 * multi-pod deployments require v1 persistence.
 *
 * Document hash semantics (v0):
 *   The operator supplies a SHA-256 hash of their agreement document at
 *   registration. We store it. On every gate evaluation we compare the stored
 *   hash against itself (immutability promise at rest). An operator who later
 *   registers a *different* hash for an existing (tenantId, providerId, kind,
 *   effectiveDate) combo triggers AGREEMENT_DOCUMENT_TAMPERED (PT-BAA-2).
 *
 *   v1 plan: operator provides a signed-URL (with X-Document-Sha256 header)
 *   pointing to their document store (S3, Azure Blob, KMS-vaulted). The
 *   registry fetches the header on each gate evaluation and compares the
 *   live hash to the stored hash. Acceptable operator-side primitives:
 *   (a) S3 pre-signed URL with ETag/Content-SHA256 header, or
 *   (b) Azure Blob with x-ms-content-md5 + SHA-256 Content-MD5 equivalent, or
 *   (c) KMS attestation document (AWS KMS GenerateDataKeyPair with signed hash),
 *   or (d) Hashicorp Vault transit engine signature. Option (c) KMS attestation
 *   is recommended for HIPAA/GDPR regulated environments as it provides a
 *   hardware-root-of-trust chain. See docs/runtime/tenant-provider-agreements.md.
 *
 * Pack-binding primacy invariant: every operation that writes a record requires
 * a non-empty packBinding[]. Ref: feedback_pack_binding_primacy.md.
 *
 * Audit chain: every gate decision (allow/deny) and every lifecycle event
 * (register/revoke) emits an audit event with SHA-256 chained prev-SHA.
 *
 * Required permission: 'governance.compliance.register' (ADMIN role).
 * Enforcement: OperatorRoles.checkPermission is injected at construction time
 * to avoid circular dependency.
 *
 * @connexum/ai-governance
 */
export type AgreementKind = 'BAA' | 'DPA' | 'SCC' | 'BCRs' | 'OTHER';
export type AgreementStatus = 'ACTIVE' | 'EXPIRED' | 'REVOKED';
export type AgreementAuditSeverity = 'INFO' | 'WARNING' | 'ERROR' | 'CRITICAL';
export type AgreementEventType = 'TENANT_PROVIDER_AGREEMENT_REGISTERED' | 'TENANT_PROVIDER_AGREEMENT_REVOKED' | 'TENANT_PROVIDER_AGREEMENT_MISSING' | 'TENANT_PROVIDER_AGREEMENT_GATE_ALLOW' | 'TENANT_PROVIDER_AGREEMENT_GATE_DENY' | 'TENANT_PROVIDER_AGREEMENT_EXPIRING' | 'AGREEMENT_DOCUMENT_TAMPERED';
export interface AgreementAuditEvent {
    type: AgreementEventType;
    severity: AgreementAuditSeverity;
    tenantId: string;
    providerId: string;
    packBinding: string[];
    timestamp: string;
    prevSha?: string;
    [key: string]: unknown;
}
export interface TenantProviderAgreementRecord {
    id: string;
    tenantId: string;
    providerId: string;
    agreementKind: AgreementKind;
    agreementId?: string;
    effectiveDate: Date;
    expirationDate?: Date;
    documentRef?: string;
    documentSha256?: string;
    signedBy?: string;
    status: AgreementStatus;
    revokedAt?: Date;
    revokedReason?: string;
    packBinding: string[];
    createdAt: Date;
    registeredBy: string;
}
export interface AgreementRegistrationPayload {
    kind: AgreementKind;
    agreementId?: string;
    effectiveDate: Date;
    expirationDate?: Date;
    documentRef?: string;
    documentSha256?: string;
    signedBy?: string;
}
export declare class MissingTenantProviderAgreementError extends Error {
    readonly tenantId: string;
    readonly providerId: string;
    readonly missingKinds: string[];
    readonly packBinding: string[];
    constructor(opts: {
        tenantId: string;
        providerId: string;
        missingKinds: string[];
        packBinding: string[];
    });
}
export declare class AgreementRegistrationError extends Error {
    constructor(message: string);
}
export declare class AgreementRevocationError extends Error {
    constructor(message: string);
}
export declare class EmptyPackBindingError extends Error {
    readonly operation: string;
    constructor(operation: string);
}
export declare class AgreementPermissionError extends Error {
    readonly operatorId: string;
    constructor(operatorId: string, action: string, reason: string);
}
export interface PermissionChecker {
    checkPermission(operatorId: string, action: string): {
        allowed: boolean;
        reason: string;
    };
}
export interface TenantProviderAgreementRegistryConfig {
    /**
     * Called for every audit event emitted by this registry.
     * Wire to AuditIntegrity / EventBus in production.
     */
    onAudit?: (event: AgreementAuditEvent) => void;
    /**
     * Permission checker (typically OperatorRoles instance).
     * If not provided, a permissive stub is used (NOT for production).
     */
    permissionChecker?: PermissionChecker;
    /**
     * Tenant context for this registry instance.
     * When set, cross-tenant queries are blocked at the data layer:
     * any operation referencing a different tenantId throws.
     * Use undefined only for super-admin / system contexts.
     */
    tenantContext?: string;
}
export declare class TenantProviderAgreementRegistry {
    private readonly records;
    private readonly onAudit;
    private readonly permissionChecker;
    private readonly tenantContext?;
    private lastSha;
    constructor(config?: TenantProviderAgreementRegistryConfig);
    /**
     * Register a tenant-provider agreement.
     *
     * Operator-only (governance.compliance.register). Pack-binding mandatory.
     * Throws on effectiveDate > expirationDate.
     * Audit-chained as TENANT_PROVIDER_AGREEMENT_REGISTERED severity ERROR.
     *
     * PT-BAA-2: If an agreement with the same (tenantId, providerId, kind,
     * effectiveDate) exists and the caller supplies a different documentSha256,
     * emits AGREEMENT_DOCUMENT_TAMPERED severity ERROR before overwriting.
     */
    register(tenantId: string, providerId: string, payload: AgreementRegistrationPayload, approverIdentity: string, packBinding: string[]): TenantProviderAgreementRecord;
    /**
     * Revoke a tenant-provider agreement by kind.
     *
     * Operator-only (governance.compliance.register). Mandatory reason.
     * Sets status REVOKED on all matching ACTIVE records for this (tenant, provider, kind).
     * Audit-chained as TENANT_PROVIDER_AGREEMENT_REVOKED severity ERROR.
     */
    revoke(tenantId: string, providerId: string, agreementKind: AgreementKind, approverIdentity: string, reason: string, packBinding: string[]): void;
    /**
     * Return the first active, non-expired agreement of the given kind for this
     * (tenantId, providerId) pair, or null if none exists.
     */
    getActive(tenantId: string, providerId: string, agreementKind: AgreementKind): TenantProviderAgreementRecord | null;
    /**
     * Enforcement gate. Throws MissingTenantProviderAgreementError if any
     * required kind has no active, non-expired agreement.
     *
     * Called by upstream pack evaluation before routing PHI/PII through a provider.
     * Emits TENANT_PROVIDER_AGREEMENT_GATE_ALLOW or _GATE_DENY (both chained).
     */
    requireActive(tenantId: string, providerId: string, requiredKinds: string[], packBinding?: string[]): void;
    /**
     * Return all ACTIVE agreements expiring within the given number of days.
     * Used by operator dashboards and automated renewal reminders.
     */
    listExpiringWithin(daysAhead: number): TenantProviderAgreementRecord[];
    private tenantKey;
    /**
     * Cross-tenant isolation guard.
     * When the registry is constructed with a tenantContext, only that tenant's
     * records may be accessed. A different tenantId is a cross-tenant traversal
     * attempt (PT-BAA-1) and is blocked.
     */
    private assertTenantContext;
    private assertNonEmptyPackBinding;
    private emitEvent;
}
//# sourceMappingURL=tenant-provider-agreements.d.ts.map