Skip to main content

@eigeninteractive/server

@eigeninteractive/server: everything that deploys, being the createEngine API factory, the GameDO base class, the D1 applier, and the protocol types.

The D1 and Durable Object table definitions are deliberately NOT exported. They are engine-owned storage internals that migrate on their own schedule, and readGameRow already returns the whole game row typed. Exporting the drizzle tables would turn a private layout into a compatibility surface.

Classes

AuthError

Defined in: server/packages/server/src/auth/firebase.ts:12

Verification failure, always the caller's fault; the app maps it to 401.

Extends

  • Error

Constructors

Constructor
new AuthError(message?): AuthError;

Defined in: web/node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1080

Parameters
ParameterType
message?string
Returns

AuthError

Inherited from
Error.constructor
Constructor
new AuthError(message?, options?): AuthError;

Defined in: web/node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1080

Parameters
ParameterType
message?string
options?ErrorOptions
Returns

AuthError

Inherited from
Error.constructor

abstract BaseGameDO

Defined in: server/packages/server/src/do/game-do.ts:117

Durable Object base class that owns one authoritative game session.

A game Worker subclasses this once to supply its gameModule and D1 binding. Do not override command, socket, alarm, or persistence behavior: the base class owns the serialized game loop and applies engine migrations on activation.

Example

export class GameDO extends BaseGameDO<Env> {
protected readonly gameModule = gameModule;
protected d1(env: Env) {
return env.GAME_DB;
}
}

Extends

  • DurableObject<TEnv>

Type Parameters

Type Parameter
TEnv

Implements

  • GameStub

Constructors

Constructor
new BaseGameDO<TEnv>(ctx, env): BaseGameDO<TEnv>;

Defined in: server/packages/server/src/do/game-do.ts:131

Parameters
ParameterType
ctxDurableObjectState
envTEnv
Returns

BaseGameDO<TEnv>

Overrides
DurableObject<TEnv>.constructor

Properties

gameModule
abstract protected readonly gameModule: GameModule;

Defined in: server/packages/server/src/do/game-do.ts:119

The implementor's game: the versions map the engine dispatches on.

Methods

abort()
abort(gameId): Promise<void>;

Defined in: server/packages/server/src/do/game-do.ts:394

Unconditional teardown (cron reap): mark the game aborted in D1 and compact its game data, with no creator gate or init requirement. A never-touched lobby's DO has no meta row, so the caller passes the gameId. Idempotent; cancel shares the teardown for its live path.

Parameters
ParameterType
gameIdstring
Returns

Promise<void>

Implementation of
GameStub.abort
alarm()
alarm(): Promise<void>;

Defined in: server/packages/server/src/do/game-do.ts:951

A timeout is derived from committed state, not submitted, so it carries no caller identity. It is idempotent because the kernel abstains once the state it was derived from has moved on, so a double fire, a retry after an alarm handler throws, and a race with a latent on-time action all resolve the same way. handle() re-arms the alarm for the next turn on its way out.

Returns

Promise<void>

Overrides
DurableObject.alarm
d1()
abstract protected d1(env): D1Database;

Defined in: server/packages/server/src/do/game-do.ts:122

The EngineConfig seam: the engine never assumes binding names, so the subclass picks the D1 database off its own Env.

Parameters
ParameterType
envTEnv
Returns

D1Database

fetch()
fetch(request): Promise<Response>;

Defined in: server/packages/server/src/do/game-do.ts:965

The worker routes the upgrade here after authenticating; the principal header is worker-set (never client-supplied; the worker strips inbound headers when forwarding). One socket serves the game's whole lifetime and carries one message kind, the per-seat SessionSnapshot. A not-yet-seated user's socket receives the envelope with no frame until the roster contains them, which is how it learns the game started at all.

Parameters
ParameterType
requestRequest
Returns

Promise<Response>

Implementation of
GameStub.fetch
Overrides
DurableObject.fetch
firebaseAdmin()
protected firebaseAdmin(env): FirebaseAdminEffects;

Defined in: server/packages/server/src/do/game-do.ts:125

Required Firebase Admin effects. Tests override this with the explicit fake exported by @eigeninteractive/server/testing.

Parameters
ParameterType
envTEnv
Returns

FirebaseAdminEffects

frames()
frames(args): Promise<FrameMessage[]>;

Defined in: server/packages/server/src/do/game-do.ts:1148

Project a version range for one seat (null = public viewer, replay only). Live rows serve the stored frame; compacted/ratings rows re-project. Raw state never leaves the DO.

Parameters
ParameterType
args{ from: number; isReplay?: boolean; seat: number | null; to: number; }
args.fromnumber
args.isReplay?boolean
args.seatnumber | null
args.tonumber
Returns

Promise<FrameMessage[]>

Implementation of
GameStub.frames
handle()
handle(cmd): Promise<CommandResult>;

Defined in: server/packages/server/src/do/game-do.ts:144

Parameters
ParameterType
cmdSingleCommand
Returns

Promise<CommandResult>

Implementation of
GameStub.handle
localRecord()
localRecord(
gameId,
from,
to
): Promise<LocalRecord | null>;

Defined in: server/packages/server/src/do/game-do.ts:271

A local game's stored log: raw state and the action that produced it, plus the seed they were all derived from.

This is the one place raw state leaves the object, and it is safe for the same reason it is useful: a local game has exactly one human, the caller, who played every one of these transitions on their own device and still holds them there. There is no other participant for the disclosure to be against. The origin gate is restated here rather than trusted from the route, because "raw state never leaves the DO" is worth guarding at the object that owns it.

Parameters
ParameterType
gameIdstring
fromnumber
tonumber
Returns

Promise<LocalRecord | null>

Implementation of
GameStub.localRecord
localTransitions()
localTransitions(cmd): Promise<LocalBatchResult>;

Defined in: server/packages/server/src/do/game-do.ts:190

Import a run of a local game's transitions, in order, under one gate entry.

The device already played these against the Dart twin of these rules; this replays them through the authoritative ones, so the server's copy is produced by the TypeScript rules and a disagreement surfaces as a rejection rather than being taken on trust. Each transition commits through exactly the live action/forfeit path — same guards, same frames, same log — so an imported game is indistinguishable from a played one afterwards.

Three things differ, and only three: the whole run is one request, the per-commit D1 summary mirror is collapsed into one write at the end (a hundred-move game would otherwise cost a hundred round trips for a row nothing reads until it settles), and the first rejection stops the batch and is REPORTED rather than thrown, because everything before it is already committed and permanent.

Parameters
ParameterTypeDescription
cmd{ actor: Principal; fromVersion: number; gameId: string; kind: "local-transitions"; transitions: LocalTransition[]; }-
cmd.actorPrincipalThe game's creator: the only principal a local game has.
cmd.fromVersionnumberThe version the device believes the server is at. The import is append-only, so a mismatch means another device already appended and this batch is refused whole (stateUpdated).
cmd.gameIdstring-
cmd.kind"local-transitions"Import a run of a local game's transitions into the authoritative object, in order, as one request. A batch rather than one command per transition because a finished local game is a whole transcript: sending it move by move would cost a Worker and a Durable Object request each, and would let a client stop halfway through with the server's copy in a state the device never saw.
cmd.transitionsLocalTransition[]-
Returns

Promise<LocalBatchResult>

Implementation of
GameStub.localTransitions
reconcile()
reconcile(gameId): Promise<ReconcileReport>;

Defined in: server/packages/server/src/do/game-do.ts:915

Re-derive D1's read model from this object's committed state, and finish any post-commit work that never landed.

The repair counterpart to the fire-and-forget mirror. #mirrorD1 writes the roster/summary rows off the response path and gives up after its retries, because a commit whose truth is already durable must not fail on a read model — which leaves D1 stale with nothing to notice. Likewise a finish whose D1 apply failed keeps its outbox row precisely so this can retry it. Both are the same defect from D1's side (a game that stopped being updated), and both are fixed by the same act: write what the DO knows.

Deliberately does NOT lazy-init. Lazy init reads the games row from D1, so an object with no meta has nothing more authoritative than the row it would be repairing — reconciling it would read the stale copy and write it straight back, reporting success. No meta row means this object never committed anything, and the answer is honestly "nothing to reconcile".

The writes here are awaited, unlike the post-commit mirror: a repair that failed silently is worse than no repair, because the operator or sweep that asked for it would believe the divergence was resolved.

Idempotent, so a sweep may call it on a healthy game: the mirror is rewritten to the same values, repokeFinish reports nothing to do, and the alarm already matches.

Parameters
ParameterType
gameIdstring
Returns

Promise<ReconcileReport>

Implementation of
GameStub.reconcile
session()
session(gameId, userId): Promise<SessionSnapshot | null>;

Defined in: server/packages/server/src/do/game-do.ts:988

The snapshot over RPC, for the HTTP paths that have no socket.

Parameters
ParameterType
gameIdstring
userIdstring | null
Returns

Promise<SessionSnapshot | null>

Implementation of
GameStub.session
webSocketClose()
webSocketClose(): Promise<void>;

Defined in: server/packages/server/src/do/game-do.ts:1001

Returns

Promise<void>

Overrides
DurableObject.webSocketClose
webSocketError()
webSocketError(_ws, error): Promise<void>;

Defined in: server/packages/server/src/do/game-do.ts:1007

Parameters
ParameterType
_wsWebSocket
errorunknown
Returns

Promise<void>

Overrides
DurableObject.webSocketError
webSocketMessage()
webSocketMessage(ws): Promise<void>;

Defined in: server/packages/server/src/do/game-do.ts:993

Parameters
ParameterType
wsWebSocket
Returns

Promise<void>

Overrides
DurableObject.webSocketMessage

CommercialLimitWriteError

Defined in: server/packages/server/src/d1/apply.ts:402

Extends

  • Error

Constructors

Constructor
new CommercialLimitWriteError(message?): CommercialLimitWriteError;

Defined in: web/node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1080

Parameters
ParameterType
message?string
Returns

CommercialLimitWriteError

Inherited from
Error.constructor
Constructor
new CommercialLimitWriteError(message?, options?): CommercialLimitWriteError;

Defined in: web/node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1080

Parameters
ParameterType
message?string
options?ErrorOptions
Returns

CommercialLimitWriteError

Inherited from
Error.constructor

HttpError

Defined in: server/packages/server/src/http.ts:56

Extends

  • Error

Constructors

Constructor
new HttpError(
status,
message,
code?,
retryAfterSeconds?
): HttpError;

Defined in: server/packages/server/src/http.ts:64

Parameters
ParameterType
status400 | 401 | 403 | 404 | 409 | 413 | 415 | 422 | 429 | 500 | 502
messagestring
code?ErrorCode
retryAfterSeconds?number
Returns

HttpError

Overrides
Error.constructor

Properties

code
readonly code: ErrorCode | undefined;

Defined in: server/packages/server/src/http.ts:58

retryAfterSeconds
readonly retryAfterSeconds: number | undefined;

Defined in: server/packages/server/src/http.ts:62

Seconds the caller should wait before retrying, rendered as the Retry-After header. Set only on a 429 (see ErrorCode.rateLimited); undefined everywhere else.

status
readonly status: 400 | 401 | 403 | 404 | 409 | 413 | 415 | 422 | 429 | 500 | 502;

Defined in: server/packages/server/src/http.ts:57

Interfaces

AccessGrant

Defined in: server/packages/server/src/commerce/types.ts:34

Permissions, content ownership, and limits contributed by one source.

Extended by

Properties

content?
optional content?: readonly ContentGrant[];

Defined in: server/packages/server/src/commerce/types.ts:36

limits?
optional limits?: readonly CommercialLimit[];

Defined in: server/packages/server/src/commerce/types.ts:37

permissions?
optional permissions?: readonly EngineAccessCapability[];

Defined in: server/packages/server/src/commerce/types.ts:35


AccessSnapshot

Defined in: server/packages/server/src/commerce/types.ts:203

Properties

content
content: ContentGrant[];

Defined in: server/packages/server/src/commerce/types.ts:206

entitlements
entitlements: ActiveEntitlement[];

Defined in: server/packages/server/src/commerce/types.ts:204

limits
limits: LimitAccess[];

Defined in: server/packages/server/src/commerce/types.ts:207

permissions
permissions: EngineAccessCapability[];

Defined in: server/packages/server/src/commerce/types.ts:205


AuthClaims

Defined in: server/packages/server/src/auth/firebase.ts:18

What a verified ID token asserts. isAnonymous (the firebase.sign_in_provider === 'anonymous' claim) drives every guest gate; the profile claims seed user provisioning (Google supplies name/picture, Apple usually only email, guests none).

Properties

email
email: string | null;

Defined in: server/packages/server/src/auth/firebase.ts:21

isAnonymous
isAnonymous: boolean;

Defined in: server/packages/server/src/auth/firebase.ts:20

name
name: string | null;

Defined in: server/packages/server/src/auth/firebase.ts:22

picture
picture: string | null;

Defined in: server/packages/server/src/auth/firebase.ts:23

uid
uid: string;

Defined in: server/packages/server/src/auth/firebase.ts:19


CommerceCatalog

Defined in: server/packages/server/src/commerce/types.ts:62

Properties

botTiers?
optional botTiers?: Readonly<Record<string, string>>;

Defined in: server/packages/server/src/commerce/types.ts:69

The bots priced differently from the rest, by registered bot id. Every bot this does not list is in standard (DEFAULT_BOT_TIER).

content?
optional content?: Readonly<Record<string, Readonly<Record<string, ContentDefinition>>>>;

Defined in: server/packages/server/src/commerce/types.ts:66

entitlements
entitlements: readonly EntitlementDefinition[];

Defined in: server/packages/server/src/commerce/types.ts:64

free
free: AccessGrant;

Defined in: server/packages/server/src/commerce/types.ts:63

offers
offers: readonly CommerceOffer[];

Defined in: server/packages/server/src/commerce/types.ts:65


CommerceCheckout

Defined in: server/packages/server/src/commerce/types.ts:102

Properties

expiresAt?
optional expiresAt?: number;

Defined in: server/packages/server/src/commerce/types.ts:105

Provider session expiry in epoch milliseconds, when known.

providerAccountId?
optional providerAccountId?: string;

Defined in: server/packages/server/src/commerce/types.ts:107

Returned when checkout created or resolved a provider customer.

url
url: string;

Defined in: server/packages/server/src/commerce/types.ts:103


CommerceConfig

Defined in: server/packages/server/src/commerce/types.ts:162

Type Parameters

Type Parameter
TEnv

Properties

catalog
catalog: CommerceCatalog;

Defined in: server/packages/server/src/commerce/types.ts:163

now?
optional now?: () => number;

Defined in: server/packages/server/src/commerce/types.ts:166

Test seam. Production uses Date.now.

Returns

number

providers
providers: readonly CommerceProvider<TEnv>[];

Defined in: server/packages/server/src/commerce/types.ts:164

reconcileBatch?
optional reconcileBatch?: number;

Defined in: server/packages/server/src/commerce/types.ts:168

Maximum nonterminal transactions checked per provider and invocation.

reconcileMaxFailures?
optional reconcileMaxFailures?: number;

Defined in: server/packages/server/src/commerce/types.ts:171

Consecutive failed sweeps after which a transaction stops being swept and is surfaced to the operator instead. Defaults to 10.


CommerceManagement

Defined in: server/packages/server/src/commerce/types.ts:110

Properties

url
url: string;

Defined in: server/packages/server/src/commerce/types.ts:111


CommerceOffer

Defined in: server/packages/server/src/commerce/types.ts:45

Properties

description
description: string;

Defined in: server/packages/server/src/commerce/types.ts:49

entitlements
entitlements: readonly string[];

Defined in: server/packages/server/src/commerce/types.ts:51

key
key: string;

Defined in: server/packages/server/src/commerce/types.ts:47

Stable logical key used by clients and analytics.

kind
kind: "oneTime" | "subscription";

Defined in: server/packages/server/src/commerce/types.ts:50

name
name: string;

Defined in: server/packages/server/src/commerce/types.ts:48

providerReferences
providerReferences: Readonly<Record<string, string>>;

Defined in: server/packages/server/src/commerce/types.ts:59

Public, provider-owned sellable references. The engine treats each value as opaque; the matching adapter may interpret a Stripe Price, or a Google Play product/base-plan/offer tuple. Secret credentials remain in bindings.

repeatable?
optional repeatable?: boolean;

Defined in: server/packages/server/src/commerce/types.ts:53

Defaults to false. Enable only for intentionally repeatable support/tip offers.


CommerceProduct

Defined in: server/packages/server/src/commerce/types.ts:96

Properties

currencyCode?
optional currencyCode?: string;

Defined in: server/packages/server/src/commerce/types.ts:99

displayPrice
displayPrice: string;

Defined in: server/packages/server/src/commerce/types.ts:98

providerReference
providerReference: string;

Defined in: server/packages/server/src/commerce/types.ts:97


CommerceProvider

Defined in: server/packages/server/src/commerce/types.ts:148

A provider boundary. Implementations perform all remote verification.

Extended by

Type Parameters

Type ParameterDefault type
TEnvunknown

Properties

key
readonly key: string;

Defined in: server/packages/server/src/commerce/types.ts:149

Methods

acknowledge()?
optional acknowledge(env, transaction): Promise<void>;

Defined in: server/packages/server/src/commerce/types.ts:157

Runs only after the normalized transaction and grants commit.

Parameters
ParameterType
envTEnv
transactionCommerceTransactionReference
Returns

Promise<void>

createCheckout()?
optional createCheckout(env, input): Promise<CommerceCheckout>;

Defined in: server/packages/server/src/commerce/types.ts:158

Parameters
ParameterType
envTEnv
inputCreateCheckoutInput
Returns

Promise<CommerceCheckout>

management()?
optional management(
env,
accountId,
providerAccountId,
returnUrl
): Promise<CommerceManagement>;

Defined in: server/packages/server/src/commerce/types.ts:159

Parameters
ParameterType
envTEnv
accountIdstring
providerAccountIdstring
returnUrlstring
Returns

Promise<CommerceManagement>

products()?
optional products(env, providerReferences): Promise<readonly CommerceProduct[]>;

Defined in: server/packages/server/src/commerce/types.ts:150

Parameters
ParameterType
envTEnv
providerReferencesreadonly string[]
Returns

Promise<readonly CommerceProduct[]>

reconcile()?
optional reconcile(env, transactions): Promise<readonly VerifiedCommerceTransaction[]>;

Defined in: server/packages/server/src/commerce/types.ts:155

Fetches current state for locally active or pending transaction refs.

Parameters
ParameterType
envTEnv
transactionsreadonly CommerceTransactionReference[]
Returns

Promise<readonly VerifiedCommerceTransaction[]>

verifyClaim()
verifyClaim(env, input): Promise<VerifiedCommerceTransaction>;

Defined in: server/packages/server/src/commerce/types.ts:151

Parameters
ParameterType
envTEnv
inputVerifyClaimInput
Returns

Promise<VerifiedCommerceTransaction>

verifyWebhook()?
optional verifyWebhook(env, request): Promise<VerifiedCommerceEvent>;

Defined in: server/packages/server/src/commerce/types.ts:153

Verifies the raw request and fetches current provider state when needed.

Parameters
ParameterType
envTEnv
requestRequest
Returns

Promise<VerifiedCommerceEvent>


CommerceTransactionReference

Defined in: server/packages/server/src/commerce/types.ts:138

Properties

accountId
accountId: string;

Defined in: server/packages/server/src/commerce/types.ts:140

acknowledgementPending
acknowledgementPending: boolean;

Defined in: server/packages/server/src/commerce/types.ts:144

kind
kind: "oneTime" | "subscription";

Defined in: server/packages/server/src/commerce/types.ts:142

providerReference
providerReference: string;

Defined in: server/packages/server/src/commerce/types.ts:141

providerTransactionId
providerTransactionId: string;

Defined in: server/packages/server/src/commerce/types.ts:139

sealedProviderState?
optional sealedProviderState?: string;

Defined in: server/packages/server/src/commerce/types.ts:143


ContentDefinition

Defined in: server/packages/server/src/commerce/types.ts:23

Properties

classification
classification: ContentClassification;

Defined in: server/packages/server/src/commerce/types.ts:24


ContentGrant

Defined in: server/packages/server/src/commerce/types.ts:15

A stable, game-owned noun below the engine-owned content.use verb.

Extended by

Properties

collection
collection: string;

Defined in: server/packages/server/src/commerce/types.ts:16

id
id: string;

Defined in: server/packages/server/src/commerce/types.ts:17


CreateGameInput

Defined in: server/packages/server/src/d1/apply.ts:359

The worker-direct create, engine-owned so implementors never touch the D1 schema: seats already validated by worker policy.

Properties

access
access: GameAccess;

Defined in: server/packages/server/src/d1/apply.ts:363

budgetSeconds
budgetSeconds: number | null;

Defined in: server/packages/server/src/d1/apply.ts:368

capacity?
optional capacity?: {
maximum: number;
};

Defined in: server/packages/server/src/d1/apply.ts:397

maximum
maximum: number;
config
config: JsonObject;

Defined in: server/packages/server/src/d1/apply.ts:366

content?
optional content?: readonly SelectedContent[];

Defined in: server/packages/server/src/d1/apply.ts:389

createdAt
createdAt: number;

Defined in: server/packages/server/src/d1/apply.ts:380

When the game began. now for an online create, which begins here; a local game began on the device, possibly days earlier, so it carries its own instant (clamped to now by the route, since it is a client claim) and history sorts by when it was played rather than when it synchronized.

createdBy
createdBy: string | null;

Defined in: server/packages/server/src/d1/apply.ts:361

creation?
optional creation?: {
creationId: string;
creatorId: string;
fingerprint: string;
};

Defined in: server/packages/server/src/d1/apply.ts:384

Present on client-facing creates; omitted only by low-level test/repair utilities that seed a game directly.

creationId
creationId: string;
creatorId
creatorId: string;
fingerprint
fingerprint: string;
gameId
gameId: string;

Defined in: server/packages/server/src/d1/apply.ts:360

incrementSeconds
incrementSeconds: number | null;

Defined in: server/packages/server/src/d1/apply.ts:369

maxPlayers
maxPlayers: number;

Defined in: server/packages/server/src/d1/apply.ts:373

minPlayers
minPlayers: number;

Defined in: server/packages/server/src/d1/apply.ts:372

now
now: number;

Defined in: server/packages/server/src/d1/apply.ts:381

origin
origin: GameOrigin;

Defined in: server/packages/server/src/d1/apply.ts:364

rated
rated: boolean;

Defined in: server/packages/server/src/d1/apply.ts:370

ratingPool
ratingPool: string | null;

Defined in: server/packages/server/src/d1/apply.ts:371

schemaVersion
schemaVersion: number;

Defined in: server/packages/server/src/d1/apply.ts:365

seats
seats: Seat[];

Defined in: server/packages/server/src/d1/apply.ts:375

shortCode
shortCode: string;

Defined in: server/packages/server/src/d1/apply.ts:374

status
status: "waiting" | "ready";

Defined in: server/packages/server/src/d1/apply.ts:362

turnSeconds
turnSeconds: number | null;

Defined in: server/packages/server/src/d1/apply.ts:367

usage?
optional usage?: readonly {
maximum: number | null;
metric: "game.create.success" | "bot.game.success";
operationId: string;
periodKey: string;
}[];

Defined in: server/packages/server/src/d1/apply.ts:390


EngineConfig

Defined in: server/packages/server/src/engine.ts:107

The EngineConfig seam: the engine never assumes binding names, so the implementor picks bindings off their own Env. Annotate the accessors' env parameter and both type arguments infer.

Type Parameters

Type Parameter
TEnv
TDO extends BaseGameDO<TEnv>

Properties

appName
appName: string;

Defined in: server/packages/server/src/engine.ts:114

The whitelabel app's display name, the single source of truth for the engine's own identity (share metadata and public-page titles today; FCM titles and share copy later). Deliberately top-level, not nested under deepLink, so there is one place to set it regardless of which optional feature blocks are enabled.

avatars?
optional avatars?: AvatarsConfig<TEnv>;

Defined in: server/packages/server/src/engine.ts:136

Opt-in avatar uploads. Omit → not mounted.

clientOrigins?
optional clientOrigins?: readonly string[] | ((env) => readonly string[]);

Defined in: server/packages/server/src/engine.ts:132

Browser origins allowed to call the engine from a different origin.

Same-origin requests always work. When omitted, the engine trusts the exact origin from the conventional WEB_APP_ORIGIN var when it is set. Supply this option to replace that default for multiple or otherwise non-standard browser origins. Paths and wildcards are intentionally unsupported. The list also protects browser WebSocket upgrades, whose Origin header is not governed by CORS.

Set an empty list to disable the WEB_APP_ORIGIN default.

commerce?
optional commerce?: CommerceConfig<TEnv>;

Defined in: server/packages/server/src/engine.ts:139

Opt-in commerce, entitlements, fixed capabilities, and commercial limits. Omit to mount no commerce routes and enforce no commercial policy.

optional deepLink?: DeepLinkConfig;

Defined in: server/packages/server/src/engine.ts:134

Native deep-link verification and store links. Omit for web-only.

gameModule
gameModule: GameModule;

Defined in: server/packages/server/src/engine.ts:108

lifecycle?
optional lifecycle?: LifecycleOptions;

Defined in: server/packages/server/src/engine.ts:146

Cron-backstop tuning: guest-purge/reap windows and batch caps. Omit for the defaults (LIFECYCLE_DEFAULTS); set any subset to override just those.

site?
optional site?: SiteConfig;

Defined in: server/packages/server/src/engine.ts:142

The public web surface: download page, legal documents, crawler files. Omit → not mounted (the worker is API-only).

testing?
optional testing?: {
auth: TokenVerifier;
firebaseAdmin: FirebaseAdminEffects;
};

Defined in: server/packages/server/src/engine.ts:151

Explicit test-only replacements for Firebase verification and Admin effects. Supplying them together prevents a fake verifier from accidentally turning missing production credentials into a nullable runtime path. Leave unset in production.

auth
auth: TokenVerifier;
firebaseAdmin()
firebaseAdmin(env): FirebaseAdminEffects;
Parameters
ParameterType
envTEnv
Returns

FirebaseAdminEffects

Methods

d1()
d1(env): D1Database;

Defined in: server/packages/server/src/engine.ts:116

The engine's D1 database (engine-private).

Parameters
ParameterType
envTEnv
Returns

D1Database

firebaseProjectId()?
optional firebaseProjectId(env): string;

Defined in: server/packages/server/src/engine.ts:121

Firebase project id for token verification; defaults to the FIREBASE_PROJECT_ID var (the only secret verification needs).

Parameters
ParameterType
envTEnv
Returns

string

gameDO()
gameDO(env): DurableObjectNamespace<TDO>;

Defined in: server/packages/server/src/engine.ts:118

The GameDO namespace binding.

Parameters
ParameterType
envTEnv
Returns

DurableObjectNamespace<TDO>


EntitlementDefinition

Defined in: server/packages/server/src/commerce/types.ts:40

Permissions, content ownership, and limits contributed by one source.

Extends

Properties

content?
optional content?: readonly ContentGrant[];

Defined in: server/packages/server/src/commerce/types.ts:36

Inherited from

AccessGrant.content

key
key: string;

Defined in: server/packages/server/src/commerce/types.ts:42

Stable logical key, independent of any storefront product identifier.

limits?
optional limits?: readonly CommercialLimit[];

Defined in: server/packages/server/src/commerce/types.ts:37

Inherited from

AccessGrant.limits

permissions?
optional permissions?: readonly EngineAccessCapability[];

Defined in: server/packages/server/src/commerce/types.ts:35

Inherited from

AccessGrant.permissions


FinishApplyInput

Defined in: server/packages/server/src/d1/apply.ts:39

Properties

finishId
finishId: string;

Defined in: server/packages/server/src/d1/apply.ts:43

The DO-minted idempotency key. The apply is a no-op replay when the games row already carries it.

gameId
gameId: string;

Defined in: server/packages/server/src/d1/apply.ts:40

now
now: number;

Defined in: server/packages/server/src/d1/apply.ts:50

outcomes
outcomes: OutcomeEntry[];

Defined in: server/packages/server/src/d1/apply.ts:44

rated
rated: boolean;

Defined in: server/packages/server/src/d1/apply.ts:46

ratingPool
ratingPool: string | null;

Defined in: server/packages/server/src/d1/apply.ts:47

roster
roster: Seat[];

Defined in: server/packages/server/src/d1/apply.ts:45

seq
seq: number;

Defined in: server/packages/server/src/d1/apply.ts:49

The finishing commit's seq.


FirebaseAdminEffects

Defined in: server/packages/server/src/firebase/admin-effects.ts:15

The Firebase Admin effects used by authenticated engine paths.

Methods

deleteAccount()
deleteAccount(userId): Promise<void>;

Defined in: server/packages/server/src/firebase/admin-effects.ts:19

Permanently delete one Firebase Authentication account.

Parameters
ParameterType
userIdstring
Returns

Promise<void>

notifyUser()
notifyUser(
d1,
userId,
message
): Promise<void>;

Defined in: server/packages/server/src/firebase/admin-effects.ts:17

Send one notification through the engine's registered-device store.

Parameters
ParameterType
d1D1Database
userIdstring
messageNotificationMessage
Returns

Promise<void>


FrameMessage

Defined in: server/packages/server/src/protocol.ts:204

One seat's versioned frame on the wire: the socket fan-out payload, and (for the acting seat) the command-response ride-along. ratings appears only on the post-finish ratings transition.

Properties

data
data: JsonObject;

Defined in: server/packages/server/src/protocol.ts:207

deadline
deadline: number | null;

Defined in: server/packages/server/src/protocol.ts:210

The true client-facing deadline (grace is display-only there).

outcomes?
optional outcomes?: OutcomeEntry[];

Defined in: server/packages/server/src/protocol.ts:212

pendingPlayers
pendingPlayers: number[];

Defined in: server/packages/server/src/protocol.ts:208

playerTimes
playerTimes: number[] | null;

Defined in: server/packages/server/src/protocol.ts:211

ratings?
optional ratings?: RatingDelta[];

Defined in: server/packages/server/src/protocol.ts:213

type
type: "frame";

Defined in: server/packages/server/src/protocol.ts:205

version
version: number;

Defined in: server/packages/server/src/protocol.ts:206


LegalConfig

Defined in: server/packages/server/src/site/config.ts:29

Legal document overrides. Each is an HTML fragment: body content only, no document wrapper; the engine supplies the shell, styling and footer. Omitted documents fall back to the engine's generic templates.

A fragment is inserted as-is, so it is the implementor's own trusted markup with their own values already written in. There are no placeholders to fill: the engine's defaults take an OperatorConfig as typed props, which is what a template's tokens used to stand in for.

Properties

deleteAccount?
optional deleteAccount?: string;

Defined in: server/packages/server/src/site/config.ts:32

privacy?
optional privacy?: string;

Defined in: server/packages/server/src/site/config.ts:31

terms?
optional terms?: string;

Defined in: server/packages/server/src/site/config.ts:30


LocalRecord

Defined in: server/packages/server/src/protocol.ts:257

What a device needs to continue a local game it holds no record for: the seed every transition's randomness derives from, plus the log itself.

Properties

seed
seed: string;

Defined in: server/packages/server/src/protocol.ts:258

transitions
transitions: LocalTransitionRow[];

Defined in: server/packages/server/src/protocol.ts:259


LocalRejection

Defined in: server/packages/server/src/protocol.ts:231

Which transition of an import batch the game refused, and why.

Not a transport error: everything before index is committed and permanent, so the batch answers 200 carrying this. It means the device's Dart twin and the authoritative TypeScript rules disagreed, which the client surfaces as a diverged record rather than retrying. abstain cannot appear: only the alarm's system timeout abstains, and a local game is untimed.

Properties

code
code:
| "expired"
| "notActive"
| "notReady"
| "notPending"
| "stateUpdated"
| "invalidPayload"
| "illegalMove"
| LobbyRejectCode;

Defined in: server/packages/server/src/protocol.ts:233

index
index: number;

Defined in: server/packages/server/src/protocol.ts:232

message
message: string;

Defined in: server/packages/server/src/protocol.ts:234


LocalTransition

Defined in: server/packages/server/src/protocol.ts:117

One transition of a local game's log, as the device recorded it.

data is the game's own action payload for game, and a LifecycleAction for lifecycle — of which only forfeit is importable, because a local game is untimed (so it can never time out) and autoForfeit is engine-driven. The worker validates the lifecycle payload before minting the command, so the DO reads the seat and nothing else.

Properties

data
data: unknown;

Defined in: server/packages/server/src/protocol.ts:120

kind
kind: "lifecycle" | "game";

Defined in: server/packages/server/src/protocol.ts:119

seat
seat: number;

Defined in: server/packages/server/src/protocol.ts:118


LocalTransitionRow

Defined in: server/packages/server/src/protocol.ts:248

One row of a local game's stored log: the raw state and the action that produced it, which is everything a device needs to rebuild its local engine. The ONLY place raw state leaves the Durable Object, and only to the game's single human (see GameStub.localRecord).

Properties

action
action: TransitionAction | null;

Defined in: server/packages/server/src/protocol.ts:251

pending
pending: number[];

Defined in: server/packages/server/src/protocol.ts:252

state
state: JsonObject;

Defined in: server/packages/server/src/protocol.ts:250

version
version: number;

Defined in: server/packages/server/src/protocol.ts:249


OperatorConfig

Defined in: server/packages/server/src/site/config.ts:9

The legal entity publishing the game. Required whenever site is present: the default legal documents take it as a prop and cannot render without it.

Properties

contactEmail
contactEmail: string;

Defined in: server/packages/server/src/site/config.ts:15

Support and privacy contact address.

effectiveDate
effectiveDate: string;

Defined in: server/packages/server/src/site/config.ts:18

Effective date of the legal documents, as displayed. A plain string, not a Date, since it is prose and its format is the operator's choice.

jurisdiction
jurisdiction: string;

Defined in: server/packages/server/src/site/config.ts:13

Governing jurisdiction, e.g. India.

name
name: string;

Defined in: server/packages/server/src/site/config.ts:11

Legal entity name. Also the page footers' copyright holder.


Principal

Defined in: server/packages/server/src/protocol.ts:32

Who a command acts as, resolved at the edge. Exactly one id is set.

Properties

botId
botId: string | null;

Defined in: server/packages/server/src/protocol.ts:34

userId
userId: string | null;

Defined in: server/packages/server/src/protocol.ts:33


RatingDelta

Defined in: server/packages/kernel/dist/index.d.ts:147

One rated identity's before → after, exactly the rating_history row minus store keys. Computed by the D1 applier inside the rating CAS and delivered on the post-finish ratings transition (the kind: "ratings" action).

Properties

displayAfter
displayAfter: number;

Defined in: server/packages/kernel/dist/index.d.ts:155

displayBefore
displayBefore: number;

Defined in: server/packages/kernel/dist/index.d.ts:152

displayChange
displayChange: number;

Defined in: server/packages/kernel/dist/index.d.ts:156

identity
identity: RatingIdentity;

Defined in: server/packages/kernel/dist/index.d.ts:148

muAfter
muAfter: number;

Defined in: server/packages/kernel/dist/index.d.ts:153

muBefore
muBefore: number;

Defined in: server/packages/kernel/dist/index.d.ts:150

pool
pool: string;

Defined in: server/packages/kernel/dist/index.d.ts:149

sigmaAfter
sigmaAfter: number;

Defined in: server/packages/kernel/dist/index.d.ts:154

sigmaBefore
sigmaBefore: number;

Defined in: server/packages/kernel/dist/index.d.ts:151


RetryOptions

Defined in: server/packages/server/src/retry.ts:17

Bounded retry with jittered exponential backoff.

Deliberately transport-agnostic: the caller supplies the predicate deciding which failures are worth retrying. Two live users, with very different predicates and budgets:

  • background D1 mirror writes (isTransientD1Error, in d1/errors.ts);
  • Worker-to-Durable-Object calls (isRetryableDoError, in game-stub.ts).

The shared discipline is the same in both: retry only transient infrastructure failures, never a deterministic one, where retrying would burn the budget before surfacing the real problem, and never an overload, where the documented remedy is to shed load rather than add to it.

Properties

attempts?
optional attempts?: number;

Defined in: server/packages/server/src/retry.ts:19

Total attempts including the first. Default 4.

baseDelayMs?
optional baseDelayMs?: number;

Defined in: server/packages/server/src/retry.ts:21

First backoff, doubling each retry. Default 50ms.

maxDelayMs?
optional maxDelayMs?: number;

Defined in: server/packages/server/src/retry.ts:23

Backoff ceiling. Default 2000ms.

onRetry?
optional onRetry?: (error, attempt) => void;

Defined in: server/packages/server/src/retry.ts:29

Observe each retry (logging); never throws into the loop.

Parameters
ParameterType
errorunknown
attemptnumber
Returns

void

shouldRetry
shouldRetry: (error) => boolean;

Defined in: server/packages/server/src/retry.ts:27

Which failures are worth retrying. Required: there is no safe default, because "retryable" is a property of the transport AND of whether the operation can be applied twice.

Parameters
ParameterType
errorunknown
Returns

boolean

sleep?
optional sleep?: (ms) => Promise<void>;

Defined in: server/packages/server/src/retry.ts:31

Delay primitive, injectable so tests run without real timers.

Parameters
ParameterType
msnumber
Returns

Promise<void>


SelectedContent

Defined in: server/packages/server/src/commerce/types.ts:183

One content choice snapshotted onto a game at creation.

Extends

Properties

classification
classification: ContentClassification;

Defined in: server/packages/server/src/commerce/types.ts:185

collection
collection: string;

Defined in: server/packages/server/src/commerce/types.ts:16

Inherited from

ContentGrant.collection

id
id: string;

Defined in: server/packages/server/src/commerce/types.ts:17

Inherited from

ContentGrant.id

ownership
ownership: ContentOwnershipScope;

Defined in: server/packages/server/src/commerce/types.ts:184


SessionSnapshot

Defined in: server/packages/server/src/protocol.ts:164

The complete live truth about one game, as ONE SEAT sees it: the only message the socket carries, and the body of every accepted command.

Sent on socket open whatever the status, and after every committed change, lobby or state. Self-describing and idempotent: a client that applies the newest one it has seen is correct, having missed any number of earlier ones, so there is no state for it to reconstruct and no channel for it to correlate against another.

It carries the immutable header as well as the moving parts because a game screen must not need a second source. That is what the old split cost: status lived only in a D1 read nothing re-issued, so a client could observe a frame without the status it belonged to, and never learned a game had started.

Hidden information is safe by construction: the envelope is projected per seat before it is sent, and frame is only ever the receiving principal's own seat's view.

Properties

access
access: GameAccess;

Defined in: server/packages/server/src/protocol.ts:176

budgetSeconds
budgetSeconds: number | null;

Defined in: server/packages/server/src/protocol.ts:182

config
config: JsonObject;

Defined in: server/packages/server/src/protocol.ts:180

createdBy
createdBy: string | null;

Defined in: server/packages/server/src/protocol.ts:188

frame
frame: FrameMessage | null;

Defined in: server/packages/server/src/protocol.ts:198

The receiving seat's observation at version. Null in the lobby, and null for a principal holding no seat, which is how an unseated client still learns that the game started.

gameId
gameId: string;

Defined in: server/packages/server/src/protocol.ts:174

Fixed at creation; carried so this is sufficient on its own.

incrementSeconds
incrementSeconds: number | null;

Defined in: server/packages/server/src/protocol.ts:183

maxPlayers
maxPlayers: number;

Defined in: server/packages/server/src/protocol.ts:187

minPlayers
minPlayers: number;

Defined in: server/packages/server/src/protocol.ts:186

origin
origin: GameOrigin;

Defined in: server/packages/server/src/protocol.ts:178

Where this game is played; never changes.

players
players: Seat[];

Defined in: server/packages/server/src/protocol.ts:192

rated
rated: boolean;

Defined in: server/packages/server/src/protocol.ts:184

ratingPool
ratingPool: string | null;

Defined in: server/packages/server/src/protocol.ts:185

schemaVersion
schemaVersion: number;

Defined in: server/packages/server/src/protocol.ts:179

seq
seq: number;

Defined in: server/packages/server/src/protocol.ts:171

Monotonic per game, incremented by every commit. Totally orders snapshots across every path they arrive by, which version cannot do because a lobby change has none. Apply a snapshot only when seq exceeds the held one. finished and aborted are absorbing, so a client also refuses a later non-terminal snapshot rather than resurrecting a completed game.

shortCode
shortCode: string;

Defined in: server/packages/server/src/protocol.ts:175

status
status: GameStatus;

Defined in: server/packages/server/src/protocol.ts:191

What moves.

turnSeconds
turnSeconds: number | null;

Defined in: server/packages/server/src/protocol.ts:181

type
type: "session";

Defined in: server/packages/server/src/protocol.ts:165

version
version: number | null;

Defined in: server/packages/server/src/protocol.ts:194

The newest committed version, or null while the game is in the lobby.


SiteConfig

Defined in: server/packages/server/src/site/config.ts:53

The public web surface a deployed game serves on its own host: download page, legal documents, and the crawler files. Absent → none of it is mounted and the worker stays API-only.

The scaffold reserves these paths for the Worker with Static Assets' run_worker_first; customize legal prose through this typed config.

Properties

description?
optional description?: string;

Defined in: server/packages/server/src/site/config.ts:59

Longer download-page prose. Defaults to tagline.

optional legal?: LegalConfig;

Defined in: server/packages/server/src/site/config.ts:73

madeByCredit?
optional madeByCredit?: string | null;

Defined in: server/packages/server/src/site/config.ts:71

Footer credit line. Defaults to DEFAULT_CREDIT; null removes it.

name?
optional name?: string;

Defined in: server/packages/server/src/site/config.ts:55

Public game name in titles and OG tags. Defaults to appName.

ogImage?
optional ogImage?: string;

Defined in: server/packages/server/src/site/config.ts:69

Path under public/ to the 1200x630 OG image. Defaults to /og-image.png, the name the branding guide prescribes for the Flutter app's own share card: one image, both surfaces. The engine never generates images.

operator
operator: OperatorConfig;

Defined in: server/packages/server/src/site/config.ts:72

primaryColor
primaryColor: string;

Defined in: server/packages/server/src/site/config.ts:61

Hex accent colour, e.g. #1a237e. Also the theme-color.

screenshots?
optional screenshots?: string[];

Defined in: server/packages/server/src/site/config.ts:63

Filenames under public/screenshots/, shown as a scrolling strip.

tagline
tagline: string;

Defined in: server/packages/server/src/site/config.ts:57

One-sentence hook. The meta description and OG description.


TokenVerifier

Defined in: server/packages/server/src/auth/firebase.ts:29

The seam createEngine consumes. Production is createFirebaseVerifier with the default remote JWKS; tests inject a local JWKS and mint their own RS256 tokens.

Methods

verify()
verify(token): Promise<AuthClaims>;

Defined in: server/packages/server/src/auth/firebase.ts:31

Resolve a bearer token to claims, or throw AuthError.

Parameters
ParameterType
tokenstring
Returns

Promise<AuthClaims>


VerifiedCommerceEvent

Defined in: server/packages/server/src/commerce/types.ts:132

A provider-authenticated notification resolved to current provider state.

Properties

accountId
accountId: string;

Defined in: server/packages/server/src/commerce/types.ts:134

providerEventId
providerEventId: string;

Defined in: server/packages/server/src/commerce/types.ts:133

transaction
transaction: VerifiedCommerceTransaction;

Defined in: server/packages/server/src/commerce/types.ts:135


VerifiedCommerceTransaction

Defined in: server/packages/server/src/commerce/types.ts:75

Provider output after server-side verification. Never accepted from a client.

Properties

kind
kind: "oneTime" | "subscription";

Defined in: server/packages/server/src/commerce/types.ts:79

Must match the configured logical offer kind.

providerAccountId?
optional providerAccountId?: string;

Defined in: server/packages/server/src/commerce/types.ts:85

Provider customer/account id, when the provider exposes one.

providerReference
providerReference: string;

Defined in: server/packages/server/src/commerce/types.ts:77

providerTransactionId
providerTransactionId: string;

Defined in: server/packages/server/src/commerce/types.ts:76

purchasedAt
purchasedAt: number;

Defined in: server/packages/server/src/commerce/types.ts:81

requiresAcknowledgement?
optional requiresAcknowledgement?: boolean;

Defined in: server/packages/server/src/commerce/types.ts:93

True when the provider requires a post-ledger acknowledgement.

sealedProviderState?
optional sealedProviderState?: string;

Defined in: server/packages/server/src/commerce/types.ts:91

Adapter-sealed state needed for later verification (for example an encrypted Play purchase token). It MUST be safe to persist in D1 and MUST never contain a plaintext receipt, token, or payment credential.

state
state: CommerceTransactionState;

Defined in: server/packages/server/src/commerce/types.ts:80

validFrom
validFrom: number;

Defined in: server/packages/server/src/commerce/types.ts:82

validUntil?
optional validUntil?: number;

Defined in: server/packages/server/src/commerce/types.ts:83

Type Aliases

Command

type Command =
| {
actor: Principal;
gameId: string;
kind: "join" | "leave";
}
| {
actor: Principal;
gameId: string;
kind: "cancel";
}
| {
actor: Principal;
gameId: string;
kind: "start";
seed?: string;
}
| {
actor: Principal;
botId: string;
gameId: string;
kind: "add-bot";
}
| {
actor: Principal;
data: unknown;
expectedVersion: number;
gameId: string;
kind: "action";
seat: number;
}
| {
actor: Principal | null;
gameId: string;
kind: "lifecycle";
seat?: number;
type: LifecycleType;
}
| {
actor: Principal;
fromVersion: number;
gameId: string;
kind: "local-transitions";
transitions: LocalTransition[];
};

Defined in: server/packages/server/src/protocol.ts:39

Everything that crosses the worker → DO boundary after creation ( create itself is a worker-direct D1 write; the DO does not exist yet).

Union Members

Type Literal
{
actor: Principal;
gameId: string;
kind: "join" | "leave";
}

Type Literal
{
actor: Principal;
gameId: string;
kind: "cancel";
}

Type Literal
{
actor: Principal;
gameId: string;
kind: "start";
seed?: string;
}
actor
actor: Principal;
gameId
gameId: string;
kind
kind: "start";
seed?
optional seed?: string;

The game's base RNG seed. Carried ONLY by the local-import create (POST /games/local): the device already played the game from this seed, so the server's replay has to draw the same values or every random hook would diverge on the first transition. Absent on every other path, where the DO generates one (randomSeed()) and the seed never leaves it.


Type Literal
{
actor: Principal;
botId: string;
gameId: string;
kind: "add-bot";
}

Type Literal
{
actor: Principal;
data: unknown;
expectedVersion: number;
gameId: string;
kind: "action";
seat: number;
}
actor
actor: Principal;
data
data: unknown;
expectedVersion
expectedVersion: number;

The version the client computed the move against; a lower value is arbitrated by the same-view rule.

gameId
gameId: string;
kind
kind: "action";
seat
seat: number;

The acting seat, carried uniformly by humans and bots. The DO verifies it belongs to the actor (user id from the token, bot id from the HMAC claim) against its own roster and rejects otherwise, so a client can never act on a seat it does not hold. Required because one bot id may hold several seats, and uniform for one code path.


Type Literal
{
actor: Principal | null;
gameId: string;
kind: "lifecycle";
seat?: number;
type: LifecycleType;
}
actor
actor: Principal | null;

Null for identity-less system lifecycles (timeout, autoForfeit).

gameId
gameId: string;
kind
kind: "lifecycle";
seat?
optional seat?: number;

The affected seat: forfeit carries the resigning seat (verified against the actor, like an action); autoForfeit the purged seat; timeout carries none (it resolves all pending).

type
type: LifecycleType;

Type Literal
{
actor: Principal;
fromVersion: number;
gameId: string;
kind: "local-transitions";
transitions: LocalTransition[];
}
actor
actor: Principal;

The game's creator: the only principal a local game has.

fromVersion
fromVersion: number;

The version the device believes the server is at. The import is append-only, so a mismatch means another device already appended and this batch is refused whole (stateUpdated).

gameId
gameId: string;
kind
kind: "local-transitions";

Import a run of a local game's transitions into the authoritative object, in order, as one request.

A batch rather than one command per transition because a finished local game is a whole transcript: sending it move by move would cost a Worker and a Durable Object request each, and would let a client stop halfway through with the server's copy in a state the device never saw.

transitions
transitions: LocalTransition[];

CommandResult

type CommandResult =
| {
ok: true;
session: SessionSnapshot;
}
| {
code: | RejectCode
| LobbyRejectCode;
message: string;
ok: false;
};

Defined in: server/packages/server/src/protocol.ts:222

What GameDO.handle() returns: one accepted shape for every command kind, the caller's own post-commit SessionSnapshot, so a lobby command and a move answer with the same value and the client feeds both into one path.

Rejections are values and are recomputed against the authoritative current state on every attempt.


CommerceTransactionState

type CommerceTransactionState = "pending" | "active" | "grace" | "expired" | "revoked";

Defined in: server/packages/server/src/commerce/types.ts:72


CommercialLimit

type CommercialLimit =
| {
maximum: number;
metric: CommercialMetric;
period: CommercialPeriod;
}
| {
maximum: "noCommercialLimit";
metric: CommercialMetric;
};

Defined in: server/packages/server/src/commerce/types.ts:31


CommercialMetric

type CommercialMetric =
| "game.create.success"
| "games.openCreated"
| "bot.game.success"
| "analysis.run.success";

Defined in: server/packages/server/src/commerce/types.ts:27


CommercialPeriod

type CommercialPeriod =
| {
kind: "calendarMonth";
timezone: "UTC";
}
| {
kind: "subscriptionPeriod";
}
| {
kind: "lifetime";
}
| {
kind: "concurrent";
};

Defined in: server/packages/server/src/commerce/types.ts:29


ContentClassification

type ContentClassification = "sharedRuleset" | "cosmetic";

Defined in: server/packages/server/src/commerce/types.ts:20


ContentOwnershipScope

type ContentOwnershipScope = "creator" | "eachParticipant" | "viewer";

Defined in: server/packages/server/src/commerce/types.ts:21


EngineAccessCapability

type EngineAccessCapability =
| {
kind: "app.access";
}
| {
access: GameAccess;
kind: "game.create";
}
| {
access: GameAccess;
kind: "game.join";
}
| {
kind: "game.create.rated";
}
| {
kind: "bot.use";
tier: string;
}
| {
collection: string;
id: string;
kind: "content.use";
}
| {
kind: "replay.read";
}
| {
analysisType?: string;
kind: "analysis.use";
};

Defined in: server/packages/server/src/commerce/types.ts:4

The engine-owned commercial authorization vocabulary.


GameOrigin

type GameOrigin = "online" | "local";

Defined in: server/packages/server/src/protocol.ts:29

Where a game is played, fixed at creation and immutable.

online is the ordinary game: every transition is decided by this server. local is a game the device played offline against on-device bot brains and imported afterwards, transition by transition, through the two import routes. The server still commits every one of them through the same rules, so an imported game is an ordinary game once it lands; origin says how it got here, which is what lets a client badge it, keep it unrated, and know that it may continue appending to it from the device.

Lives here rather than beside the D1 column because it is protocol: it rides SessionSnapshot and the game summary, so a game screen needs no second source to know what it is looking at.


LobbyRejectCode

type LobbyRejectCode =
| "unknownGame"
| "notJoinable"
| "gameFull"
| "alreadyJoined"
| "notParticipant"
| "notCreator"
| "creatorCannotLeave";

Defined in: server/packages/server/src/protocol.ts:128

Why the DO refused a waiting-room command: the integrity column. These are expected refusals (accepted lobby staleness: the lobby may show a game that just filled), returned as values exactly like kernel rejections; the worker maps them to HTTP. Genuine protocol violations (acting on a seat you don't own) still throw.


LocalBatchResult

type LocalBatchResult =
| {
applied: number;
ok: true;
rejection: LocalRejection | null;
session: SessionSnapshot;
}
| {
code: | RejectCode
| LobbyRejectCode;
message: string;
ok: false;
};

Defined in: server/packages/server/src/protocol.ts:242

What one import batch returns: how far it got, the creator's session after the last committed transition, and the rejection that stopped it (null when the whole batch landed). A refusal of the batch as a whole (an unknown game, a non-creator, a fromVersion another device moved past) is the same rejection value shape every command uses.


SingleCommand

type SingleCommand = Exclude<Command, {
kind: "local-transitions";
}>;

Defined in: server/packages/server/src/protocol.ts:106

Every command that is exactly one commit: what GameStub.handle takes. The import batch is the one command that is not, and it has its own entry point, because it answers with how far it got rather than with one commit's result.


UserRow

type UserRow = typeof users.$inferSelect;

Defined in: server/packages/server/src/auth/provision.ts:19

Variables

DEADLINE_GRACE_MS

const DEADLINE_GRACE_MS: 750 = 750;

Defined in: server/packages/kernel/dist/index.d.ts:395

Grace window (ms) added to every deadline comparison so a player who submits on time is not rejected because network latency carried the request past the deadline. Keep it small relative to per-action turnSeconds windows. The client's display-only kServerDeadlineGrace mirrors this.


DEFAULT_BOT_TIER

const DEFAULT_BOT_TIER: "standard" = "standard";

Defined in: server/packages/server/src/commerce/capability.ts:14

The tier of every bot botTiers does not list.

Every bot belongs to exactly one tier, so a bot.use grant always names one and covers only that one. There is deliberately no grant meaning "every bot": it is the grant a free profile reaches for to keep ordinary bots free, and it would quietly cover the paid tiers too. A deployment that prices no bot grants standard; one that sells a tier grants standard free and the paid tier through an entitlement.


DEFAULT_CREDIT

const DEFAULT_CREDIT: "Built with EigenInteractive" = "Built with EigenInteractive";

Defined in: server/packages/server/src/site/config.ts:41

The credit line in every page footer. Set site.madeByCredit to your own string, or to null to drop it.

The footer links whichever part of the line reads CREDIT_BRAND, so a custom credit that names the engine gets the link too, and one that does not renders as plain text rather than pointing somewhere it never mentioned.

Functions

applyFinish()

function applyFinish(d1, input): Promise<RatingDelta[] | null>;

Defined in: server/packages/server/src/d1/apply.ts:71

Apply one finished game to D1. Returns the rated deltas (null for an unrated game) for the DO to deliver as the ratings transition. Throws on failure, so the caller logs and keeps the outbox row (single attempt at the call site; the internal loop only absorbs CAS conflicts).

Parameters

ParameterType
d1D1Database
inputFinishApplyInput

Returns

Promise<RatingDelta[] | null>


capabilityAllows()

function capabilityAllows(granted, required): boolean;

Defined in: server/packages/server/src/commerce/capability.ts:87

Whether a grant covers a requirement. A grant covers exactly the resource it names and nothing wider: a creation access mode, a bot tier, a content item. As with game.create, there is no unparameterized grant standing for "all of them", because that is the grant that silently gives away what a deployment sells. analysis.use still accepts an untyped grant, which covers untyped analysis only; whether an analysis type must be named belongs to the decision that ships analysis.

Parameters

ParameterType
grantedEngineAccessCapability
requiredEngineAccessCapability

Returns

boolean


capabilityKey()

function capabilityKey(capability): string;

Defined in: server/packages/server/src/commerce/capability.ts:60

Stable structural identity for set membership, logs, and error details.

Parameters

ParameterType
capabilityEngineAccessCapability

Returns

string


createEngine()

function createEngine<TEnv, TDO>(cfg): ExportedHandler<TEnv>;

Defined in: server/packages/server/src/engine.ts:487

Creates the complete Cloudflare Worker for one game deployment.

Call this once from the default export of src/index.ts. The returned handler mounts the authenticated game API, WebSocket upgrades, scheduled lifecycle work, and any configured public/deep-link routes. Game implementors provide only EngineConfig.gameModule and binding accessors; routes, persistence, migrations, authentication, and session dispatch stay engine-owned.

Type Parameters

Type Parameter
TEnv extends object
TDO extends BaseGameDO<TEnv>

Parameters

ParameterType
cfgEngineConfig<TEnv, TDO>

Returns

ExportedHandler<TEnv>

Example

export default createEngine({
gameModule,
appName: "My Game",
d1: (env: Env) => env.GAME_DB,
gameDO: (env: Env) => env.GAME_DO,
});

createFirebaseVerifier()

function createFirebaseVerifier(projectId, getKey?): TokenVerifier;

Defined in: server/packages/server/src/auth/firebase.ts:46

Parameters

ParameterType
projectIdstring
getKey?JWTVerifyGetKey<CryptoKeyStructuralFallback | Uint8Array<ArrayBufferLike>>

Returns

TokenVerifier


createGame()

function createGame(d1, input): Promise<void>;

Defined in: server/packages/server/src/d1/apply.ts:409

Write the games row + one participants row per seat, atomically. The DO lazy-inits from exactly these rows on first contact.

A duplicate short code is the only expected insert collision; callers retry it with a newly generated code.

Parameters

ParameterType
d1D1Database
inputCreateGameInput

Returns

Promise<void>


deriveBotKey()

function deriveBotKey(masterSecret, botId): Promise<string>;

Defined in: server/packages/server/src/bot/bot-auth.ts:60

The per-bot signing key as base64, the operator utility. This is the one value an external bot's owner is given, and the only one they need: it is what they HMAC their request bodies with. The master BOT_SIGNING_SECRET never leaves the operator, and because every bot's key is derived from it, registering a bot needs no new secret and no redeploy.

Base64 to match the signature transport encoding. Equivalent to:

echo -n "<botId>" | openssl dgst -sha256 -hmac "<BOT_SIGNING_SECRET>" -binary | base64

Treat the result as a credential: it authenticates that bot to the engine for as long as it is registered. Rotating one bot's key means rotating the master secret, which rotates every bot's key, so issue per-bot keys only to owners you would re-issue all of them for.

Parameters

ParameterType
masterSecretstring
botIdstring

Returns

Promise<string>


displayRating()

function displayRating(mu, sigma): number;

Defined in: server/packages/kernel/dist/index.d.ts:160

max(0, round((mu − 3σ) · 40)): the one server-side home of the display formula (the client mirrors it for optimistic display only).

Parameters

ParameterType
munumber
sigmanumber

Returns

number


ensureUser()

function ensureUser(
d1,
claims,
now
): Promise<{
avatarUrl: string | null;
createdAt: number;
displayName: string;
email: string | null;
id: string;
isAnonymous: boolean;
updatedAt: number;
username: string;
}>;

Defined in: server/packages/server/src/auth/provision.ts:51

Load the caller's row, creating or backfilling it as the token demands. One read on the hot path; writes only on first sight and on guest → permanent conversion.

Parameters

ParameterType
d1D1Database
claimsAuthClaims
nownumber

Returns

Promise<{ avatarUrl: string | null; createdAt: number; displayName: string; email: string | null; id: string; isAnonymous: boolean; updatedAt: number; username: string; }>


isTransientD1Error()

function isTransientD1Error(error): boolean;

Defined in: server/packages/server/src/d1/errors.ts:118

True for the D1 failures worth retrying: a network blip, a storage or Durable-Object reset, a code-update restart, or a transient routing failure.

Deliberately narrow; see RETRYABLE_D1. Pass to withRetry as its shouldRetry for an idempotent D1 write.

Parameters

ParameterType
errorunknown

Returns

boolean


mirrorRoster()

function mirrorRoster(d1, args): Promise<void>;

Defined in: server/packages/server/src/d1/apply.ts:325

The roster mirror after a committed waiting-room command. The DO's roster is the integrity copy; this rewrites the D1 display copy wholesale (delete + reinsert), which is idempotent and immune to per-row drift. Fire-and-forget post-commit (the DO leaves it unawaited, under a retry).

Each reinsert is an INSERT ... SELECT from the game's own row at this revision, so it carries the same guard as the delete: a stale mirror must leave the roster a newer one wrote, not delete it and put back an older one.

Parameters

ParameterType
d1D1Database
args{ gameId: string; now: number; seats: Seat[]; seq: number; status: GameStatus; }
args.gameIdstring
args.nownumber
args.seatsSeat[]
args.seqnumber
args.statusGameStatus

Returns

Promise<void>


openApiDocument()

function openApiDocument(version): OpenAPIObject;

Defined in: server/packages/server/src/engine.ts:602

Parameters

ParameterType
versionstring

Returns

OpenAPIObject


readCreationOperation()

function readCreationOperation(
d1,
creatorId,
creationId
): Promise<
| {
createdAt: number;
creationId: string;
creatorId: string;
fingerprint: string;
gameId: string;
id: string;
shortCode: string;
}
| undefined>;

Defined in: server/packages/server/src/d1/apply.ts:498

Parameters

ParameterType
d1D1Database
creatorIdstring
creationIdstring

Returns

Promise< | { createdAt: number; creationId: string; creatorId: string; fingerprint: string; gameId: string; id: string; shortCode: string; } | undefined>


readGameRow()

function readGameRow(d1, gameId): Promise<
| {
access: GameAccess;
archivedAt: number | null;
budgetSeconds: number | null;
config: JsonObject;
createdAt: number;
createdBy: string | null;
finishedAt: number | null;
finishId: string | null;
id: string;
incrementSeconds: number | null;
maxPlayers: number;
minPlayers: number;
origin: GameOrigin;
outcomes: OutcomeEntry[] | null;
participants: Seat[];
pendingPlayers: number[] | null;
rated: boolean;
ratingPool: string | null;
schemaVersion: number;
seq: number;
shortCode: string;
status: GameStatus;
turnDeadline: number | null;
turnSeconds: number | null;
updatedAt: number;
}
| undefined>;

Defined in: server/packages/server/src/d1/apply.ts:508

Lazy-init read: the D1 game + participants rows the DO copies into its meta/roster on first contact, in one batched round trip.

Parameters

ParameterType
d1D1Database
gameIdstring

Returns

Promise< | { access: GameAccess; archivedAt: number | null; budgetSeconds: number | null; config: JsonObject; createdAt: number; createdBy: string | null; finishedAt: number | null; finishId: string | null; id: string; incrementSeconds: number | null; maxPlayers: number; minPlayers: number; origin: GameOrigin; outcomes: OutcomeEntry[] | null; participants: Seat[]; pendingPlayers: number[] | null; rated: boolean; ratingPool: string | null; schemaVersion: number; seq: number; shortCode: string; status: GameStatus; turnDeadline: number | null; turnSeconds: number | null; updatedAt: number; } | undefined>


resolveCommerce()

function resolveCommerce<TEnv>(config): ResolvedCommerce;

Defined in: server/packages/server/src/commerce/catalog.ts:80

Validate a deployment catalog once, before any request can reach it.

Type Parameters

Type Parameter
TEnv

Parameters

ParameterType
configCommerceConfig<TEnv>

Returns

ResolvedCommerce


updateSummary()

function updateSummary(d1, args): Promise<void>;

Defined in: server/packages/server/src/d1/apply.ts:303

The display upsert after a non-finishing transition: fire-and-forget post-commit (the DO leaves it unawaited, under a retry), re-derivable from the DO at any time.

Parameters

ParameterType
d1D1Database
args{ gameId: string; now: number; pendingPlayers: number[]; seq: number; status?: "active"; turnDeadline: number | null; }
args.gameIdstring
args.nownumber
args.pendingPlayersnumber[]
args.seqnumber
args.status?"active"
args.turnDeadlinenumber | null

Returns

Promise<void>


withRetry()

function withRetry<T>(op, options): Promise<T>;

Defined in: server/packages/server/src/retry.ts:49

Run op, retrying a retryable failure with jittered exponential backoff up to attempts. A non-retryable failure, or the last attempt, throws.

Safe to leave unawaited inside a Durable Object: the DO stays alive while the returned promise (and its backoff timers) is pending, so the whole sequence runs to completion without waitUntil, exactly like the single-attempt writes it wraps.

op MUST be idempotent: a retry can fire after an operation that actually landed but whose acknowledgement was lost. Nothing here can detect that, so it is the caller's invariant, not this function's.

Type Parameters

Type Parameter
T

Parameters

ParameterType
op() => Promise<T>
optionsRetryOptions

Returns

Promise<T>