Coppice records API/envd decisions at the gateway boundary. The audit feed captures mutating requests, auth failures, scope denials, and HTTP errors with tenant labels when API-key auth is enabled.
What is recorded
Each event contains:
eventID,timestamp,method,path,status, andoutcome.tenantID,principalName, andscopeswhen a request authenticated with an API key.- A short
messagefor denials such as missing keys or insufficient scope.
Successful GET/HEAD reads are intentionally
not logged to keep the feed useful. Failed reads are logged. Successful
POST, PATCH, PUT, and
DELETE requests are logged.
API
curl -H "Authorization: Bearer $COPPICE_TOKEN" \
"http://127.0.0.1:3000/audit/events?limit=50"
The route requires admin scope when API-key auth is
enabled. Query parameters:
| parameter | effect |
|---|---|
limit | return at most this many events, capped at 500 |
offset | skip events after filtering |
orderAsc=true | oldest-first instead of newest-first |
tenantID / tenant | filter to one tenant |
outcome | filter to allowed, denied, or error |
pathPrefix | filter by route prefix |
The response is:
{
"events": [
{
"eventID": "8b7...",
"timestamp": "2026-04-27T00:18:45Z",
"outcome": "denied",
"method": "GET",
"path": "/audit/events",
"status": 403,
"tenantID": "team-b",
"scopes": ["read"],
"message": "API key lacks required scope: admin"
}
],
"count": 1
}
Persistence
The in-memory ring is enabled by default and keeps the newest 2048
events. Set COPPICE_AUDIT_LOG_CAP to tune that.
For durable JSONL, set:
export COPPICE_AUDIT_LOG=/var/log/coppice-audit.jsonl
export COPPICE_AUDIT_LOG_CAP=4096
service e2b-compat restart
The gateway creates the parent directory and appends each event as one JSON object per line. If the append fails, the in-memory ring still records the event and the gateway logs a warning.
Admin view
The Astro admin dashboard reads /audit/events?limit=12 and
renders the most recent decisions next to lifecycle and metrics panels.
In local dev, astro.config.mjs proxies /audit
to COPPICE_ADMIN_GATEWAY or http://127.0.0.1:3001.
Receipt: benchmarks/results/api-key-auth/latest.txt.