"use strict";
/**
 * Security → baseline-entry producer.
 *
 * Converts the canonical `SecurityAggregate` produced by the security
 * analyzer (`src/analyzers/security/aggregator.ts`) into the per-kind
 * `BaselineEntry` shape stored in the baseline file. Pure function
 * over its input apart from the optional content-hash stamp, which
 * reads the file at the baseline commit via git (skipped when the
 * caller doesn't supply a commit SHA).
 *
 * Four `BaselineEntry` kinds are derived here, matching the four
 * categories the aggregator emits:
 *
 *   - `findingsByCategory.secret`    → kind: 'secret'
 *   - `findingsByCategory.code`      → kind: 'code'
 *   - `findingsByCategory.config`    → kind: 'config'
 *   - `findingsByCategory.dependency`→ kind: 'dep-vuln'
 *
 * The location-based `secret` entries are sufficient for tracking a
 * secret that stays in the same file. The companion `secret-hmac`
 * scheme (recognizes a leaked token moving files) requires raw
 * secret values that the aggregator doesn't carry — those entries
 * are produced by the sibling `secret-hmac.ts` producer. The two
 * schemes co-exist: a single underlying secret can be represented by
 * both a `secret` entry (location identity, stable across re-runs at
 * the same line) and a `secret-hmac` entry (content identity, stable
 * across file moves).
 *
 * Content-hash stamping (third-pass matcher fallback): when `cwd` +
 * `commitSha` are supplied, the producer reads each file at the
 * baseline commit and hashes the normalized context window around
 * the finding's line. The hash lands in `BaselineEntry.contentHash`
 * for the secret / code / config kinds; the matcher's content-hash
 * pass uses it to pair findings across runs even when git diff can't
 * map the line position. Producers can pass `undefined` for the SHA
 * (e.g., non-git directories) and content-hash matching is simply
 * unavailable for that baseline — the matcher's other passes still
 * work.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.securityAggregateToBaselineEntries = securityAggregateToBaselineEntries;
const content_hash_1 = require("../content-hash");
const finding_identity_1 = require("../finding-identity");
/**
 * Build `BaselineEntry`s from a `SecurityAggregate`. Returned in the
 * iteration order of the four categories so the produced baseline
 * stays stable across re-runs of the same scan.
 */
function securityAggregateToBaselineEntries(aggregate, options = {}) {
    const out = [];
    const stamp = (file, line) => {
        if (!options.cwd || !options.commitSha || line <= 0)
            return undefined;
        const hash = (0, content_hash_1.computeContentHashFromCommit)(options.cwd, options.commitSha, file, line);
        return hash ?? undefined;
    };
    for (const f of aggregate.findingsByCategory.secret) {
        const input = {
            kind: 'secret',
            tool: f.tool,
            rule: f.rule,
            file: f.file,
            line: f.line,
        };
        const contentHash = stamp(f.file, f.line);
        out.push({
            id: (0, finding_identity_1.identityFor)(input),
            kind: 'secret',
            tool: f.tool,
            rule: f.rule,
            file: f.file,
            line: f.line,
            ...(contentHash !== undefined ? { contentHash } : {}),
        });
    }
    for (const f of aggregate.findingsByCategory.code) {
        const input = {
            kind: 'code',
            tool: f.tool,
            rule: f.rule,
            file: f.file,
            line: f.line,
        };
        const contentHash = stamp(f.file, f.line);
        out.push({
            id: (0, finding_identity_1.identityFor)(input),
            kind: 'code',
            tool: f.tool,
            rule: f.rule,
            file: f.file,
            line: f.line,
            ...(contentHash !== undefined ? { contentHash } : {}),
        });
    }
    for (const f of aggregate.findingsByCategory.config) {
        const input = {
            kind: 'config',
            tool: f.tool,
            rule: f.rule,
            file: f.file,
            line: f.line,
        };
        // Whole-file findings (`.env in git`) carry line 0; content-hash
        // is meaningless for them and `stamp` returns undefined.
        const contentHash = stamp(f.file, f.line);
        out.push({
            id: (0, finding_identity_1.identityFor)(input),
            kind: 'config',
            tool: f.tool,
            rule: f.rule,
            file: f.file,
            line: f.line,
            ...(contentHash !== undefined ? { contentHash } : {}),
        });
    }
    for (const f of aggregate.findingsByCategory.dependency) {
        const input = {
            kind: 'dep-vuln',
            package: f.package,
            installedVersion: f.installedVersion,
            id: f.id,
        };
        const entry = {
            id: (0, finding_identity_1.identityFor)(input),
            kind: 'dep-vuln',
            package: f.package,
            advisoryId: f.id,
            ...(f.installedVersion !== undefined ? { installedVersion: f.installedVersion } : {}),
        };
        out.push(entry);
    }
    return out;
}
//# sourceMappingURL=security.js.map