Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.knoxcall.com/llms.txt

Use this file to discover all available pages before exploring further.

Audit Logs overview

KnoxCall logs every meaningful event in your tenant — secret reads, route changes, key rotations, vault tokenize / detokenize calls, webhook deliveries, admin sign-ins, policy edits — into a single audit_logs table per tenant. The log is hash-chained: each row stores a SHA-256 hash of its own contents plus the hash of the previous row. Tampering with any row breaks the chain at that point and every row after it. Auditors can replay the chain offline and detect a single byte-level change. This is what compliance frameworks like SOC 2 Type II and HIPAA call a non-repudiable audit trail — a log that’s expensive to alter without being noticed.

Why use it

ProblemWithout KnoxCallWith KnoxCall
”Who decrypted this PII record?”Per-app logs, partial coverage, easy to loseCentralised; every detokenize tagged with user / API key
”Did anyone modify production after the freeze?”Hard to proveHash-chain verifies untampered; configuration changes appear with old/new values
Compliance audit asks for 12 months of access logsMulti-app collection + format normalisationExport the table; retention configurable per plan
A leak investigation needs a precise timelineReconstruct from app logsSingle ordered timeline per tenant, sub-second timestamps

What gets logged

Every event in the audit log carries:
  • tenant_id — your tenant
  • user_id — the human user (or null for API-key actions)
  • action — verb-noun string (e.g. secret.read, route.update, vault.detokenize, crypto.rotate)
  • resource_type + resource_id — what was acted on
  • details — JSON payload with action-specific context (old/new values for updates, key version for crypto, etc.)
  • ip_address — source IP from the request
  • created_at — sub-second-precision timestamp
  • row_hash — SHA-256 of this row’s contents
  • prev_hashrow_hash of the previous row in this tenant’s chain
Categories of event that land here:
  • Secrets — create, read, update, delete, rotate. Every read is logged with the route or caller that triggered it.
  • Routes — create, update, delete, environment changes, mTLS cert binding.
  • Crypto Keys — create, rotate, encrypt, decrypt, sign, verify, JWT issue / verify, version destroy.
  • Vaults — create, tokenize, detokenize, rotate, delete (cryptographic erasure).
  • Webhooks — outbound delivery, inbound verification (verified or rejected with reason).
  • Admin — sign-in, sign-out, MFA changes, role assignments, policy edits, API key creation / revocation.
  • Tenant config — billing changes, integration adds / removes, BYOK rotation.
The proxy’s per-request audit goes into a separate table — api_requests — because the volume is much higher and the schema differs (status code, latency, response size). Audit logs cover changes and sensitive reads; api_requests covers every request.

Hash-chain integrity

Every insert into audit_logs runs a BEFORE INSERT trigger that:
  1. Reads the most recent row_hash for this tenant — that’s the previous chain link.
  2. Builds a deterministic content string from the new row’s columns + the previous hash.
  3. Sets the new row’s row_hash to the SHA-256 of that content.
  4. Sets the new row’s prev_hash to the previous row_hash.
Verifying the chain after the fact:
-- For each row: recompute the content hash and check it matches row_hash.
-- Then check that this row's prev_hash equals the prior row's row_hash.
SELECT id, created_at, action,
       (encode(sha256((COALESCE(prev_hash,'')
            || COALESCE(tenant_id::text,'')
            || COALESCE(user_id::text,'')
            || COALESCE(action,'')
            || COALESCE(resource_type,'')
            || COALESCE(resource_id::text,'')
            || COALESCE(details::text,'')
            || COALESCE(ip_address,''))::bytea), 'hex') = row_hash) AS row_hash_ok
FROM audit_logs
WHERE tenant_id = $1
ORDER BY id;
A single altered byte in any column produces a different SHA-256, which breaks the row’s own hash AND every subsequent row’s prev_hash link. The “first” altered row is provable. The trigger lives at the database level so application code can’t accidentally bypass it. Inserts go through one path; the chain is mandatory.

Retention

PlanRetention
Free7 days
Starter7 days
Pro30 days
Enterprise90 days (extensible per contract)
Older rows are pruned by a daily cron. The hash chain stays intact across pruning — pruning removes the oldest rows, never the middle, so verification of remaining rows continues to work. If you need longer retention for compliance, an Enterprise SOW can extend it to 12 months or 7 years (HIPAA / SOC 2 typical asks). The data lives in your tenant’s row partition and you can export it to long-term storage at any time.

Critical audit chain

For BYOK KMS operations, secret migration events, and tenant impersonation, KnoxCall also writes to a separate append-only table (audit_log_critical) with stronger guarantees than the standard audit_logs table:
  • Application-layer SHA-256 chain — KnoxCall code (not a Postgres trigger) computes each row’s hash over a length-prefixed canonical byte sequence. An external verifier can reproduce every hash from raw DB values without any KnoxCall involvement.
  • No pruning — the critical chain is never deleted, regardless of plan retention.
  • Serialized writes — an advisory lock prevents concurrent inserts from forking the sequence.
This table is used for the 14 actions across BYOK KMS, migration lifecycle, migration item review, migration DB proxy routes, and tenant impersonation. See the Audit Logs API reference for the full action list, row schema, and verification endpoint. The Audit Logs page in the admin UI supports:
  • Time window — last hour / 24h / 7 days / custom.
  • Action prefixsecret.*, vault.*, crypto.*, etc. for fast triage.
  • Resource — type + name search.
  • User / API key — who triggered the action.
  • Free-text search over the JSON details payload.
Each row links to a detail page that shows the full JSON details, the source IP geolocation (when available), and — for resource events — the resource as it exists today plus a link to its own audit history.

Export to SIEM

Two options:
  1. Webhook delivery — every audit row fires an outbound webhook to your endpoint of choice. Signed with HMAC-SHA256 in any of the supported webhook formats, so your SIEM can verify authenticity end-to-end.
  2. Bulk export — use the Export button in the admin UI (Logs → Audit) to download an ndjson file of the current filter set, suitable for ingestion into Splunk, Datadog, ELK, or similar.
Both methods preserve the row_hash / prev_hash columns so external systems can re-verify the chain after import.

Quick start (UI)

  1. Go to Logs → Audit in the admin UI.
  2. Filter by action (e.g. secret.read) and resource type.
  3. Click any row for the full detail view.
  4. Use the Export button (top right) for an ndjson dump of the current filter set.

Quick start (API)

# Audit logs for a specific action (exact match)
curl -H "Authorization: Bearer $KC_API_KEY" \
  "https://api.knoxcall.com/v1/audit-logs?action=secret.read&per_page=50"

# Filter by resource type
curl -H "Authorization: Bearer $KC_API_KEY" \
  "https://api.knoxcall.com/v1/audit-logs?resource_type=secret"
Supported filter parameters: action (exact action string match), resource_type, page, per_page.

Next steps