"use strict";
// outcome contract for audit Task input persistence.
//
// Doctrine: every audit Task records enough operator-meaningful information to
// explain what happened, AND no audit Task contains secret material. Mechanism
// is centralised here, not at the per-kind writer: form/action input
// definitions tag secret fields at the source of truth, and writers strip
// those fields via `redactSecrets` before persisting `inputs.<field>` props
// onto the Task node.
//
// Single file by design — no per-kind branching, no factory. A future
// schema shape change extends `FormSchema` here; the contract stays one place.
Object.defineProperty(exports, "__esModule", { value: true });
exports.redactSecrets = redactSecrets;
/**
 * Strip every secret-tagged field from `payload` per `schema`. Pure: no IO,
 * no logging, no thrown errors. Caller is responsible for the
 * `[task] redacted ...` log line when `droppedFields > 0`.
 *
 * Edge-case behaviour:
 * - `payload` undefined / null → empty result, droppedFields=0.
 * - `schema` undefined / no `secretFields` → every key passes through.
 * - A secret field whose key is absent from `payload` → no-op (not counted).
 * - Non-string values on a secret field → key still dropped, value never
 *   inspected. Redaction is by KEY, not by value-shape heuristic.
 */
function redactSecrets(payload, schema) {
    if (!payload) {
        return { redacted: {}, droppedFields: 0, droppedFieldNames: [] };
    }
    const secrets = new Set(schema?.secretFields ?? []);
    const redacted = {};
    const dropped = [];
    for (const [key, value] of Object.entries(payload)) {
        if (secrets.has(key)) {
            dropped.push(key);
            continue;
        }
        redacted[key] = value;
    }
    dropped.sort();
    return { redacted, droppedFields: dropped.length, droppedFieldNames: dropped };
}
//# sourceMappingURL=index.js.map