Kaiten

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:

EventRecords
LICENSE_ENTITLEMENT_ASSIGNEDAn entitlement attached to a License, with its granted value and overage allowance
LICENSE_UPDATEDA License modified
INSTANCE_CREATEDAn Instance created, in the console or over the API — with the License it was given
RELEASE_DEPLOYEDA release landing in a deployment zone

Evaluations — reads and reports that produced a decision:

EventRecords
ENTITLEMENT_VALUE_GETAn entitlement value read — the answer your integration received
ENTITLEMENT_USAGE_REPORT_ACCEPTEDA usage report folded into the running total
ENTITLEMENT_USAGE_REPORT_REJECTEDA usage report refused above the grant's maximum allowed usage — nothing written
INSTANCE_ENTITLEMENT_USAGE_PERIOD_ROLLED_OVERA periodic counter closing a window — one entry per closed window, skipped windows included
FEATURE_FLAG_EVALUATEDA 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.

Sakura Tokyo Production's Event Log filtered on Instance created, with the entry's details: the instance's slug and the License it was created under, premium-v2Sakura Tokyo Production's Event Log filtered on Instance created, with the entry's details: the instance's slug and the License it was created under, premium-v2

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:

  1. The License the instance ran under. On the trail of sakura-tokyo-prod, the INSTANCE_CREATED entry carries its licenseSlug — premium-v2 — and no later INSTANCE_UPDATED entry changes it.
  2. What that License granted. On the organization's trail, the LICENSE_ENTITLEMENT_ASSIGNED entry for premium-v2: delivery-tracking, value true. It has no Instance — a grant is a change to the License, not to one instance.
  3. 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, serving on where the delivery-tracking entitlement 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.

On this page