Audit
Comprehensive audit logging for all admin actions with before/after diffs.
What Audit does
Every admin-plane action — config edits, secret rotations, deploy approvals — is captured as a signed audit record with before/after snapshots and the responsible actor. The chain is append-only and tamper-evident: each row is hash-linked to the previous one, so a single byte changed downstream invalidates everything after it.
The Hono adapter wires this into your HTTP layer for free. Every authenticated request emits an `audit` event with the resource type, the resource id, and a redacted snapshot of the request body. Sensitive headers (Authorization, Cookie, X-Cuitty-Signature) and payload fields (password, secret, token, apiKey) are stripped before the event leaves your process.
Wire payload
Same shape, three syntaxesThe wire protocol is plain HTTP, plain JSON, HMAC-SHA256. The TypeScript tab uses the SDK; the cURL tab is the raw HTTP equivalent; the Python tab shows the preview SDK shape.
import { createCuittyClient } from "@cuitty/sdk";
import { auditPlugin } from "@cuitty/sdk/plugins/audit";
const cuitty = createCuittyClient({
portalUrl: "https://app.cuitty.com",
projectId: process.env.CUITTY_PROJECT_ID!,
apiKey: process.env.CUITTY_API_KEY!,
});
cuitty.use(auditPlugin());
cuitty.start();
await cuitty.emit({
type: "audit",
timestamp: new Date().toISOString(),
data: {
actor: "alice@example.com",
action: "secret.rotate",
resourceType: "secret",
resourceId: "stripe.live_key",
method: "POST",
path: "/api/secrets/stripe.live_key/rotate",
statusCode: 200,
duration: 142,
},
});
Drop-in plugin
import { auditPlugin } from "@cuitty/sdk/plugins/audit";
cuitty.use(auditPlugin({
excludeRoutes: ["/health", "/metrics"],
redactBodyFields: ["password", "secret", "token"],
}));Database schema
Excerpt from modules/audit/schema.sql.
One libSQL file per module — back it up with cp.
CREATE TABLE IF NOT EXISTS audit_logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
user_email TEXT,
module_id TEXT NOT NULL,
action TEXT NOT NULL,
resource_type TEXT NOT NULL,
resource_id TEXT NOT NULL,
before_state TEXT,
after_state TEXT,
ip_address TEXT,
request_method TEXT,
request_path TEXT,
status_code INTEGER,
duration_ms INTEGER,
timestamp INTEGER DEFAULT (unixepoch())
);Related modules
Secrets
1Password-backed secrets management — integration in progress.
Configs
Configuration management and synchronization with versioning and a diff viewer.
Cloud Costs
Track cloud costs across GCP, AWS, DigitalOcean, and Azure with budget alerts.