36 lines
1.2 KiB
TypeScript
36 lines
1.2 KiB
TypeScript
import type { AuditEntry } from "@repo/core-shared/audit";
|
|
import type { IAuditLog } from "./audit-log.interface";
|
|
|
|
/**
|
|
* Writes one structured JSON line per audit entry to stdout. A log shipper
|
|
* (Vector, Fluent Bit) picks these up and forwards to the centralized
|
|
* aggregator (Grafana Cloud, Datadog, Loki EU, etc.).
|
|
*
|
|
* Lines include a `_type` discriminator so the shipper can route:
|
|
* "audit" → audit entry
|
|
* "audit-erasure" → GDPR erasure tombstone
|
|
*
|
|
* `eraseSubject` is best-effort: past stdout lines can't be retroactively
|
|
* removed. The tombstone informs the downstream aggregator to filter/delete.
|
|
*/
|
|
export class StdoutJsonAuditLog implements IAuditLog {
|
|
async record(entry: AuditEntry): Promise<void> {
|
|
const serialized = JSON.stringify({
|
|
_type: "audit",
|
|
...entry,
|
|
at: entry.at.toISOString(),
|
|
});
|
|
process.stdout.write(serialized + "\n");
|
|
}
|
|
|
|
async eraseSubject(actorId: string, mode: "pseudonymize" | "delete"): Promise<void> {
|
|
const tombstone = {
|
|
_type: "audit-erasure",
|
|
actorId,
|
|
mode,
|
|
at: new Date().toISOString(),
|
|
};
|
|
process.stdout.write(JSON.stringify(tombstone) + "\n");
|
|
}
|
|
}
|