Durable Audit API (Bun)
Relevant source files
The following files were used as context for generating this wiki page:
The Durable Audit API is a TypeScript-based service running on the Bun runtime that provides a high-performance, queryable interface over historical audit logs generated by the Honmoon data plane. Unlike the in-process management API (honmoon-mgmt), which handles live, in-memory data and real-time approvals, this API focuses on the long-term, durable storage provided by the JSONL audit files written by the gateway proxy.
It serves as the historical query layer for the Control Plane & Dashboard, allowing users to filter and analyze past decisions made by the policy engine. The service implements a robust query logic that includes filtering by decision type, domain, and time ranges, while utilizing a localized cache to coalesce high-frequency polling bursts.
Architecture and Data Flow
The API follows a decoupled architecture where the TypeScript service reads from a JSONL file appended to by the Rust data plane. This ensures that historical audit queries do not put a load on the performance-critical proxy loop.
The diagram above shows the unidirectional flow of audit data from the proxy to the persistent JSONL storage, and the subsequent retrieval path via the Bun API.
Sources: wiki/deep-dive/control-plane.md:25-45, packages/api/src/index.ts:1-20
Component Responsibilities
| Component | Responsibility | Relevant Files |
|---|---|---|
| Gateway Proxy | Generates AuditEvent objects and appends them to a persistent JSONL file. | wiki/deep-dive/control-plane.md:25-45 |
| Query Logic | Parses JSONL streams and applies filters (limit, decision, since, domain). | packages/api/src/audit.ts:1-40 |
| Bun Server | Handles HTTP requests, manages CLI arguments for file paths, and implements caching. | packages/api/src/index.ts:1-60 |
| Read Cache | Prevents redundant disk I/O by caching audit results for 1 second. | packages/api/src/index.ts:20-35 |
API Endpoints and Parameters
The service exposes two primary GET endpoints for retrieving audit data and summary statistics.
GET /api/audit
Retrieves a list of filtered and sorted audit events. Results are sorted by timestamp rather than ID because IDs may restart if the gateway process restarts, whereas timestamps provide a reliable historical sequence.
| Parameter | Type | Description | Default |
|---|---|---|---|
limit | number | Maximum number of records to return. | 100 |
decision | string | Filter by verdict (e.g., allowed, denied, paused). | None |
since | string | ISO timestamp to filter events occurring after a specific time. | None |
domain | string | Filter by the target domain of the request. | None |
Sources: packages/api/src/audit.ts:43-69, packages/api/src/index.ts:45-55
GET /api/audit/stats
Provides a summary of total counts categorized by the decision verdict. This is used by the dashboard overview to display activity metrics.
Sources: packages/api/src/audit.ts:74-83, packages/api/src/index.ts:50-52
Data Processing Logic
The API utilizes a stream-based approach to read the JSONL audit file, which allows it to handle large logs efficiently without loading the entire file into memory at once.
Event Filtering and Sorting
The filtering logic is centralized in the queryAuditLog function. It processes each line of the JSONL file, parses the JSON object, and applies conditional checks based on the request parameters.
The sequence illustrates the request lifecycle, highlighting the timestamp-based sorting and the cache-first approach.
Sources: packages/api/src/audit.ts:43-69, packages/api/src/index.ts:20-35
Correctness and Testing
As the repository's first major TypeScript test suite, the Durable Audit API includes comprehensive unit tests in audit.test.ts. These tests ensure that:
- Empty or missing files return appropriate empty results.
- Filtering by decision (e.g.,
allowedvsdenied) correctly reduces the dataset. - The
limitparameter is strictly enforced. - Timestamp sorting correctly handles out-of-order appends or ID resets.
Sources: packages/api/src/audit.test.ts:1-120, packages/AGENTS.md:20-25
Implementation Details
The server is configured via command-line arguments when started by the Bun runtime.
// packages/api/src/index.ts:11-15
const auditFile = process.argv[2] || "audit.jsonl";
const port = parseInt(process.argv[3] || "8445");
console.log(`Starting Audit API on port ${port}, reading from ${auditFile}`);
Cache Mechanism
A simple in-memory cache is used to protect the filesystem from excessive reads during rapid dashboard polling.
- Cache Key: A JSON-serialized string of the filter parameters.
- TTL: 1 second.
- Invalidation: Automatic expiration after the 1000ms window.
Sources: packages/api/src/index.ts:20-35, wiki/deep-dive/control-plane.md:120-130
Conclusion
The Durable Audit API provides a robust, test-verified mechanism for accessing historical Honmoon audit data. By separating the durable query layer from the live proxy state, the system maintains performance while providing the deep visibility required for security compliance and troubleshooting. It effectively bridges the gap between the Rust data plane's raw logs and the TypeScript control plane's visualization requirements.