/**
 * Audit Trail Module
 *
 * SPARC Architecture Reference: §6.1 (SPARC_PSEUDOCODE)
 *
 * PURPOSE: Record CLI operations for compliance and debugging
 *
 * FORBIDDEN:
 * - State Modification (audit is append-only)
 * - Error Recovery (errors recorded but not handled)
 * - Data Transformation (raw data recorded)
 */
import * as crypto from 'node:crypto';
// ============================================================================
// Audit Trail Implementation
// ============================================================================
export class AuditTrail {
    version = '1.3.2';
    entries = new Map();
    /**
     * Record a command execution
     * SPARC: Append-only, no modification of existing entries
     */
    record(input) {
        const id = crypto.randomUUID();
        const timestamp = new Date().toISOString();
        // Compute inputs hash for reproducibility
        const inputsHash = this.hashInputs(input.inputs);
        // Redact sensitive fields from inputs
        const inputsRedacted = this.redactSensitive(input.inputs);
        // Compute checksum for entry integrity
        const entryData = {
            id,
            version: this.version,
            command: input.command,
            inputs_hash: inputsHash,
            outputs: input.outputs,
            dependencies: input.dependencies.map(d => d.service),
            timestamp,
            duration_ms: input.duration_ms,
            status: input.status,
            error_code: input.error_code,
            error_message: input.error_message,
            trace_id: input.trace_id,
            parent_id: input.parent_id,
        };
        const checksum = this.computeChecksum(entryData);
        const entry = {
            id,
            version: this.version,
            command: input.command,
            inputs_hash: inputsHash,
            inputs_redacted: inputsRedacted,
            outputs: input.outputs,
            dependencies: input.dependencies.map(d => d.service),
            timestamp,
            duration_ms: input.duration_ms,
            status: input.status,
            error_code: input.error_code,
            error_message: input.error_message,
            trace_id: input.trace_id,
            parent_id: input.parent_id,
            checksum,
        };
        // Store by trace_id for retrieval
        const traceEntries = this.entries.get(input.trace_id) ?? [];
        traceEntries.push(entry);
        this.entries.set(input.trace_id, traceEntries);
        return entry;
    }
    /**
     * Get audit entries for a trace
     */
    getByTraceId(traceId) {
        return this.entries.get(traceId) ?? [];
    }
    /**
     * Format audit entry for output (JSON format)
     */
    format(entry) {
        return JSON.stringify(entry, null, 2);
    }
    // ============================================================================
    // Private Methods
    // ============================================================================
    hashInputs(inputs) {
        const canonical = JSON.stringify(inputs, this.sortKeys);
        return crypto.createHash('sha256').update(canonical).digest('hex').slice(0, 16);
    }
    sortKeys(_key, value) {
        if (value && typeof value === 'object' && !Array.isArray(value)) {
            return Object.keys(value)
                .sort()
                .reduce((sorted, key) => {
                sorted[key] = value[key];
                return sorted;
            }, {});
        }
        return value;
    }
    redactSensitive(inputs) {
        if (!inputs || typeof inputs !== 'object') {
            return inputs;
        }
        const sensitivePatterns = [
            /token/i,
            /password/i,
            /secret/i,
            /key/i,
            /auth/i,
            /credential/i,
        ];
        const redact = (obj) => {
            if (!obj || typeof obj !== 'object') {
                return obj;
            }
            if (Array.isArray(obj)) {
                return obj.map(redact);
            }
            const result = {};
            for (const [key, value] of Object.entries(obj)) {
                const isSensitive = sensitivePatterns.some(pattern => pattern.test(key));
                if (isSensitive && typeof value === 'string') {
                    result[key] = '[REDACTED]';
                }
                else if (typeof value === 'object') {
                    result[key] = redact(value);
                }
                else {
                    result[key] = value;
                }
            }
            return result;
        };
        return redact(inputs);
    }
    computeChecksum(data) {
        const canonical = JSON.stringify(data, this.sortKeys);
        return crypto.createHash('sha256').update(canonical).digest('hex');
    }
}
// ============================================================================
// Audit Logger (Console output for audit trail)
// ============================================================================
export class AuditLogger {
    destination;
    constructor(destination = 'stderr') {
        this.destination = destination;
    }
    log(entry) {
        const output = JSON.stringify({
            level: 'AUDIT',
            ...entry,
        });
        if (this.destination === 'stdout') {
            console.log(output);
        }
        else {
            console.error(output);
        }
    }
}
// ============================================================================
// Factory Functions
// ============================================================================
export function createAuditTrail() {
    return new AuditTrail();
}
export function createAuditLogger(destination) {
    return new AuditLogger(destination);
}
//# sourceMappingURL=audit-trail.js.map