46 lines
1.4 KiB
JavaScript
46 lines
1.4 KiB
JavaScript
import fs from "node:fs";
|
|
import path from "node:path";
|
|
|
|
function redacted(value) {
|
|
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
const scrubbed = {};
|
|
for (const [key, item] of Object.entries(value)) {
|
|
if (key === "token" || key === "authorization" || key === "secret" || key === "credential") {
|
|
continue;
|
|
}
|
|
if (item && typeof item === "object") {
|
|
scrubbed[key] = redacted(item);
|
|
} else if (typeof item === "string" && ["x-aios-token", "x-api-token", "authorization"].includes(key.toLowerCase())) {
|
|
scrubbed[key] = "[redacted]";
|
|
} else {
|
|
scrubbed[key] = item;
|
|
}
|
|
}
|
|
return scrubbed;
|
|
}
|
|
|
|
function appendRecord(auditPath, record) {
|
|
const parent = path.dirname(auditPath);
|
|
fs.mkdirSync(parent, { recursive: true, mode: 0o750 });
|
|
const fd = fs.openSync(auditPath, "a", 0o640);
|
|
try {
|
|
fs.writeSync(fd, `${JSON.stringify(record)}\n`, null, "utf8");
|
|
fs.fsyncSync(fd);
|
|
} finally {
|
|
fs.closeSync(fd);
|
|
}
|
|
fs.chmodSync(auditPath, 0o640);
|
|
}
|
|
|
|
export function appendDispatchAudit(auditPath, record) {
|
|
if (!auditPath) return;
|
|
const absolute = path.isAbsolute(auditPath);
|
|
if (!absolute) throw new Error("invalid_audit_path");
|
|
const payload = {
|
|
schema_version: "aios.protected-dispatch-audit/v1",
|
|
recorded_at: Date.now(),
|
|
...(redacted(record) || {}),
|
|
};
|
|
appendRecord(auditPath, payload);
|
|
}
|