Identity
See Correlation, identity, and causation for what identity means and why Chronicle tracks it. This page covers the TypeScript-specific API in depth. The Identity class is sent with every event append as the CausedBy field.
The Identity class
Section titled “The Identity class”import { Identity } from '@cratis/chronicle';
// Create a user identityconst identity = new Identity( 'a1b2c3d4-...', // subject — unique identifier (e.g. a user's ID or OAuth subject claim) 'Jane Doe', // name 'jane.doe' // userName (optional, defaults to ''));
// On-behalf-of chains are supportedconst delegatedIdentity = new Identity( 'service-id-...', 'My Service', 'my-service', identity // onBehalfOf);Well-known statics
Section titled “Well-known statics”| Static | Subject | Description |
|---|---|---|
Identity.system | 5d032c92-9d5e-41eb-947a-ee5314ed0032 | Default — used when no identity is set. |
Identity.notSet | 1efc9b81-0612-4466-962c-86acc4e9a028 | Sentinel for an explicitly unset identity. |
Identity.unknown | 3321cf62-db16-425e-8173-99fcfefe11dd | Sentinel for an unknown identity. |
Removing duplicate subjects
Section titled “Removing duplicate subjects”If a CausedBy chain contains the same subject more than once (can happen with intermediary services), call withoutDuplicates() to collapse duplicates while keeping the first occurrence:
const clean = delegatedIdentity.withoutDuplicates();Setting the identity for a call context
Section titled “Setting the identity for a call context”The module exports a singleton identityProvider backed by Node.js AsyncLocalStorage, so the identity is automatically scoped to the active async call — there is no need to thread it through function signatures.
import { identityProvider, Identity } from '@cratis/chronicle';
// Set once at the entry-point of a request / command handleridentityProvider.setCurrentIdentity(new Identity(userId, displayName, userName));
// Anywhere deeper in the same async context, the identity is available:const identity = identityProvider.getCurrent(); // returns the identity set above
// Reset to Identity.system when the context endsidentityProvider.clearCurrentIdentity();Express middleware example
Section titled “Express middleware example”import express from 'express';import { identityProvider, Identity } from '@cratis/chronicle';
app.use((req, res, next) => { const subject = req.auth?.sub ?? 'anonymous'; const name = req.auth?.name ?? '[Anonymous]'; identityProvider.setCurrentIdentity(new Identity(subject, name)); res.on('finish', () => identityProvider.clearCurrentIdentity()); next();});Implementing a custom provider
Section titled “Implementing a custom provider”If you need to derive the identity from a framework-specific source (e.g. an HTTP context, a gRPC call, a message-bus header), implement IIdentityProvider:
import { IIdentityProvider, Identity } from '@cratis/chronicle';
class MyIdentityProvider implements IIdentityProvider { getCurrent(): Identity { return ...; // pull from your context }
setCurrentIdentity(identity: Identity): void { /* ... */ } clearCurrentIdentity(): void { /* ... */ }}Then pass it wherever IIdentityProvider is expected, or replace usages of the identityProvider singleton with your instance.