Audit Logs
Every mutation in oikapi is recorded in an immutable, append-only audit log. This includes record changes, schema modifications, permission changes, and authentication events.
What gets logged
Section titled “What gets logged”| Operation | Details tracked |
|---|---|
| Record create | User, table, new values |
| Record update | User, table, before/after diff |
| Record delete | User, table, deleted values |
| Schema changes | Table/field creation, modification, deletion |
| Auth events | Login, logout, credential access |
| Permission changes | Grants, revocations, role assignments |
Viewing audit logs
Section titled “Viewing audit logs”Audit history is read through dedicated, permission-aware endpoints rather than generic record queries:
GET /api/apps/{app}/tables/{table}/records/{record_id}/historyGET /api/apps/{app}/tables/{table}/activityThe first returns the change history for a single record; the second returns recent activity across the whole table. Both use cursor-based pagination.
Each log entry contains:
| Field | Description |
|---|---|
id | Unique identifier for this audit entry |
operation | create, update, or delete for record history; CREATE, UPDATE, DELETE, or other action codes for table activity |
user | Object with id, name, and email of the actor |
changes | Structured change record (see below) |
timestamp | When the change occurred |
version | Monotonic version counter; only populated on table-activity entries (/activity endpoint) — always 0 in record history (/history) responses |
Change diffs
Section titled “Change diffs”The changes field carries a structured change record. Each key is a field name, and each value is a two-element array [old_value, new_value]. For create operations the old value is null; for delete operations the prior record is captured under a _deleted_ key.
{ "status": ["draft", "active"], "budget": ["10000.00", "15000.00"]}System and auto-generated fields (such as created_at, updated_at, created_by, updated_by) are excluded from change records, so diffs focus on meaningful business changes.
Field-level filtering
Section titled “Field-level filtering”Audit log diffs are filtered based on the requesting user’s field-level permissions. If a user cannot read the salary field, they won’t see salary changes in audit logs either. Admins see complete, unfiltered diffs.
Sensitive data redaction
Section titled “Sensitive data redaction”Fields can be marked as PII (pii: true) or sensitive (sensitive: true) when creating or adding fields to a table. PII and sensitive field values are excluded from full-text search indexes. Note that field-level PII redaction inside audit log diffs (record history) is not yet implemented — raw values are visible to users who have read access to the record. For audit trail exports (the download endpoints), the actor’s email address and IP address are redacted via the oikapi/redaction module (on by default in production, off in development).
Permission audit trail
Section titled “Permission audit trail”Permission and role changes are tracked in a separate, append-only audit trail with these change types:
permission_created,permission_updated,permission_deleted– Permission grant changesrole_created,role_updated,role_deleted– Role definition changesrole_assigned,role_revoked– Role assigned to or removed from a user
Soft deletion
Section titled “Soft deletion”Nothing is ever permanently deleted in oikapi. Deleted records, tables, and fields are deactivated rather than destroyed. The audit trail is always preserved.