feat(housekeeping): correlate command audit evidence
This commit is contained in:
1 parent
7c93d3e766
commit
89dec9da05
4 files changed
+226
-4
No files matched your search
@@ -1,13 +1,28 @@
|
||||
import { count, desc, inArray, like, or } from "drizzle-orm";
|
||||
import { AdminAuditLog, db, User } from "@/lib/db";
|
||||
import type { HousekeepingDomainId } from "@/features/housekeeping/migration/types";
|
||||
import { AdminAuditLog, type Db, db, User } from "@/lib/db";
|
||||
|
||||
interface AuditEntry {
|
||||
export interface AuditEntry {
|
||||
userId: number;
|
||||
action: string;
|
||||
target: string;
|
||||
targetId?: number;
|
||||
before?: Record<string, unknown>;
|
||||
after?: Record<string, unknown>;
|
||||
correlationId?: string;
|
||||
outcome?: "intent" | "success" | "failure" | "partial" | "denied";
|
||||
reason?: string;
|
||||
domain?: HousekeepingDomainId;
|
||||
ipAddress?: string;
|
||||
}
|
||||
|
||||
export type HousekeepingAuditTransaction = Pick<Db, "insert">;
|
||||
|
||||
export interface HousekeepingAuditWriter {
|
||||
write(
|
||||
entry: AuditEntry,
|
||||
transaction?: HousekeepingAuditTransaction,
|
||||
): Promise<void>;
|
||||
}
|
||||
|
||||
const SENSITIVE_KEY_RE =
|
||||
@@ -47,7 +62,10 @@ function computeDiff(
|
||||
return Object.keys(diff).length > 0 ? diff : null;
|
||||
}
|
||||
|
||||
export async function logAudit(entry: AuditEntry): Promise<void> {
|
||||
export async function logAudit(
|
||||
entry: AuditEntry,
|
||||
transaction?: HousekeepingAuditTransaction,
|
||||
): Promise<void> {
|
||||
const sanitizedBefore = entry.before
|
||||
? (sanitizeAuditPayload(entry.before) as Record<string, unknown>)
|
||||
: undefined;
|
||||
@@ -56,7 +74,8 @@ export async function logAudit(entry: AuditEntry): Promise<void> {
|
||||
: undefined;
|
||||
const diff = computeDiff(sanitizedBefore, sanitizedAfter);
|
||||
|
||||
await db.insert(AdminAuditLog).values({
|
||||
const auditWriter: HousekeepingAuditTransaction = transaction ?? db;
|
||||
await auditWriter.insert(AdminAuditLog).values({
|
||||
userId: entry.userId,
|
||||
action: entry.action,
|
||||
target: entry.target,
|
||||
@@ -64,10 +83,19 @@ export async function logAudit(entry: AuditEntry): Promise<void> {
|
||||
before: sanitizedBefore ? JSON.stringify(sanitizedBefore) : null,
|
||||
after: sanitizedAfter ? JSON.stringify(sanitizedAfter) : null,
|
||||
diff: diff ? JSON.stringify(diff) : null,
|
||||
correlationId: entry.correlationId,
|
||||
outcome: entry.outcome,
|
||||
reason: entry.reason,
|
||||
domain: entry.domain,
|
||||
ipAddress: entry.ipAddress,
|
||||
createdAt: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
export const housekeepingAuditWriter: HousekeepingAuditWriter = {
|
||||
write: logAudit,
|
||||
};
|
||||
|
||||
interface GetLogsOptions {
|
||||
search?: string;
|
||||
page?: number;
|
||||
|
||||
Reference in new issue
Block a user