"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultPolicyConfig = void 0;
exports.evaluateRiskPolicy = evaluateRiskPolicy;
const riskLevelOrder = {
    low: 0,
    moderate: 1,
    high: 2,
    critical: 3,
};
exports.defaultPolicyConfig = {
    enforcementLevels: {
        warnAt: 'moderate',
        requireAdrAt: 'high',
        failAt: 'critical',
    },
    riskThresholds: {
        warn: 'moderate',
        block: 'critical',
    },
    requireADR: {
        level: 'high',
    },
    baselineRegression: {
        elevateOnRegression: false,
        minimumLevelOnRegression: 'warn',
    },
    allowOverrideWithJustification: true,
};
function isAtOrAboveRiskLevel(current, threshold) {
    return riskLevelOrder[current] >= riskLevelOrder[threshold];
}
function toUpperRiskLevel(level) {
    return level.toUpperCase();
}
function policyLevelToAction(policyLevel) {
    if (policyLevel === 'fail') {
        return 'fail';
    }
    if (policyLevel === 'require-adr') {
        return 'require-adr';
    }
    if (policyLevel === 'warn') {
        return 'warn';
    }
    return 'pass';
}
function policyLevelRank(level) {
    if (level === 'advisory') {
        return 0;
    }
    if (level === 'warn') {
        return 1;
    }
    if (level === 'require-adr') {
        return 2;
    }
    return 3;
}
function toDefaultRequiredActions(policyLevel) {
    if (policyLevel === 'fail') {
        return ['Reduce architecture risk below block threshold before merge.'];
    }
    if (policyLevel === 'require-adr') {
        return ['Add or update an ADR for this architecture change before merge.'];
    }
    return undefined;
}
function resolveBasePolicyLevel(risk, config, thresholdSource) {
    const riskLevelLabel = toUpperRiskLevel(risk.level);
    if (isAtOrAboveRiskLevel(risk.level, config.enforcementLevels.failAt)) {
        return {
            policyLevel: 'fail',
            reason: `Risk level ${riskLevelLabel} meets or exceeds fail threshold ${toUpperRiskLevel(config.enforcementLevels.failAt)}.`,
            matchedThreshold: {
                id: 'fail-at',
                source: thresholdSource,
                configuredValue: config.enforcementLevels.failAt.toUpperCase(),
                matchedValue: riskLevelLabel,
            },
        };
    }
    if (isAtOrAboveRiskLevel(risk.level, config.enforcementLevels.requireAdrAt)) {
        return {
            policyLevel: 'require-adr',
            reason: `Risk level ${riskLevelLabel} meets or exceeds ADR threshold ${toUpperRiskLevel(config.enforcementLevels.requireAdrAt)}.`,
            matchedThreshold: {
                id: 'require-adr-at',
                source: thresholdSource,
                configuredValue: config.enforcementLevels.requireAdrAt.toUpperCase(),
                matchedValue: riskLevelLabel,
            },
        };
    }
    if (isAtOrAboveRiskLevel(risk.level, config.enforcementLevels.warnAt)) {
        return {
            policyLevel: 'warn',
            reason: `Risk level ${riskLevelLabel} meets or exceeds warning threshold ${toUpperRiskLevel(config.enforcementLevels.warnAt)}.`,
            matchedThreshold: {
                id: 'warn-at',
                source: thresholdSource,
                configuredValue: config.enforcementLevels.warnAt.toUpperCase(),
                matchedValue: riskLevelLabel,
            },
        };
    }
    return {
        policyLevel: 'advisory',
        reason: 'Risk level is below configured enforcement thresholds.',
        matchedThreshold: {
            id: 'below-threshold',
            source: thresholdSource,
            configuredValue: config.enforcementLevels.warnAt.toUpperCase(),
            matchedValue: riskLevelLabel,
        },
    };
}
function resolveCiExitBehavior(action) {
    if (action === 'fail') {
        return {
            blocking: true,
            exitCode: 1,
            reason: 'Policy level FAIL is blocking in CI.',
        };
    }
    return {
        blocking: false,
        exitCode: 0,
        reason: action === 'require-adr'
            ? 'Policy level REQUIRE-ADR is advisory in CI (non-blocking).'
            : action === 'warn'
                ? 'Policy level WARN is non-blocking in CI.'
                : 'Policy level ADVISORY is non-blocking in CI.',
    };
}
function evaluateRiskPolicy(risk, config, options) {
    const thresholdSource = options?.thresholdSource ?? 'default';
    const baseLevel = resolveBasePolicyLevel(risk, config, thresholdSource);
    let policyLevel = baseLevel.policyLevel;
    let matchedThreshold = baseLevel.matchedThreshold;
    let baselineContribution;
    if (config.baselineRegression.elevateOnRegression &&
        options?.baselineStatus === 'REGRESSED') {
        const baselineMinimum = config.baselineRegression.minimumLevelOnRegression;
        if (policyLevelRank(baselineMinimum) > policyLevelRank(policyLevel)) {
            baselineContribution = {
                enabled: true,
                baselineStatus: options.baselineStatus,
                elevated: true,
                previousPolicyLevel: policyLevel,
                resultingPolicyLevel: baselineMinimum,
                reason: `Baseline status REGRESSED elevated policy level from ${policyLevel.toUpperCase()} to ${baselineMinimum.toUpperCase()}.`,
            };
            policyLevel = baselineMinimum;
            matchedThreshold = {
                id: 'baseline-regression',
                source: thresholdSource,
                configuredValue: baselineMinimum.toUpperCase(),
                matchedValue: options.baselineStatus,
            };
        }
        else {
            baselineContribution = {
                enabled: true,
                baselineStatus: options.baselineStatus,
                elevated: false,
                resultingPolicyLevel: policyLevel,
                reason: `Baseline status REGRESSED did not elevate policy level because current level ${policyLevel.toUpperCase()} already meets baseline minimum ${baselineMinimum.toUpperCase()}.`,
            };
        }
    }
    else {
        baselineContribution = {
            enabled: config.baselineRegression.elevateOnRegression,
            ...(options?.baselineStatus ? { baselineStatus: options.baselineStatus } : {}),
            elevated: false,
            resultingPolicyLevel: policyLevel,
            reason: config.baselineRegression.elevateOnRegression
                ? 'Baseline regression elevation is enabled but no REGRESSED baseline status was detected.'
                : 'Baseline regression elevation is disabled by policy.',
        };
    }
    const action = policyLevelToAction(policyLevel);
    const ciExitBehavior = resolveCiExitBehavior(action);
    const reasons = [baseLevel.reason];
    if (baselineContribution?.elevated && baselineContribution.reason) {
        reasons.push(baselineContribution.reason);
    }
    return {
        action,
        policyLevel,
        enforcementDecision: action.toUpperCase(),
        matchedThreshold,
        reasons,
        thresholdSource,
        baselineContribution,
        ciExitBehavior,
        ...(toDefaultRequiredActions(policyLevel)
            ? { requiredActions: toDefaultRequiredActions(policyLevel) }
            : {}),
    };
}
//# sourceMappingURL=riskPolicyEnforcement.js.map