Appearance
Audit Events
Lumi emits security audit events as structured JSON to stdout. In BYOC deployments, the customer is responsible for log shipping, SIEM ingestion, retention, tamper protection, and access control for stored logs. Lumi is responsible for event emission and the stable schema documented here.
Transport
lumi-apiemits audit events through theno.lumi.auditlogger.lumi-dashboardemits audit events through a dedicated server-side pino logger.- General log-level knobs must not silence audit events.
- Audit examples below are synthetic and do not contain production identifiers.
Schema
Current schema version: lumi.audit.v1.
Required fields:
| Field | Description |
|---|---|
audit_schema | Schema version, currently lumi.audit.v1 |
audit_event | Stable event id from the catalog below |
audit_category | auth, admin, api_key, export, or delete |
audit_operation | Operation verb such as create, delete, or authorize |
audit_outcome | success, denied, not_found, conflict, or failure |
actor_type | oidc_user, api_key, anonymous, or system |
resource_type | Resource category for the event |
Optional fields include actor_user_ref, actor_key_id, actor_is_org_admin, org_id, org_slug, team_id, team_slug, resource_id, resource_id_pseudonymized, resource_count, route_template, and request_method.
Role-gated team operations can also emit actor_role, effective_role, required_role, role_source, and authorization_policy. actor_role is the role from the selected team mapping before org-admin coercion, while effective_role is the role used for the authorization decision. authorization_policy is one of explicit_team_required, ambiguous_multi_team_read, team_editor_required, team_admin_required, secret_key_required, secret_key_minting_blocked, or secret_key_rotation_blocked.
actor_user_ref and pseudonymized resource ids use the same deterministic pseudonym in API and dashboard logs: id: plus the first 12 lowercase hexadecimal characters of SHA-256 over the UTF-8 identifier.
Privacy Rules
Audit events must not contain bearer tokens, API key values, API key hashes, session ids, encrypted cookie values, emails, display names, raw OIDC subjects, raw OIDC group ids, raw feedback text, raw answer values, raw export filter values, or raw customer-controlled surveyId values.
When an identifier is customer-controlled, the event uses a pseudonymized resource_id and sets resource_id_pseudonymized=true.
Event Catalog
| Event | Category | Meaning |
|---|---|---|
auth.oidc.success | auth | Dashboard OIDC callback created a server-side session |
auth.oidc.denied | auth | API rejected an invalid bearer token |
auth.oidc.failure | auth | API OIDC validation failed unexpectedly |
auth.org_admin.denied | auth | Org-admin authorization rejected a caller |
auth.team.denied | auth | Team authorization rejected a caller |
auth.team.explicit_team_missing | auth | An explicit-only route lacked ?team=, or a multi-team read was ambiguous |
admin.org.update | admin | Organization metadata changed |
admin.team.create | admin | Team created |
admin.group_mapping.create | admin | OIDC group mapping created |
admin.group_mapping.delete | admin | OIDC group mapping deleted |
admin.survey_definition.delete | admin | Survey definition deleted |
api_key.create | api_key | API key created |
api_key.rotate | api_key | API key rotated |
api_key.revoke | api_key | API key revoked |
export.feedback | export | Feedback export generated |
feedback.delete | delete | Single feedback item deleted |
survey_feedback.delete | delete | Feedback and markers for a survey deleted |
marker.delete | delete | Rating marker deleted |
tag.delete | delete | Feedback tag deleted |
Team-selection policy migration
auth.team.explicit_team_missing now represents two denied decisions. Use the stable, non-PII authorization_policy field to distinguish them:
authorization_policy | Meaning |
|---|---|
explicit_team_required | Export, mutation, or API-key operation requires an explicit team even for a one-team caller |
ambiguous_multi_team_read | A normal read lacked a usable team while the caller had more than one authorized team |
SIEM alerts and dashboards that previously grouped only by event id must also group by authorization_policy. Expect denied-event volume to increase when multi-team users or custom clients omit the query parameter. Neither policy contains a team slug, UUID, raw path, email, display name, or submission data.
API Key Event Read Surface
Dashboard clients can read the API key lifecycle trail for an authorized team:
http
GET /api/v1/dashboard/api-keys/events?team={teamSlug}&keyId={uuid?}&limit={1..100?}The response is additive and reserves cursor pagination for a later release:
json
{
"events": [
{
"id": "00000000-0000-0000-0000-000000000001",
"keyId": "00000000-0000-0000-0000-000000000002",
"keyPrefix": "lumi_pk_live",
"keyType": "pk",
"eventType": "created",
"actor": {
"type": "oidc_user",
"userRef": "id:fcdec6df4d44",
"keyId": null
},
"createdAt": "2026-06-13T12:00:00Z"
}
],
"nextBefore": null
}Org admins can read events for all keys in the authorized team. Non-admin users can read only pk key events. If a non-admin requests an invisible sk key by id, the response returns an empty event list rather than confirming whether the key exists.
