Audit log

What is recorded, how admins search and export it, and why it can't be changed.

Every security-relevant action is written to a tamper-resistant audit log that tenant admins can search and export. It answers questions like "who downloaded the contract we sent on Monday, and from which IP address?" (UC-4).

What is recorded

Each record holds the actor, the tenant, the target, the time, the source IP address and the user agent (FR-27). The log covers:

AreaActions
Sign-inEvery sign-in, failed attempts included
Transfers and requestsCreation, each upload, emails sent, expiry and expiry extensions, revocation, deletion
FilesScan results and DLP inspection results
External peopleEach verification attempt, success or failure, and each download
Data loss preventionDecisions, with the policy version and matched rules; confirmations; approval requests and decisions; views of finding details; every DLP policy change
AdministrationMember and policy changes
API keysCreation, every call the key makes (reads included), and revocation
The log itselfEvery audit search and export
OperatorsBreak-glass access to the tenant's data

Records hold IDs, detectors, counts and enumerated values. They never hold matched sensitive values, approval justifications or rejection comments (FR-54), so the log can be searched and exported without becoming a second copy of confidential data.

Search and export

A tenant admin searches the log in the web app (FR-28) by actor, email address, target, action, source IP address and time range, newest first. Filters travel in the request body, not the URL, so email and IP addresses never appear in URLs or access logs.

Results export as CSV or JSON, from the web app and the API (FR-29). CSV exports neutralise spreadsheet formulas: fields such as a user agent hold text an outsider chose, so any cell starting with =, +, -, @, a tab or a carriage return is prefixed with a quote and shown as text.

WhoLimits
Tenant admin, web appA sign-in within the last 15 minutes; at most 1,000,000 events per export
API key with the audit:read scopeAt most one export an hour per key, at most 100,000 events per export
Per tenantAt most 10 exports an hour, one at a time; 60 searches a minute

The tenant's admins are emailed the first time each API key exports. So a leaked key can pull at most 100,000 events an hour, and its first pull is noticed at once. When an export is too large, narrow the time range.

DLP reports (decisions by outcome, rule and detector; approvals; files not fully inspected) are exported with the audit log (FR-55).

Integrity

The audit design starts from a simple rule: an action that matters can't happen without its record (NFR-15).

  • Same transaction. The service writes each audit record in the same database transaction as the change it describes. The application's database role can insert audit rows but can't update or delete them.
  • Within 60 seconds. Every action is recorded within 60 seconds of happening. Failed sign-ins to the service's user pool reach the log through its sign-in triggers, which deny the sign-in if they can't report it.
  • Downloads fail closed. A download is served only once its audit record has been written. If the record can't be written, the recipient gets an error and nothing is counted.
  • Write-once archive. A job copies new records at least every minute to an S3 bucket under Object Lock, which replicates to the disaster-recovery region. In production the lock is in compliance mode: no one, operators included, can change or delete an archived record before its retention ends, and no restore or failover removes one.
  • Security-critical records in both regions first. Revocations of transfers, upload requests and API keys; deactivations, demotions and forced sign-outs; lockouts and unlocks; sign-in resets; and download grants are written straight to the archive in both Tokyo and Osaka. The API confirms the change only once both regions have it.
  • Cross-checking. A daily job matches storage access logs against audit records, so a storage read with no matching record stands out.

One limit is stated plainly in the PRD: ordinary records written in the last seconds of database replication can be lost if the whole Tokyo region fails before they reach the archive. Security-critical records can't, because they are in both regions before the API answers.

Retention

Audit records are kept for 365 days and then deleted (NFR-9). In the database, the table is partitioned by month and a daily job removes rows older than a year. Archived objects carry a 365-day Object Lock retention, and each archive bucket's lifecycle rule deletes them a day after it ends.

The production audit archive outlives the rest of the environment. When production is torn down, the archive, the key that encrypts it and the few resources that guard it are kept until the retention ends (NFR-19).

Transfer and upload request metadata is kept as long as an audit record refers to it, so a year-old record still names the transfer it is about. See Revocation and retention for the full data lifecycle.

Source: PRD, Architecture, API contract, Authentication and authorization, Delivery plan