Skip to main content

Audit log

  • Sells as: the audit-log product (a product-scoped API key). This capability has no separate product-face contract — its public product route reuses the capability contract below; see the Edge route table's Product face row.

Append-only, org-scoped SOC2 audit-trail capability — one immutable write API + a forensic-replay query API, so products stop each owning a private admin-audit table and instead EMIT audit records to ONE shared, queryable compliance backend. Records are IMMUTABLE (no update/delete API — retention purge is bulk housekeeping past the legal window). I4: own Postgres store, never a product Mongo.

  • Group: Governance & platform
  • Contract: contracts/audit-log/v1/openapi.yaml
  • Console: Manage the audit-log product in the console →
  • Runbook: operational checklist for audit-log — internal (Vagary Labs ops; not part of this public site): docs/runbooks/capability-operations.md#audit-log
  • Public base: https://api.vagarylabs.com (the consolidated API gateway — one host, per-brand sibling api.<zone>)
  • Auth: a product API key (vgk_…) issued from the console — Authorization: Bearer vgk_…
  • Product face (customer-keyed):
    • https://api.vagarylabs.com/product/v1/audit/events

Edge route table​

The routes this capability actually serves on the public edge — live-synced from GET https://api.vagarylabs.com/product/v1/_meta/catalog (snapshot v1). The metric is the request-granularity billing counter; the scope is the key permission required.

Product face (customer-keyed)​

MethodPathMetricScope
POST/product/v1/audit/eventsaudit_eventswrite

Endpoints​

MethodPathSummary
POST/v1/audit/eventsRecord one immutable audit event
GET/v1/audit/eventsThe caller org's audit trail, newest-first, optionally filtered (SOC2 forensic replay)
POST/v1/audit/redact-subjectGDPR Art-17 subject erasure — pseudonymise (never delete) every audit row an actor touched, so the immutable evidentiary trail survives while the subject link is severed
GET/healthliveness
GET/metricsPrometheus

Schemas​

Outcome​

SOC2 outcome — the UNION of the platform set {success,failure,denied,partial} and the voice audit_logs status set {allowed,denied,error}. An unknown value is normalized to "success" on write (platform parity), never rejected.

AppendRequest​

FieldTypeDescription
organization_idstringproduct-tier tenant (I6); anti-spoof-verified against the token
actionstringcanonical '<resource>.<verb>' event name, e.g. 'user.unlock'
resource_typestringthe affected resource class, e.g. 'user'
resource_idstringprimary id of the affected row (if any)
actor_idstringthe acting user id (or service credential id when actor_type is service); omit/null for system/webhook actors
actor_typestringwhat kind of actor acted, e.g. 'human'
capabilitystringthe capability that produced the event, e.g. 'identity'
detailsobjectstructured context (stored raw JSONB)
outcomeobject
source_ipstringcaller IP for forensic replay
request_idstringcorrelation id across log streams
occurred_atstringevent time; defaults to server now() if omitted

AuditEvent​

FieldTypeDescription
idstring
organization_idstring
actor_idstring
actor_typestring
capabilitystring
actionstring
resource_typestring
resource_idstring
detailsobject
outcomeobject
source_ipstring
request_idstring
occurred_atstring

QueryResult​

FieldTypeDescription
eventsarray
countinteger

RedactSubjectRequest​

FieldTypeDescription
organization_idstringinformational only — tenancy is resolved anti-spoof from Authorization/X-Organization-Id, never trusted from the body
actor_idstringthe subject to pseudonymise; blank/whitespace is refused 422 (fail-closed — never a blanket redaction)
dry_runbooleanwhen true, returns the would-be match count without mutating any row

RedactSubjectResponse​

FieldTypeDescription
organization_idstring
dry_runboolean
matchedintegerrows found for this (organization_id, actor_id)
pseudonymizedintegerrows actually mutated — always 0 when dry_run is true or matched is 0

Error​

FieldTypeDescription
errorstringstable machine code (e.g. validation_error, not_found, unauthorized)
reasonstringhuman-readable one-line explanation (no secrets/PII)
detailobject
request_idstring

Generated by scripts/gen-capability-docs.py from contracts/audit-log/v1/openapi.yaml — the contract IS the source of truth; edit the contract, not this page. The Edge route table section is synced from the live edge catalog snapshot (v1) — re-sync with python3 scripts/sync-edge-catalog.py.