Skip to content
// EFFECT DAYS 2026

EventLogServer unstable

Builds server-side handlers for the event-log remote protocol.

Transport modules use these handlers to expose an event journal to remote replicas. The handlers run the hello/authenticate challenge flow, attach the authenticated EventLog.Identity to later requests, accept single or chunked writes, and stream changes back as single or chunked messages.

5 exports Since v4.0.0 Source

Layers

Since v4.0.0

Provides RPC authentication middleware that reads the authenticated EventLog.Identity from client annotations.

Details

Requests without an identity fail with a forbidden EventLogProtocolError.

Signature

declare const layerAuthMiddleware: Layer.Layer<EventLogAuthentication>
Since v4.0.0

Creates the shared RPC handlers for the event-log remote protocol.

Details

The layer manages hello challenges, verifies session authentication, reassembles chunked writes, delegates write and change handling to the supplied callbacks, and frames large change payloads into chunks.

Authenticate calls authorizeIdentity with the claimed public key and the presented signing public key, then verifies the signature against the presented key. Only a verified key is passed to getOrCreateSessionAuthBinding, and a key that differs from the identity's existing binding is rejected.

Use the connection's ConnectionWrites.track in onWrite and ConnectionWrites.filter in changes to suppress its own write echoes. compaction sets HelloResponse.compaction, advertising that the server also serves EventLogCompactionRpcs.

Signature

declare function layerRpcHandlers(options: {
readonly authorizeIdentity?: (publicKey: string, signingPublicKey: Uint8Array<ArrayBuffer>) => Effect<void, EventLogProtocolError>;
readonly changes: (options: {
readonly publicKey: string;
readonly startSequence: number;
readonly storeId: StoreId;
readonly writes: ConnectionWrites;
}) => Stream<Uint8Array<ArrayBuffer>, unknown>;
readonly compaction?: boolean;
readonly firstSequence?: number;
readonly getOrCreateSessionAuthBinding: (publicKey: string, signingPublicKey: Uint8Array<ArrayBuffer>) => Effect<Uint8Array<ArrayBuffer>>;
readonly onWrite: (data: Uint8Array<ArrayBuffer>, authenticatedPublicKeys: ReadonlySet<string>, writes: ConnectionWrites) => Effect<readonly Array<{
readonly entryId: Uint8Array<ArrayBuffer> & Brand<"effect/eventlog/EventJournal/EntryId">;
readonly sequence: number;
}>, EventLogProtocolError>;
readonly remoteId: RemoteId;
}): Layer<EventLogAuthentication | Handler<"EventLog.Hello"> | Handler<"EventLog.Authenticate"> | Handler<"EventLog.WriteChunked"> | Handler<"EventLog.WriteSingle"> | Handler<"EventLog.Changes">>

Models

Since v4.0.6

Tracks writes to suppress their echoes on the same RPC connection.

Details

Only tracks entries for stores with an open change stream.

Signature

declare class ConnectionWrites {
constructor();
filter<A, E, R>(options: {
readonly entryIds: (item: A) => readonly Array<EntryId>;
readonly publicKey: string;
readonly sequence: (item: A) => number;
readonly storeId: StoreId;
}, stream: Stream<A, E, R>): Stream<A, E, R>;
track<E, R>(options: {
readonly entryIds: readonly Array<EntryId>;
readonly publicKey: string;
readonly storeId: StoreId;
}, write: Effect<readonly Array<{
readonly entryId: Uint8Array<ArrayBuffer> & Brand<"effect/eventlog/EventJournal/EntryId">;
readonly sequence: number;
}>, E, R>): Effect<readonly Array<{
readonly entryId: Uint8Array<ArrayBuffer> & Brand<"effect/eventlog/EventJournal/EntryId">;
readonly sequence: number;
}>, E, R>;
}

Services

Annotation containing the public keys authenticated on an RPC connection.

Signature

declare class AuthenticatedIdentities extends Shape<"effect/eventlog/EventLogServer/AuthenticatedIdentities", Set<string>, this> {
constructor(_: never);
}
Since v4.0.0

Annotation that stores partial ChunkedMessage data while chunked writes are being reassembled.

When to use

Use to keep per-client chunk assembly state while handling chunked event-log writes.

Signature

declare class ChunkedMessageState extends {} {
constructor(_: never);
}