Audit: one viewer-aware timeline
Audit stores Incld lifecycle events beside events written by your application. Query by component, actor, subject, or time; visibility rules determine which records an end user may read.
Event model
| Field | Meaning |
|---|---|
| component | schedules, approvals, bulk, or custom for manual application events. |
| type | Stable dotted event name such as approval.approved or customer.exported. |
| actorId | External user responsible for the event, or absent for system events. |
| subjectType / subjectId | Application resource addressed by the event. |
| source | system for built-in lifecycle events; manual for application-created events. |
| visibility | project, participants, or restricted. |
| data | Structured event-specific context. |
| tombstonedAt / tombstoneReason | Set when identity and payload fields were erased. |
| occurredAt / createdAt | Domain occurrence time and ingestion time. |
Create a manual event
await incld.auditEvents.create(
{
type: "customer.exported",
subjectType: "customer",
subjectId: "cus_42",
visibility: "participants",
participantIds: ["user_123", "user_456"],
data: { format: "csv", rows: 942 },
occurredAt: new Date().toISOString(),
},
{ idempotencyKey: "customer:cus_42:export:job_99" },
)
A user-scoped server client or framework proxy injects the trusted organization and actor identity. Use an organization-scoped client without a user only for system-authored tenant events.
Visibility rules
| Visibility | A viewer may see the event when |
|---|---|
| project | They have application permission to query project Audit through your proxy. |
| participants | Their ID is the actor or appears in participantIds. |
| restricted | Their ID is the actor or appears in allowedViewerIds. |
The proxy always selects the viewer
viewerId. The adapter overwrites it with context.user.id. Organization-scoped server clients may omit viewerId for authorized tenant-operator queries; only an intentional unscoped administrator client can query the whole project.
Query a cross-component timeline
const page = await incld.auditEvents.list({
components: ["schedules", "approvals", "bulk", "custom"],
subjectType: "customer",
subjectId: "cus_42",
since: "2026-08-01T00:00:00Z",
until: "2026-09-01T00:00:00Z",
limit: 100,
})
Append-only history and privacy tombstones
Normal history is append-only. Record a correction as a new event that references the original subject. For a data-subject request or accidentally captured sensitive data, a trusted server may tombstone the original event. This erases actor and subject identifiers, viewer lists, idempotency material, and payload data while preserving the organization, component, event type, timestamps, and source. incld also appends an
audit.event_tombstoned
record with the target event ID and a constrained reason.
await incld.auditEvents.tombstone(eventId, {
reason: "data_subject_erasure",
actorId: privacyOperator.id,
})
Tombstoning is server-only and organization-scoped
data_subject_erasure, sensitive_data, and customer_request. Tombstoning is idempotent, but prevention still matters: never place secrets, payment card data, or unnecessary personal data in an audit payload.