// SPDX-License-Identifier: Apache-2.0
// Copyright 2024-2026 Vorion LLC
/**
 * CAR Integration for Trust Engine
 *
 * Bridges CAR identity layer with Vorion runtime trust enforcement.
 *
 * **CRITICAL DESIGN PRINCIPLE:**
 * The CAR is an IMMUTABLE identifier. Trust is NOT embedded in the CAR.
 * Trust is computed at RUNTIME from:
 * 1. Attestations (external certifications linked to the CAR identity)
 * 2. Behavioral signals (runtime observations)
 * 3. Deployment context policies
 *
 * This separation ensures:
 * - CAR remains stable (like a passport number)
 * - Trust can evolve independently
 * - Same agent can have different trust in different deployments
 *
 * @packageDocumentation
 */
import { getCARIdentity, } from '@vorionsys/contracts/car';
import { createLogger } from '../common/logger.js';
import { z } from 'zod';
const logger = createLogger({ component: 'car-integration' });
// ============================================================================
// Helper Functions
// ============================================================================
/**
 * Convert CertificationTier to RuntimeTier
 * Both use 0-5 values, so we can safely convert via unknown
 */
function certificationToRuntimeTier(certTier) {
    return certTier;
}
/**
 * Default certification tier when no attestation exists
 */
const DEFAULT_CERTIFICATION_TIER = 0; // T0: Unverified
// ============================================================================
// Zod Schemas for Validation
// ============================================================================
/**
 * Schema for Attestation validation
 */
export const AttestationSchema = z.object({
    id: z.string().uuid(),
    subject: z.string(),
    issuer: z.string(),
    trustTier: z.number().int().min(0).max(7),
    scope: z.array(z.string()),
    issuedAt: z.date(),
    expiresAt: z.date(),
    evidence: z.array(z.string()),
});
// ============================================================================
// Tier/Score Conversion Utilities
// ============================================================================
/**
 * Tier to minimum score mapping (aligned with TRUST_THRESHOLDS)
 */
const TIER_TO_MIN_SCORE = {
    0: 0, // T0_SANDBOX
    1: 200, // T1_OBSERVED
    2: 350, // T2_PROVISIONAL
    3: 500, // T3_MONITORED
    4: 650, // T4_STANDARD
    5: 800, // T5_TRUSTED
    6: 876, // T6_CERTIFIED
    7: 951, // T7_AUTONOMOUS
};
/**
 * Tier to maximum score mapping (aligned with TIER_TO_MIN_SCORE)
 */
const TIER_TO_MAX_SCORE = {
    0: 199, // T0_SANDBOX: 0-199
    1: 349, // T1_OBSERVED: 200-349
    2: 499, // T2_PROVISIONAL: 350-499
    3: 649, // T3_MONITORED: 500-649
    4: 799, // T4_STANDARD: 650-799
    5: 875, // T5_TRUSTED: 800-875
    6: 950, // T6_CERTIFIED: 876-950
    7: 1000, // T7_AUTONOMOUS: 951-1000
};
/**
 * Convert certification tier to minimum trust score
 */
export function certificationTierToMinScore(tier) {
    return TIER_TO_MIN_SCORE[certificationToRuntimeTier(tier)] ?? 0;
}
/**
 * Convert certification tier to maximum trust score
 */
export function certificationTierToMaxScore(tier) {
    return TIER_TO_MAX_SCORE[certificationToRuntimeTier(tier)] ?? 1000;
}
/**
 * Convert certification tier to a representative trust score
 */
export function certificationTierToScore(tier) {
    const runtimeTier = certificationToRuntimeTier(tier);
    const min = TIER_TO_MIN_SCORE[runtimeTier] ?? 0;
    const max = TIER_TO_MAX_SCORE[runtimeTier] ?? 199;
    return Math.floor((min + max) / 2);
}
/**
 * Convert trust score to runtime tier
 */
export function scoreToTier(score) {
    if (score >= 951)
        return 7; // T7_AUTONOMOUS
    if (score >= 876)
        return 6; // T6_CERTIFIED
    if (score >= 800)
        return 5; // T5_TRUSTED
    if (score >= 650)
        return 4; // T4_STANDARD
    if (score >= 500)
        return 3; // T3_MONITORED
    if (score >= 350)
        return 2; // T2_PROVISIONAL
    if (score >= 200)
        return 1; // T1_OBSERVED
    return 0; // T0_SANDBOX
}
/**
 * Get minimum score for a given tier
 */
export function tierToMinScore(tier) {
    return TIER_TO_MIN_SCORE[tier] ?? 0;
}
/**
 * Convert competence level to ceiling tier
 */
export function competenceLevelToCeiling(level) {
    if (typeof level === 'number') {
        return Math.min(7, level);
    }
    const levelMap = {
        none: 0,
        basic: 1,
        intermediate: 2,
        advanced: 3,
        expert: 4,
        master: 5,
        certified: 6,
        autonomous: 7,
    };
    return levelMap[String(level).toLowerCase()] ?? 2;
}
// ============================================================================
// Core CAR Integration Functions
// ============================================================================
/**
 * Determine which factor is limiting the effective tier
 */
export function determineCeilingReason(ctx, effectiveTier) {
    const certTierAsRuntime = certificationToRuntimeTier(ctx.certificationTier);
    if (effectiveTier === certTierAsRuntime) {
        if (!ctx.hasValidAttestation) {
            return 'Limited by lack of attestation (default T0)';
        }
        return 'Limited by attestation certification tier';
    }
    if (effectiveTier === competenceLevelToCeiling(ctx.competenceLevel)) {
        return 'Limited by competence level';
    }
    if (effectiveTier === ctx.runtimeTier) {
        return 'Limited by runtime behavioral trust';
    }
    if (effectiveTier === ctx.observabilityCeiling) {
        return 'Limited by observability class';
    }
    if (effectiveTier === ctx.contextPolicyCeiling) {
        return 'Limited by deployment context policy';
    }
    return undefined;
}
/**
 * Calculate effective permission from CAR context
 *
 * The effective tier is the minimum of:
 * 1. Certification tier (from attestations, NOT the CAR itself)
 * 2. Competence ceiling (what the agent's capability allows)
 * 3. Runtime tier (what behavioral signals indicate)
 * 4. Observability ceiling (what we can verify)
 * 5. Context policy ceiling (what the deployment allows)
 */
export function calculateEffectiveFromCAR(ctx) {
    const effectiveTier = Math.min(certificationToRuntimeTier(ctx.certificationTier), competenceLevelToCeiling(ctx.competenceLevel), ctx.runtimeTier, ctx.observabilityCeiling, ctx.contextPolicyCeiling);
    logger.debug({
        identity: ctx.identity,
        certificationTier: ctx.certificationTier,
        hasValidAttestation: ctx.hasValidAttestation,
        competenceCeiling: competenceLevelToCeiling(ctx.competenceLevel),
        runtimeTier: ctx.runtimeTier,
        observabilityCeiling: ctx.observabilityCeiling,
        contextPolicyCeiling: ctx.contextPolicyCeiling,
        effectiveTier,
    }, 'Calculated effective tier from CAR context');
    return {
        tier: effectiveTier,
        score: tierToMinScore(effectiveTier),
        domains: [...ctx.operationalDomains],
        level: ctx.competenceLevel,
        ceilingReason: determineCeilingReason(ctx, effectiveTier),
    };
}
/** @deprecated Use calculateEffectiveFromCAR instead */
export const calculateEffectiveFromACI = calculateEffectiveFromCAR;
/**
 * Create a CAR Trust Context from a parsed CAR and attestation lookup.
 */
export function createCARTrustContext(parsedCAR, attestation, runtimeScore, observabilityCeiling, contextCeiling) {
    const identity = getCARIdentity(parsedCAR);
    const certificationTier = attestation?.trustTier ?? DEFAULT_CERTIFICATION_TIER;
    const hasValidAttestation = attestation !== null && attestation.expiresAt > new Date();
    const runtimeTier = scoreToTier(runtimeScore);
    const effectiveTier = Math.min(certificationToRuntimeTier(certificationTier), competenceLevelToCeiling(parsedCAR.level), runtimeTier, observabilityCeiling, contextCeiling);
    const effectiveScore = calculateEffectiveScoreFromFactors(runtimeScore, certificationTier, observabilityCeiling, contextCeiling);
    return {
        car: parsedCAR,
        identity,
        competenceLevel: parsedCAR.level,
        operationalDomains: [...parsedCAR.domains],
        certificationTier,
        hasValidAttestation,
        attestationExpiresAt: attestation?.expiresAt,
        runtimeTier,
        runtimeScore,
        observabilityCeiling,
        contextPolicyCeiling: contextCeiling,
        effectiveTier,
        effectiveScore,
    };
}
/** @deprecated Use createCARTrustContext instead */
export const createACITrustContext = createCARTrustContext;
/**
 * Calculate effective score from multiple factors.
 */
function calculateEffectiveScoreFromFactors(runtimeScore, certificationTier, observabilityCeiling, contextCeiling) {
    let score = applyCARFloor(runtimeScore, certificationTier);
    score = enforceCARCeiling(score, certificationTier);
    const observabilityMax = TIER_TO_MAX_SCORE[observabilityCeiling];
    score = Math.min(score, observabilityMax);
    const contextMax = TIER_TO_MAX_SCORE[contextCeiling];
    score = Math.min(score, contextMax);
    return score;
}
/**
 * Convert attestation to Vorion trust signal
 */
export function attestationToTrustSignal(attestation) {
    return {
        id: crypto.randomUUID(),
        entityId: attestation.subject,
        type: 'ATTESTATION',
        value: certificationTierToScore(attestation.trustTier),
        weight: 1.0,
        source: attestation.issuer,
        timestamp: attestation.issuedAt.toISOString(),
        metadata: {
            scope: attestation.scope,
            expiresAt: attestation.expiresAt.toISOString(),
            evidence: attestation.evidence,
            attestationId: attestation.id,
        },
    };
}
/**
 * Apply CAR floor to runtime trust
 *
 * An agent with T3 certification starts at minimum T3 score.
 * The certification tier provides a "floor".
 */
export function applyCARFloor(runtimeScore, certificationTier) {
    const floorScore = certificationTierToMinScore(certificationTier);
    const result = Math.max(runtimeScore, floorScore);
    if (result > runtimeScore) {
        logger.debug({ runtimeScore, floorScore, result, certificationTier }, 'Applied CAR floor to runtime score');
    }
    return result;
}
/** @deprecated Use applyCARFloor instead */
export const applyACIFloor = applyCARFloor;
/**
 * Enforce CAR ceiling on runtime trust
 *
 * Runtime cannot exceed what the agent is certified for.
 */
export function enforceCARCeiling(runtimeScore, certificationTier) {
    const ceilingScore = certificationTierToMaxScore(certificationTier);
    const result = Math.min(runtimeScore, ceilingScore);
    if (result < runtimeScore) {
        logger.debug({ runtimeScore, ceilingScore, result, certificationTier }, 'Enforced CAR ceiling on runtime score');
    }
    return result;
}
/** @deprecated Use enforceCARCeiling instead */
export const enforceACICeiling = enforceCARCeiling;
/**
 * Calculate effective tier combining multiple factors
 */
export function calculateEffectiveTier(certificationTier, competenceLevel, runtimeTier, observabilityCeiling, contextCeiling) {
    return Math.min(certificationToRuntimeTier(certificationTier), competenceLevelToCeiling(competenceLevel), runtimeTier, observabilityCeiling, contextCeiling);
}
/**
 * Calculate effective score combining multiple factors
 */
export function calculateEffectiveScore(certificationTier, runtimeScore, observabilityCeiling, contextCeiling) {
    let score = applyCARFloor(runtimeScore, certificationTier);
    score = enforceCARCeiling(score, certificationTier);
    const observabilityMax = TIER_TO_MAX_SCORE[observabilityCeiling];
    score = Math.min(score, observabilityMax);
    const contextMax = TIER_TO_MAX_SCORE[contextCeiling];
    score = Math.min(score, contextMax);
    return score;
}
/**
 * Look up the certification tier for a CAR identity from attestations.
 */
export function lookupCertificationTier(identity, attestations) {
    const now = new Date();
    const validAttestations = attestations.filter((a) => a.subject === identity && a.expiresAt > now);
    if (validAttestations.length === 0) {
        logger.debug({ identity }, 'No valid attestations found, using default tier');
        return DEFAULT_CERTIFICATION_TIER;
    }
    const maxTier = Math.max(...validAttestations.map((a) => a.trustTier));
    logger.debug({ identity, attestationCount: validAttestations.length, maxTier }, 'Found valid attestations for identity');
    return maxTier;
}
//# sourceMappingURL=car-integration.js.map