6548b40f17
Task O.3: IiosAuditLink (traceId/correlationId/scopeId/actorRefId/action/ resourceType/resourceId) + recordAudit() helper (reads the current trace from ALS, best-effort). Written at the decision/mutation points — route approve/deny, AI accept/reject, meeting summarize, outbound send — so the trace appears in DB and a decision can be replayed / traced across services (mandated iios_audit_link). Migration audit-link; resetDb truncates it. 2 tests bind approve/accept to a trace. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
36 lines
1.1 KiB
TypeScript
36 lines
1.1 KiB
TypeScript
import type { PrismaService } from '../prisma/prisma.service';
|
|
import { currentTraceId } from './trace-context';
|
|
|
|
export interface AuditInput {
|
|
action: string;
|
|
resourceType: string;
|
|
resourceId: string;
|
|
scopeId?: string;
|
|
actorRefId?: string;
|
|
correlationId?: string;
|
|
}
|
|
|
|
/**
|
|
* Write an audit link (P9): binds an action to its trace + actor + resource so a
|
|
* decision can be replayed / a request traced across services. Plain function — reads
|
|
* the current request's trace id from AsyncLocalStorage (no DI). Best-effort: never
|
|
* throws into the caller's happy path.
|
|
*/
|
|
export async function recordAudit(prisma: PrismaService, input: AuditInput): Promise<void> {
|
|
try {
|
|
await prisma.iiosAuditLink.create({
|
|
data: {
|
|
action: input.action,
|
|
resourceType: input.resourceType,
|
|
resourceId: input.resourceId,
|
|
scopeId: input.scopeId,
|
|
actorRefId: input.actorRefId,
|
|
traceId: currentTraceId(),
|
|
correlationId: input.correlationId ?? currentTraceId(),
|
|
},
|
|
});
|
|
} catch {
|
|
/* audit is best-effort; do not break the request */
|
|
}
|
|
}
|