/**
 * Transcript Signing
 *
 * Signs transcripts using Sigstore for keyless verification.
 * Generates in-toto provenance statements for audit compliance.
 *
 * @module transcripts/signing
 */
import { createHash } from "crypto";
import { writeFile, readFile } from "fs/promises";
// ============================================================================
// Provenance Generation
// ============================================================================
/**
 * Generate in-toto provenance statement for a transcript
 */
export function generateTranscriptProvenance(transcript, entries, metadata) {
    // Calculate digest of transcript content
    const transcriptContent = JSON.stringify(transcript);
    const transcriptHash = createHash("sha256").update(transcriptContent).digest("hex");
    return {
        _type: "https://in-toto.io/Statement/v0.1",
        predicateType: "https://vaspera.dev/attestation/transcript/v1",
        subject: [
            {
                name: `transcript:${transcript.sessionId}`,
                digest: { sha256: transcriptHash },
            },
        ],
        predicate: {
            sessionId: transcript.sessionId,
            entryCount: transcript.entryCount,
            rootHash: transcript.rootHash,
            tipHash: transcript.tipHash,
            startedAt: transcript.startedAt,
            endedAt: transcript.endedAt,
            hasRedactions: transcript.hasRedactions,
            builderVersion: "vaspera-hardening-mcp@2.1.1",
            metadata: {
                ...metadata,
                entrySummary: transcript.entrySummary,
            },
        },
    };
}
// ============================================================================
// Signing Functions
// ============================================================================
/**
 * Sign transcript content using available signing method
 */
async function signTranscriptContent(content) {
    try {
        // Try to import the signing module from sbom
        const { signContent: sigstoreSign, isSigningAvailable } = await import("../sbom/signing.js");
        const available = isSigningAvailable();
        if (!available) {
            return null;
        }
        const signedArtifact = await sigstoreSign(content);
        if (!signedArtifact.signed) {
            return null;
        }
        // Extract log ID from bundle if available
        const logId = signedArtifact.bundle?.verificationMaterial?.tlogEntries?.[0]?.logIndex;
        return {
            sig: signedArtifact.digest, // Use digest as signature identifier
            signedAt: signedArtifact.signedAt,
            rekorLogId: logId ? String(logId) : undefined,
        };
    }
    catch {
        // Signing not available
        return null;
    }
}
/**
 * Sign a transcript and generate a bundle
 */
export async function signTranscript(transcript, entries, options) {
    // Generate provenance
    const provenance = generateTranscriptProvenance(transcript, options?.includeEntries ? entries : undefined, options?.metadata);
    // Create bundle without signature
    const bundle = {
        transcript,
        provenance,
        createdAt: new Date().toISOString(),
        version: "1.0.0",
    };
    // Sign if not skipped
    if (!options?.skipSigning) {
        const provenanceJson = JSON.stringify(provenance);
        const signature = await signTranscriptContent(provenanceJson);
        if (signature) {
            bundle.signature = signature;
            bundle.transcript.signature = signature.sig;
            bundle.transcript.signedAt = signature.signedAt;
        }
    }
    return bundle;
}
/**
 * Save a signed transcript bundle to file
 */
export async function saveTranscriptBundle(bundle, filePath) {
    await writeFile(filePath, JSON.stringify(bundle, null, 2));
}
/**
 * Load a transcript bundle from file
 */
export async function loadTranscriptBundle(filePath) {
    const content = await readFile(filePath, "utf-8");
    return JSON.parse(content);
}
// ============================================================================
// Batch Signing
// ============================================================================
/**
 * Sign multiple transcripts in a batch
 */
export async function signTranscriptBatch(transcripts, options) {
    const bundles = [];
    for (const { transcript, entries } of transcripts) {
        const bundle = await signTranscript(transcript, entries, options);
        bundles.push(bundle);
    }
    return bundles;
}
// ============================================================================
// Helpers
// ============================================================================
/**
 * Check if transcript signing is available
 */
export async function isTranscriptSigningAvailable() {
    try {
        const { isSigningAvailable } = await import("../sbom/signing.js");
        return await isSigningAvailable();
    }
    catch {
        return false;
    }
}
/**
 * Generate a signature summary
 */
export function generateSigningSummary(bundle) {
    const lines = [];
    lines.push("## Transcript Signing Summary");
    lines.push("");
    lines.push(`**Session ID**: ${bundle.transcript.sessionId}`);
    lines.push(`**Entry Count**: ${bundle.transcript.entryCount}`);
    lines.push(`**Created**: ${bundle.createdAt}`);
    lines.push("");
    lines.push("### Chain Integrity");
    lines.push(`- Root Hash: \`${bundle.transcript.rootHash.slice(0, 16)}...\``);
    lines.push(`- Tip Hash: \`${bundle.transcript.tipHash.slice(0, 16)}...\``);
    lines.push(`- Has Redactions: ${bundle.transcript.hasRedactions ? "Yes" : "No"}`);
    lines.push("");
    lines.push("### Signature");
    if (bundle.signature) {
        lines.push(`- Signed At: ${bundle.signature.signedAt}`);
        lines.push(`- Signature: \`${bundle.signature.sig.slice(0, 32)}...\``);
        if (bundle.signature.rekorLogId) {
            lines.push(`- Rekor Log: ${bundle.signature.rekorLogId}`);
        }
    }
    else {
        lines.push("- Status: Unsigned");
    }
    return lines.join("\n");
}
//# sourceMappingURL=signing.js.map