Core Concepts
The Audit Trail
Every change and every evaluation, recorded in one trail — the memory of the system, and the answer to "who had access to what, when?"
Most tools keep an audit log of changes — who edited what. Kaiten's audit trail records changes and evaluations: "the License was modified", and also "this flag resolved to on, for this reason, at this moment." The second kind is what turns an audit log into the memory of the system, because in a licensing layer the reads are the business.
What gets recorded
Every domain event Kaiten emits also lands in the audit trail — the trail and your event subscriptions read from the same stream. Two families:
Changes — creates, updates, deletes, and commercial actions across the model:
| Event | Records |
|---|---|
LICENSE_ENTITLEMENT_ASSIGNED | An entitlement attached to a License, with its granted value and overage allowance |
LICENSE_UPDATED | A License modified |
INSTANCE_CREATED | An Instance created, in the console or over the API — with the License it was given |
RELEASE_DEPLOYED | A release landing in a deployment zone |
Evaluations — reads and reports that produced a decision:
| Event | Records |
|---|---|
ENTITLEMENT_VALUE_GET | An entitlement value read — the answer your integration received |
ENTITLEMENT_USAGE_REPORT_ACCEPTED | A usage report folded into the running total |
ENTITLEMENT_USAGE_REPORT_REJECTED | A usage report refused above the grant's maximum allowed usage — nothing written |
INSTANCE_ENTITLEMENT_USAGE_PERIOD_ROLLED_OVER | A periodic counter closing a window — one entry per closed window, skipped windows included |
FEATURE_FLAG_EVALUATED | A flag's resolution — the flag, the variant, the reason, the rule that matched. Recorded for the organization, and deliberately without the caller's evaluation context, so no PII enters the trail |
The shape of an entry
Every entry carries the same skeleton — what happened, when, with the event's data as payload, and the Instance it concerns when it concerns one:
{
"id": "0d6e2f5a-4b1c-4c6e-9a0f-2f8f4f1c9d3e",
"instanceId": "c3a4b5c6-d7e8-4f9a-0b1c-2d3e4f5a6b7c",
"instanceSlug": "sakura-tokyo-prod",
"eventName": "INSTANCE_CREATED",
"eventType": "com.kaiten.instance.v1.created",
"timestamp": "2026-08-14T11:02:11Z",
"payload": { /* the event's data — the same contract as the published event */ }
}eventName is the catalog name — the value the event_name filter matches. eventType is the versioned identifier the published event contracts use.
An entry is recorded at one of two levels. An Instance's own events carry the Instance: its creation and its updates — which is where the License it was given is on record — its status and lifecycle changes, and everything about its usage, the reads as well as the reports. Every other entry is recorded for the organization, without an Instance: a grant, a change to a License or to the catalog, a change to a flag or to its rules, and every flag evaluation.
Entries are append-only: the API exposes reads only — there is no operation to edit or delete an entry. That property makes the trail trustworthy in a dispute.
Querying the trail
The canonical question — "who had access to what, when?" — is answered with a filter. Each Instance exposes its own trail over the API, cursor-paginated, filtered by event name and time range:
curl "$KAITEN_API/instances/sakura-tokyo-prod/audit-trails?event_name=INSTANCE_CREATED" \
-H "Authorization: Bearer $KAITEN_TOKEN"The response is a page of entries plus hasMore and a nextCursor to walk further back; after and before bound it with RFC 3339 timestamps. Reading it requires the read:instances scope.
That endpoint returns an Instance's entries and no others. The entries recorded without an Instance are read on the organization's audit trail — the console's Audit trail page, at the bottom of the sidebar — which holds every entry of the organization, the instances' included. No REST operation lists it. Answer who had access walks both levels.
Evaluations are recorded for the organization
Kaiten follows the OpenFeature Remote Evaluation Protocol, in which an evaluation is addressed by a targeting key. Its entry, FEATURE_FLAG_EVALUATED, is recorded for the organization, without an Instance: it appears on the organization's trail and never in an Instance's — neither through GET /instances/{instanceSlug}/audit-trails nor on an instance's Audit Trail tab in the console. The entry names the flag and the decision, and neither the targeting key nor an Instance. It is written best effort: under sustained load one can be dropped, and an evaluation is never slowed down or failed by the recording. The evaluations Kaiten makes of its own flags, for its own organization, are not recorded.
Recording the Instance sent in the evaluation context on the audit entry is in progress Coming soon.
The Kaiten Sushi Shop walkthrough
Support asks why a Sakura Tokyo user could see delivery tracking. An evaluation entry does not answer alone: it names the flag and the decision, not the customer. The contract does, in three hops — on a seeded stack, every entry is dated relative to the moment the dataset was loaded:
- The License the instance ran under. On the trail of
sakura-tokyo-prod, theINSTANCE_CREATEDentry carries itslicenseSlug—premium-v2— and no laterINSTANCE_UPDATEDentry changes it. - What that License granted. On the organization's trail, the
LICENSE_ENTITLEMENT_ASSIGNEDentry forpremium-v2:delivery-tracking, valuetrue. It has no Instance — a grant is a change to the License, not to one instance. - What the flag's rule said. On the organization's trail, the entry that created
delivery-tracking-enabled, or the last one that changed it: one rule, servingonwhere thedelivery-trackingentitlement is granted.
Three dated entries, and the answer is complete. Where the flag was evaluated in the period, its FEATURE_FLAG_EVALUATED entries confirm it: the flag served on, reason TARGETING_MATCH, with the rule that matched.
The mirror question — why a Ninja Osaka user did not see it — is the same three hops from ninja-osaka-prod: a licenseSlug of starter, and a Starter grant of false.
The metering side is read on the Instance's own trail. Ninja Osaka's Menu Items sit at 5 of 5 under a Starter grant with a 0 % allowance: the report that filled the cap left an ENTITLEMENT_USAGE_REPORT_ACCEPTED entry and an INSTANCE_ENTITLEMENT_USAGE_REACHED entry; the next report that tries to go past it is refused and leaves an ENTITLEMENT_USAGE_REPORT_REJECTED entry, "status": "REJECTED" — the 409 your customer sees, kept as a receipt.
If Demo Restaurant reports no order for a whole month, its next Monthly Orders report makes the rollover write two INSTANCE_ENTITLEMENT_USAGE_PERIOD_ROLLED_OVER entries — the seeded month's stored bucket ("is_synthetic": false, 41 orders) and the empty month after it ("is_synthetic": true) — so a monthly counter's history has no gaps.
That is the whole chain of custody, with no grepping of application logs and no cross-referencing of the billing tool's history against the flag tool's: there is one trail.
What it's for
Debugging access. "Why does this customer see / not see feature X?" is answered by the three hops above.
Billing disputes. When a customer contests their usage, the ENTITLEMENT_USAGE_REPORT_ACCEPTED and REJECTED entries are the line-by-line receipt — timestamped, append-only, per instance, with every closed window in between.
Notifications. The bell in the console is a view over this trail, one per user: 29 of its events can notify, each user chooses which, and a notification carries the id of the entry it reports. Notifications covers the feed and its API.
Compliance. SOC 2, DSP2, and the AI Act converge on the same demand: demonstrate who had access to what, and when. Three disconnected tools cannot produce that answer; one trail across the whole model can. It is the case made in Why Kaiten, made concrete.
The audit trail is also the foundation layer for what's coming: the usage and activity insights on the roadmap read from this same record.
Where to go next
Exact reference — entry shape, table, and constraints: the data model.
Notifications
The per-user feed read from this trail: what notifies, read state, preferences.
Feature Flags
How flags evaluate, target with CEL, and read entitlements directly.
Gate a feature by License
Build the chain this page audits: entitlement, grant, flag, two evaluations — and read both decisions back in the organization's trail.
Metadata Fields
Typed, JSON-Schema-validated properties you declare on instances and deployment zones — rendered in the console, enforced on every write, readable by targeting rules.
Notifications
The in-app feed — each user's view over the organization's audit trail, with a read state and per-event preferences, in the console and over four API operations.