Audit log
The Audit log page (/admin/audit) lists security-relevant events from across the server — authentication, admin actions, license changes, group changes, encryption configuration. Events are stored in the audit_log table and written through the IAuditLogger service.
The page carries three tabs, each with its own route:
| Tab | Route | Rows |
|---|---|---|
| Events | /admin/audit |
The audit log itself |
| Anomalies | /admin/anomalies |
Detected login anomalies awaiting review |
| Guardrails | /admin/guardrail-decisions |
One row per guardrail-judged chat request |
Event format
Section titled “Event format”Every entry has:
- Event — dotted name like
Login.Failed,User.RoleChanged,Group.MemberAdded,License.Updated. - Actor — the email of the principal performing the action (admin or end user).
systemwhen the actor is the server itself. - Target — the affected user / group / object, where applicable.
- IP and User-Agent — captured from the request when relevant.
- Timestamp — in your browser’s time zone.
- Payload — small JSON blob with event-specific context.
Filtering
Section titled “Filtering”The Events tab provides two filters:
- Event type — substring match on the event name (e.g.
Login.for all login events). - Actor email — substring match on the email of the user who performed the action.
Press Apply to run them, Clear to drop them. Filters apply server-side and the list is cursor-paged — Load more appends the next page, and Refresh re-reads every page already open rather than collapsing back to the first.
Login anomalies
Section titled “Login anomalies”The Anomalies tab (/admin/anomalies) reads detected anomalies rather than raw events — the 200 most recent, newest first. It surfaces signals like:
- Repeated failed logins from the same IP in a short window.
- Successful logins from geographically improbable locations (impossible-travel).
- A successful login immediately following a burst of failures.
Each anomaly carries its detection metadata and an Acknowledge action that stamps who reviewed it and when; acknowledging twice is a no-op. The Unacknowledged only switch is on by default — turn it off to see the history.
Guardrail decisions
Section titled “Guardrail decisions”The Guardrails tab (/admin/guardrail-decisions) is the routing record for guarded chat requests: outcome, which model answered, which classifier judged it, and the per-guard verdicts behind the decision. It is documented with the feature, on Guardrails.
Retention
Section titled “Retention”Two six-hourly sweeps cover the audit log. Audit:RetentionDays (180 days) deletes entries past that age. Audit:IpRetentionDays (14 days) clears the IpAddress column on older entries and leaves the row itself standing, so the trail stays reconstructable after the address has gone.
Sign-in events and the login anomalies derived from them are a separate table pair with their own keys: LoginHistory:RetentionDays (90 days) deletes both, LoginHistory:IpRetentionDays (14 days) clears the address the same way. A new-location anomaly compares a sign-in with the country and device of earlier ones, so an account that signs in from a place less often than every 90 days is flagged again each time: the earlier sign-in from there is gone. The sweep is also the only thing that removes a failed sign-in against an unknown account — those rows carry no user id, so deleting the user never reaches them. Audit:RetentionDays covers neither table, and guardrail decisions and token usage rows have their own keys again — see Guardrails and Token usage.
Each of these periods is its default and its maximum at once. A shorter value is honoured; a longer one is capped at the maximum, and 0 or a negative value gets the default — neither turns a sweep off any more. Both are logged as a warning when the first sweep runs at startup. The full list is in the configuration reference.
Outbound notifications
Section titled “Outbound notifications”Pia Server does not send email notifications for admin alerts. If you want alerts off-server, scrape the audit log via SQL or build a watcher around the IAuditLogger interface — there’s no built-in webhook today.