Initial Commit
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
# services/audit-service
|
||||
|
||||
## Purpose
|
||||
|
||||
Constructs the `AuditService` adapter the plugin registers in `ServiceRegistry` under the `auditService` slot. The adapter wraps a constructed `AuditLogger` from `@suaveplan/audit-logging` so downstream code depends on the stable interface declared in `../types/types.ts` instead of binding to whatever the universal library exposes today. If the library renames or removes a method later, only this adapter file changes.
|
||||
|
||||
The wrapper is intentionally thin — every method delegates to the underlying logger one-for-one — but it gives the plugin a clean seam to add cross-cutting behaviour (tenancy enforcement, OTel correlation, idempotency) without touching every call site.
|
||||
|
||||
## Features
|
||||
|
||||
- 1:1 proxy over `AuditLogger.log / query / verifyChainIntegrity / exportGDPRData / applyRetentionPolicy`.
|
||||
- `getLogger()` escape hatch for callers that need direct access (the underlying logger exposes operations not in the stable surface, e.g. event-bus introspection).
|
||||
- Constructor takes a plain `{ logger }` dependency bundle — easy to swap or stub at test time.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { AuditLogger, MemoryAuditAdapter } from "@suaveplan/audit-logging";
|
||||
import { createAuditService } from "@suaveplan/api-plugin-audit/services/audit-service";
|
||||
|
||||
const logger = new AuditLogger({
|
||||
storage: new MemoryAuditAdapter(),
|
||||
secretKey: process.env.AUDIT_SECRET_KEY!,
|
||||
});
|
||||
|
||||
const auditService = createAuditService({ logger });
|
||||
await auditService.log({
|
||||
type: "user.created",
|
||||
severity: "info",
|
||||
actor: { userId: "u1" },
|
||||
});
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import {
|
||||
AuditLogger,
|
||||
MemoryAuditAdapter,
|
||||
type AuditEvent,
|
||||
} from "@suaveplan/audit-logging";
|
||||
import { createAuditService } from "@suaveplan/api-plugin-audit/services/audit-service";
|
||||
|
||||
const auditService = createAuditService({
|
||||
logger: new AuditLogger({
|
||||
storage: new MemoryAuditAdapter(),
|
||||
secretKey: process.env.AUDIT_SECRET_KEY!,
|
||||
enableChainIntegrity: true,
|
||||
}),
|
||||
});
|
||||
|
||||
const events: AuditEvent[] = await auditService.query({
|
||||
userId: "u1",
|
||||
limit: 50,
|
||||
order: "desc",
|
||||
});
|
||||
|
||||
const verdict = await auditService.verifyChainIntegrity(events);
|
||||
if (!verdict.valid) {
|
||||
console.error("chain broken at", verdict.brokenAt, verdict.reason);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `createAuditService(deps: { logger: AuditLogger }): AuditService`
|
||||
- Returns an object satisfying the `AuditService` interface from `../types/types.ts`.
|
||||
- Methods: `getLogger()`, `log(event)`, `query(opts)`, `verifyChainIntegrity(events)`, `exportGDPRData(userId, signal?)`, `applyRetentionPolicy(signal?)`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
Every method returns the underlying `Promise` directly — no wrapping, no try/catch — because the plugin's middleware path handles sink failures explicitly via `audit.sink_failures_total`. Consumers that call `auditService.log(...)` from a handler get the raw `AuditError` from `@suaveplan/audit-logging` and can branch on its codes. This separation keeps the middleware (which must never throw into the request response) and the handler-level helper (which can surface failures) consistent.
|
||||
Reference in New Issue
Block a user