Audit Log
Every meaningful change to your .solid file is recorded in an immutable audit log. This is what makes the file trustable to a CPA, an auditor, the IRS, or a lender — every number can be traced to who entered it, when, and what it replaced.
This page covers what the audit log captures, how to query it, and where it shows up in regulated workflows.
What's recorded
Solid logs every operation that changes data. For each event:
| Field | Notes |
|---|---|
| Timestamp | UTC, microsecond precision |
| User | Which user performed the action |
| Action | create, update, delete, view, post, void, import, export, login, logout, password_change, tin_view, etc. |
| Resource type | journal_entry, customer, account, attachment, tin, etc. |
| Resource ID | The UUID of the affected record |
| Before / after values | For updates: the changed fields, before and after |
| Source | ui, api, import, system, recurring, accountant_adjustment |
| Session ID | Ties events from the same login session together |
| IP address | For multi-user / API events; localhost for single-user |
| Client info | App version, platform, machine identifier |
That's a lot — and deliberately so. The log is the legal/regulatory backbone of the file's trustworthiness.
Categories of events
Data changes
Every create, update, delete on a transaction or list record:
- Posting a journal entry
- Editing a customer's address
- Voiding a check
- Importing 500 transactions from a CSV
- An API caller creating an invoice
Privileged operations
Operations that warrant extra scrutiny even if they don't change a number:
- Viewing an encrypted TIN
- Viewing the Cloud Backup recovery phrase
- Changing the file's master password
- Closing or re-opening a period
- Granting or revoking user roles
- Posting to a closed period (with override)
Authentication events
- Logins (success + failure)
- Logouts
- Failed password attempts
- API-key creations and revocations
- Multi-user session starts and ends
- Pairing a new device
System events
Operations Solid itself does on a schedule:
- Recurring-transaction generation
- Scheduled depreciation runs
- Cloud Backup runs (configure / disable / backup / restore / verify / GC)
- Auto-update of the application
Immutability
The audit log is append-only. Even Admins can't edit or delete entries. The log entries themselves are written to the same SQLCipher database as the rest of the file, but the table has no UPDATE or DELETE statements anywhere in the codebase — only INSERT.
What this means in practice:
- An attacker who got Admin credentials still can't rewrite history
- A user who edits a transaction generates a new audit entry showing the edit; the old one stays
- Even if you re-import a corrupted backup that "loses" recent entries, the entries up to the backup's date are still there
For Cloud Backup specifically, the audit log is in a separate SQLite file (backup_audit.db) so backup-related operations stay logged even if the main .solid file is restored from a snapshot. See Cloud Backup → Audit log.
Viewing the log
In Solid: Reports → Audit Log opens the log viewer. Filters:
- Date range — when the events happened
- User — only events from a specific user
- Action — only creates, only views, only password changes, etc.
- Resource type — only journal entries, only contacts, etc.
- Specific record — every event affecting one transaction or one customer
The viewer renders a chronological table. Click any row to see the full detail (before/after values for updates, the request body for API calls, etc.).
For point-in-time investigation, you can also drill from any record's Activity tab — every audit event scoped to that one record.
Retention
The audit log is retained for the life of the file. Solid never expires or rotates audit entries.
| File state | Audit log retention |
|---|---|
| File active and in use | All events kept |
| File closed (but kept) | All events kept |
| File deleted | Audit log goes with it (the file is the log) |
| File restored from backup | Events up to the backup snapshot |
| Cloud Backup audit log specifically | In a separate backup_audit.db file at app local data |
For regulatory compliance (SOC 2, sales-tax audits, IRS audits, lender covenants), the audit log is your evidence. Don't delete .solid files older than your retention policy demands, and back them up.
API access
The REST API exposes the audit log:
GET /audit-log?from=2026-01-01&to=2026-12-31&user_id=...&action=...
Common integration patterns:
- SIEM forwarding — daily pull of audit events into Splunk / Datadog / Elastic for correlation with other log sources
- Compliance reporting — periodic reports of "who accessed which TIN this quarter"
- Anomaly detection — flag unusual patterns (a user posting transactions outside business hours, an API key being used from a new IP)
The audit-log endpoint requires Admin role; the data is sensitive.
Regulatory uses
SOC 2
Auditors looking at your SOC 2 controls want to see that:
- Every privileged action is logged
- Logs are immutable
- Logs are retained
- Sensitive data access is specifically tracked
Solid's audit log addresses all four. The most-asked-for filtering during a SOC 2 review: TIN access, user-role changes, period close/re-open events, password changes.
IRS audit
In the rare case of an IRS audit, the auditor wants to confirm:
- Every transaction can be tied to source documentation
- The books haven't been altered to hide income or fabricate deductions
- The audit trail is complete
The combination of audit log + attachments (PDF receipts, vendor invoices) + the immutable journal-entry trail gives you a complete defense. Most IRS audits don't escalate beyond verifying a sample of transactions, and the audit log lets you produce the documentation quickly.
Lender covenants
Some lenders require attestation that financial records are tamper-proof. Solid's append-only audit log + cryptographic file integrity (SQLCipher) is the technical control behind that attestation; your CPA writes the management assertion.
Sales-tax audits
State tax authorities sometimes audit sales-tax remittance accuracy. The audit log shows:
- Which sales were tagged with which tax codes
- When tax codes were created or modified
- Who collected the tax (the user posting the transaction)
- When tax-rate changes happened
Combined with the Sales Tax Liability report, this is a complete defense for any sales-tax assessment.
Privacy considerations
Some events log potentially sensitive data:
- TIN view events record which user viewed which contact's TIN (but not the TIN itself in the log)
- Login events record IP addresses (which can be PII)
- Password change events don't store passwords (obviously) but do timestamp them
For multi-user files, all users with Admin role can see the full audit log — including events about other users. That's intentional (Admins need this for security investigations) but worth communicating to your team.
Common gotchas
Audit log is huge — 100K+ entries. Expected for an active file. Filtering is what makes it manageable; the full log isn't typically reviewed end-to-end.
Audit-log entries for a transaction don't match what I edited. Every edit produces a new audit entry. If you edited a transaction five times, there are five audit entries. The before/after values on each show the cumulative state at that point.
Audit log for a deleted record is "orphaned". The audit entries reference the deleted record's UUID but the record itself is gone (soft-delete). The orphan entries are still useful — they show the deletion happened and what the record looked like before — but you can't navigate from them to a "current" version.
Importing a backup re-creates audit-log entries from the backup date. Yes — restoring rolls back the audit log too. New events post-restore start from the restore point. The restore itself is logged.
An API caller's actions show as one user. Each API key has an associated user; events from that key log under that user. To distinguish multiple integrations, use a separate API key per integration.
Logs from before I started using Solid don't exist. Audit log starts when the file is created. Importing historical data from QuickBooks/Xero adds an import event to the log but doesn't synthesize per-transaction audit entries from before the import. The historical data has the original transaction date but the import date as its created-at timestamp.
Cross-references
- General Ledger → audit trail — the GL-side append-only model
- Cloud Backup → Audit log — separate audit DB for backup operations
- Multi-User → session management — the session-tracking surface that audit events reference
- REST API — programmatic audit-log access