Skip to main content
Pylon keeps one append-only audit log per app. Auth events (sign-in, password reset, role changes) already go there. Your functions add their own events with ctx.audit.log, and entities declared audit: true get a record for every write. The log lives in the app database (_pylon_audit_events) on SQLite and Postgres. There is no API to change or delete an event.

Log an event

Call ctx.audit.log from a mutation or an action:
Pylon sets the actor (ctx.auth.userId) and tenant (ctx.auth.tenantId) from the caller’s session. A function cannot choose them. Inside a mutation, the event is written after the mutation commits and dropped if it rolls back, so a change that did not happen leaves no record. From an action, the event is written at once, and log rejects with AUDIT_WRITE_FAILED if it could not be stored.

Record every write to an entity

Every insert, update, and delete of a Script row, from the entity API, ctx.db in a mutation, or a nested mutation, adds an event: Field values are not recorded. For reads and exports, which do not go through a write, call ctx.audit.log yourself.

Read the log

From an action:
ctx.audit.list is available in actions only; mutations can log but not read. Filters: entity, entityId, actor, action, before (unix seconds), limit (default 100, max 1000). action: "lead.export" matches the stored app.lead.export; framework actions (entity.update, retention.delete) and auth action names such as sign_in match as given. Results are newest first. To page, pass beforeId set to the id of the last event you have. A caller with an active tenant reads that tenant’s events. A caller without a tenant reads only events it performed. Admin callers can pass tenant or read every tenant. Operators read across tenants over HTTP:
Query parameters: tenant, entity, id, actor, subject, action, before, beforeId, limit. Each event looks like: