> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orca-klavest.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Audit logs

> Append-only record of every security-relevant action in your workspace, scoped per organisation and queryable from the admin UI or API.

## Overview

ORCA writes an immutable audit log entry every time something security-relevant happens in your workspace — logins, file uploads, jobs, configuration changes, key rotations. Entries are append-only: there is no API or UI path that can delete or modify them after the fact.

This is the system of record auditors and compliance teams ask about. It's also the first place to look when something unexpected happens in your workspace and you need a clean answer to "who did what, when."

## What gets logged

Every entry stores the event code, the acting user (if any), the source IP, a timestamp, and a JSON metadata payload describing the action. The events ORCA always records:

| Category           | Events                                                                                                                          |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------- |
| **Authentication** | `login`, `logout`, `login_failed`, `register`, `email_verified`, `2fa_enabled`, `2fa_disabled`                                  |
| **Files & jobs**   | `file_uploaded`, `file_rejected_raw_password`, `job_created`, `job_started`, `job_completed`, `files_deleted`, `files_expiring` |
| **Compliance**     | `gdpr_check_disabled`, `credits_added`                                                                                          |
| **API access**     | `api_key_created`, `api_key_revoked`, `api_key_used`                                                                            |

The list is enforced in code — security-critical events cannot be silently dropped, and the [project security rules](https://github.com/Klavest/orca) explicitly forbid removing audit calls from any of the events above.

## Properties

* **Append-only.** No update or delete operation exists on the `audit_log` table. The schema enforces this at the database level.
* **Org-scoped.** Every entry is stamped with `org_id` and the API only returns entries belonging to the requesting user's organisation. Cross-tenant access is impossible by design.
* **Admin-only.** Reading audit logs requires the `admin` role.
* **Best-effort write.** The audit logger is designed to never raise — a failure to write a single audit entry never breaks the action being audited. Write failures are logged but not propagated.

## Viewing audit logs

In the web app, open **Settings → Audit logs** (admin only). The viewer supports:

* **Pagination** — 50 entries per page by default, configurable up to 200
* **Event filter** — narrow to a single event code, e.g. `login_failed`
* **User column** — joined from the user table, so you see emails not UUIDs

Newest entries appear first.

## API

```bash theme={null}
# List audit logs (admin token required)
GET /api/v1/audit?limit=50&offset=0

# Filter by a specific event
GET /api/v1/audit?event=login_failed&limit=200

# Paginate
GET /api/v1/audit?limit=100&offset=100
```

Response shape:

```json theme={null}
{
  "data": {
    "logs": [
      {
        "id": "8fa1...",
        "event": "file_uploaded",
        "user_email": "alice@acme.com",
        "ip_address": "203.0.113.42",
        "created_at": "2026-04-07T09:14:22Z",
        "metadata": {
          "file_id": "...",
          "filename": "transactions_q1.csv",
          "size_bytes": 1485220
        }
      }
    ],
    "total": 18432
  }
}
```

`limit` is capped at 200 entries per request. Use `offset` to paginate through larger result sets.

## Common queries

| You want to know                                  | Filter                                         |
| ------------------------------------------------- | ---------------------------------------------- |
| Failed logins in the last day                     | `event=login_failed` then sort by `created_at` |
| Who disabled GDPR scanning on a job               | `event=gdpr_check_disabled`                    |
| Whether a specific file ever existed              | `event=file_uploaded` and search the metadata  |
| Who created the API key with prefix `ok_live_abc` | `event=api_key_created`                        |
| When raw password files were rejected             | `event=file_rejected_raw_password`             |

## Retention

Audit logs are retained for the lifetime of the organisation by default. They are not deleted by the [data retention worker](/data-retention) — that worker only handles uploaded customer files, not security records.

If your compliance posture requires log archival to a customer-controlled bucket (e.g. for SIEM ingestion), contact support — we can configure scheduled exports to S3 or webhook delivery.

## Tips

* **Pull audit logs into your SIEM.** The endpoint is paginated and stable; a small cron that polls `?event=login_failed` and forwards to Splunk/Datadog gives you alerting without any custom integration.
* **Audit before debugging.** Before investigating a "weird state" complaint, pull `event=*` for the affected user's email and look for a manual config change you forgot about.
* **Pair with [API keys](/api-keys).** Every API key use creates an `api_key_used` event with the key prefix in metadata, so you can reconstruct exactly what an integration did.

## What's next?

* [API keys](/api-keys) — manage and rotate the keys whose usage shows up here
* [Security overview](/security) — the broader compliance picture
* [Data retention](/data-retention) — control how long uploaded files are kept (separate from audit retention)
