CodamAIDocs
Topicdone

Read the audit

Who may read the audit and in which form the entries are available.

Variants
platform administratoreveryone else → refusedpage too large → refused

What this is about

The audit contains what everyone did across the whole platform, in every tenant. Whoever could read part of it could already tell from the entries which customers exist. That is why reading is strictly controlled.

How it is read

The audit has exactly one read function: the interface AuditQueryUseCase with the method page(page, size). Code running in the same program as CIAS calls it, for example an admin screen of the host. There is no write access. Entries come only from the listener, see One trail for everything. An audit that someone can write to from outside would be a place for an alibi.

May this caller read the audit?
  1. CIAS
    logged in
    Is there a logged-in caller?
    ↳ no refused: cias.audit.access-denied
  2. CIAS
    Platform administrator
    Does their token carry a role that counts as platform administrator?
    ↳ no refused: cias.audit.access-denied
  3. CIAS
    Page
    Is page at least 0 and size between 1 and 500?
    ↳ no refused, before anything is read
  4. One page of entries, newest first

A page

Request
auditQuery.page(0, 3)
Response
AuditPage[
  total = 1284, page = 0, size = 3,
  entries = [
    { type: "AuthorizationEvent.Granted",
      detail: "Granted[assignmentId=a41f…, userId=5c9e…, roleClient=cias-backend, roleKey=tenant-user, tenantKey=nordbau, validUntil=null, grantedBy=nordbau, occurredOn=2026-09-22T09:20:11Z]",
      actorId: "e7d0…", actorTenant: "nordbau",
      occurredOn: 2026-09-22T09:20:11Z, recordedOn: 2026-09-22T09:20:11.042Z },
    { type: "TenantEvent.Suspended",
      detail: "Suspended[tenantId=4f2a…, tenantKey=suedlogistik, occurredOn=2026-09-22T09:14:03Z]",
      actorId: "b21c…", actorTenant: null, … },
    { type: "AuthorizationEvent.Expired",
      detail: "Expired[assignmentId=77c3…, …]",
      actorId: null, actorTenant: null, … }
  ]
]
PartMeaning
entriesthe entries of this page, newest first. At the same point in time the ID decides, so no row appears twice or goes missing while paging
totalhow many entries there are in total
page, sizewhich page was read and how many rows a full page holds. Default 50, at most 500
actorId emptythe platform acted on its own or nobody was logged in, in the example a timer

The field detail is text, not structured. It is the description of the event the way Java prints a record as text: name, then all fields with values in square brackets.

The variants

Who reads

When: The token carries a role that counts as platform administrator.

Reads all entries of all tenants.

Result: one page of entries

When: Tenant administrator, ordinary person or no token.

They do not see their own tenant either. A filter by tenant would have to leave out entries without a tenant, such as those of a timer, and an audit that silently leaves out what it cannot classify is the worst audit.

Result: refused: cias.audit.access-denied

When: size above 500, below 1, or page negative.

CIAS refuses instead of silently returning fewer rows. Otherwise the caller would believe they had seen everything.

Result: refused, nothing read

Pitfalls

Next

Sources in the code and the knowledge base
  • CIAS/cias-audit – AuditQueryUseCase.page, AuditService (requireAdministrator), AuditPage (DEFAULT_SIZE 50, MAX_SIZE 500, requireReadable), AuditEntryView, AuditAccessDeniedException (cias.audit.access-denied)
  • CIAS/cias-audit – JpaAuditTrailAdapter.findPage (newest first, then by id), count
  • CIAS/cias-audit/docs/adr – ADR-033
Search