Files
skills/docs/api-stack/api/api-plugin-audit/src/context/audit-context.md
2026-05-29 08:20:56 +01:00

2.5 KiB

context/audit-context

Purpose

Builds the per-request AuditContext handle the audit middleware attaches to c.set("audit", context) before invoking next(). Handlers call c.get("audit").log({...}) to fire explicit, semantic audit events alongside the implicit per-request audit that the middleware writes. This is the public extension point for application code — instead of importing auditService and threading it through every route, handlers reach into the Hono context.

The two-method surface (log + getLogger) is intentionally small so handler code stays focused on the event payload rather than the plumbing. The same underlying AuditLogger instance is reused across every request — there is one logger per app, not one per request — so chain-integrity links hold across handler-level and middleware-level events.

Features

  • Stable two-method surface (log, getLogger).
  • Hono ContextVariableMap augmentation declared in ./context-augmentation.ts so c.get("audit") types as AuditContext (not unknown).
  • Zero per-request allocation beyond the lightweight wrapper object (no closures over the request, so the object can be cached if needed).

Usage: Basic

// In a route handler:
app.post("/users/:id/delete", async (c) => {
    const audit = c.get("audit");
    await audit.log({
        type: "user.deleted",
        severity: "warning",
        actor: { userId: c.get("user")?.id },
        target: { type: "user", id: c.req.param("id") },
    });
    return c.json({ deleted: true });
});

Usage: Advanced

// Reach the underlying logger for advanced ops:
app.get("/admin/audit-chain/verify", async (c) => {
    const logger = c.get("audit").getLogger();
    const events = await logger.query({ limit: 1000, order: "asc" });
    const verdict = await logger.verifyChainIntegrity(events);
    return c.json(verdict);
});

API Reference

  • createAuditContext(deps: { logger: AuditLogger }): AuditContext
    • log(event) → Promise<AuditEvent>
    • getLogger() → AuditLogger

Implementation Notes

AuditContext does not carry the request, the principal, or the tenant. Handlers fill actor.userId, actor.sessionId, tenantId, and so on from c.get("user") / c.get("tenant") themselves. The middleware's per-request event populates those fields automatically; handler-level events stay explicit because the handler knows the semantic of the event (which user is the actor versus the target) better than the middleware does.