@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
| Parameter | Type |
|---|---|
message? | string |
Returns
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
| Parameter | Type |
|---|---|
message? | string |
options? | ErrorOptions |
Returns
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
| Parameter | Type |
|---|---|
ctx | DurableObjectState |
env | TEnv |
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
| Parameter | Type |
|---|---|
gameId | string |
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
| Parameter | Type |
|---|---|
env | TEnv |
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
| Parameter | Type |
|---|---|
request | Request |
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
| Parameter | Type |
|---|---|
env | TEnv |
Returns
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
| Parameter | Type |
|---|---|
args | { from: number; isReplay?: boolean; seat: number | null; to: number; } |
args.from | number |
args.isReplay? | boolean |
args.seat | number | null |
args.to | number |
Returns
Promise<FrameMessage[]>
Implementation of
GameStub.frames
handle()
handle(cmd): Promise<CommandResult>;
Defined in: server/packages/server/src/do/game-do.ts:144
Parameters
| Parameter | Type |
|---|---|
cmd | SingleCommand |
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
| Parameter | Type |
|---|---|
gameId | string |
from | number |
to | number |
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
| Parameter | Type | Description |
|---|---|---|
cmd | { actor: Principal; fromVersion: number; gameId: string; kind: "local-transitions"; transitions: LocalTransition[]; } | - |
cmd.actor | Principal | The game's creator: the only principal a local game has. |
cmd.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). |
cmd.gameId | string | - |
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.transitions | LocalTransition[] | - |
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
| Parameter | Type |
|---|---|
gameId | string |
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
| Parameter | Type |
|---|---|
gameId | string |
userId | string | 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
| Parameter | Type |
|---|---|
_ws | WebSocket |
error | unknown |
Returns
Promise<void>
Overrides
DurableObject.webSocketError
webSocketMessage()
webSocketMessage(ws): Promise<void>;
Defined in: server/packages/server/src/do/game-do.ts:993
Parameters
| Parameter | Type |
|---|---|
ws | WebSocket |
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
| Parameter | Type |
|---|---|
message? | string |
Returns
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
| Parameter | Type |
|---|---|
message? | string |
options? | ErrorOptions |
Returns
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
| Parameter | Type |
|---|---|
status | 400 | 401 | 403 | 404 | 409 | 413 | 415 | 422 | 429 | 500 | 502 |
message | string |
code? | ErrorCode |
retryAfterSeconds? | number |
Returns
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 Parameter | Default type |
|---|---|
TEnv | unknown |
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
| Parameter | Type |
|---|---|
env | TEnv |
transaction | CommerceTransactionReference |
Returns
Promise<void>
createCheckout()?
optional createCheckout(env, input): Promise<CommerceCheckout>;
Defined in: server/packages/server/src/commerce/types.ts:158
Parameters
| Parameter | Type |
|---|---|
env | TEnv |
input | CreateCheckoutInput |
Returns
Promise<CommerceCheckout>
management()?
optional management(
env,
accountId,
providerAccountId,
returnUrl
): Promise<CommerceManagement>;
Defined in: server/packages/server/src/commerce/types.ts:159
Parameters
| Parameter | Type |
|---|---|
env | TEnv |
accountId | string |
providerAccountId | string |
returnUrl | string |
Returns
Promise<CommerceManagement>
products()?
optional products(env, providerReferences): Promise<readonly CommerceProduct[]>;
Defined in: server/packages/server/src/commerce/types.ts:150
Parameters
| Parameter | Type |
|---|---|
env | TEnv |
providerReferences | readonly 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
| Parameter | Type |
|---|---|
env | TEnv |
transactions | readonly CommerceTransactionReference[] |
Returns
Promise<readonly VerifiedCommerceTransaction[]>
verifyClaim()
verifyClaim(env, input): Promise<VerifiedCommerceTransaction>;
Defined in: server/packages/server/src/commerce/types.ts:151
Parameters
| Parameter | Type |
|---|---|
env | TEnv |
input | VerifyClaimInput |
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
| Parameter | Type |
|---|---|
env | TEnv |
request | Request |
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.
deepLink?
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
| Parameter | Type |
|---|---|
env | TEnv |
Returns
Methods
d1()
d1(env): D1Database;
Defined in: server/packages/server/src/engine.ts:116
The engine's D1 database (engine-private).
Parameters
| Parameter | Type |
|---|---|
env | TEnv |
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
| Parameter | Type |
|---|---|
env | TEnv |
Returns
string
gameDO()
gameDO(env): DurableObjectNamespace<TDO>;
Defined in: server/packages/server/src/engine.ts:118
The GameDO namespace binding.
Parameters
| Parameter | Type |
|---|---|
env | TEnv |
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
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
permissions?
optional permissions?: readonly EngineAccessCapability[];
Defined in: server/packages/server/src/commerce/types.ts:35
Inherited from
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
| Parameter | Type |
|---|---|
userId | string |
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
| Parameter | Type |
|---|---|
d1 | D1Database |
userId | string |
message | NotificationMessage |
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, ind1/errors.ts); - Worker-to-Durable-Object calls (
isRetryableDoError, ingame-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
| Parameter | Type |
|---|---|
error | unknown |
attempt | number |
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
| Parameter | Type |
|---|---|
error | unknown |
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
| Parameter | Type |
|---|---|
ms | number |
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
id
id: string;
Defined in: server/packages/server/src/commerce/types.ts:17
Inherited from
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.
legal?
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
| Parameter | Type |
|---|---|
token | string |
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
| Parameter | Type |
|---|---|
d1 | D1Database |
input | FinishApplyInput |
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
| Parameter | Type |
|---|---|
granted | EngineAccessCapability |
required | EngineAccessCapability |
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
| Parameter | Type |
|---|---|
capability | EngineAccessCapability |
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
| Parameter | Type |
|---|---|
cfg | EngineConfig<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
| Parameter | Type |
|---|---|
projectId | string |
getKey? | JWTVerifyGetKey<CryptoKeyStructuralFallback | Uint8Array<ArrayBufferLike>> |
Returns
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
| Parameter | Type |
|---|---|
d1 | D1Database |
input | CreateGameInput |
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
| Parameter | Type |
|---|---|
masterSecret | string |
botId | string |
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
| Parameter | Type |
|---|---|
mu | number |
sigma | number |
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
| Parameter | Type |
|---|---|
d1 | D1Database |
claims | AuthClaims |
now | number |
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
| Parameter | Type |
|---|---|
error | unknown |
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
| Parameter | Type |
|---|---|
d1 | D1Database |
args | { gameId: string; now: number; seats: Seat[]; seq: number; status: GameStatus; } |
args.gameId | string |
args.now | number |
args.seats | Seat[] |
args.seq | number |
args.status | GameStatus |
Returns
Promise<void>
openApiDocument()
function openApiDocument(version): OpenAPIObject;
Defined in: server/packages/server/src/engine.ts:602
Parameters
| Parameter | Type |
|---|---|
version | string |
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
| Parameter | Type |
|---|---|
d1 | D1Database |
creatorId | string |
creationId | string |
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
| Parameter | Type |
|---|---|
d1 | D1Database |
gameId | string |
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
| Parameter | Type |
|---|---|
config | CommerceConfig<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
| Parameter | Type |
|---|---|
d1 | D1Database |
args | { gameId: string; now: number; pendingPlayers: number[]; seq: number; status?: "active"; turnDeadline: number | null; } |
args.gameId | string |
args.now | number |
args.pendingPlayers | number[] |
args.seq | number |
args.status? | "active" |
args.turnDeadline | number | 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
| Parameter | Type |
|---|---|
op | () => Promise<T> |
options | RetryOptions |
Returns
Promise<T>