API changelog
Notable, consumer-facing changes to the public Crowded Kingdoms APIs (Management API,
Game API, Replication API) and SDKs. Newest first. Breaking changes always ship with a
deprecation window — deprecated fields keep working and are marked @deprecated in the
schema (visible in the reference and the
downloadable SDL) until the stated removal date.
2026-07-20 (latest)
Terrain grounding for engine agents + chunk_get repair (game-api v0.14.5)
chunk_getnow works (its SQL had referenced a nonexistent column since Phase 3, so every call errored) and returns the dense voxel grid asstateBase64plus the game's opaque metadata blob aschunkStateBase64.- New
crowdy-game-kit-simterrain::TerrainCache: cached, per-tick budgeted ground sampling over dense chunks (ground_y(x, z)— the server-side equivalent of a client ground scan), fail-soft on unloaded chunks and non-voxel games. - The
mob-engineandnpc-enginetemplates (and Blocks with Friends'bwf-mobs) now walk agents ON the terrain instead of approximating height from nearby players — the approximation floated/flew mobs whenever players jumped or flew, and NPC heights froze at their seeded values.
Redeploy dry run: preview what a release will do before running it
- New Management API query
environmentRedeployPlan(input)— the DRY RUN ofredeployEnvironment. Same input, read-only: it resolves the same target version and returns per-component version diffs (game-api, Buddy, base images), whether game-DB schema DDL applies or is skipped (schemaWillApply+schemaGitRef), Buddy artifact resolution, the exact pipeline tasks/steps the change order would run (enumerated through the real planner), andblockers— everything that would make the real mutation fail (active change order, missing flavors, non-deployable version) reported instead of thrown. Requiresview_environments(the mutation still requiresmanage_environments). - SDK coverage: CrowdyJS 8.15 (
client.environments.redeployPlan(input)) and CrowdyCPP v0.11.0 (admin_().redeployPlan(input)).
Complete flow timelines: demand-driven compute runs always record
wasm_module_runsnow records every demand-driven run —invokeandevententries, success or failure, each carrying itsflowId— in addition to the existing init rows, failures, and circuit probes. Flow timelines (gameModelFlow) therefore show the compute leg of a cross-engine chain instead of only its Model/Automation legs. Healthy high-frequency ticks still aggregate into per-minute usage rather than one row per tick.computeAppDiagnosticsgainstoolchainRustVersion/toolchainWasmOptVersion: the compile-toolchain fingerprint of the replica that served the query (null when the toolchain is not provisioned). Skewed replicas compile correct but non-shared artifacts, so surfacing the fingerprint makes fleet drift visible from the studio. CrowdyJS 8.14.1 / CrowdyCPP v0.10.1 select the new fields.
Operator-editable platform compute ceilings (Management API)
- New operator-only Management API surface: query
cpComputePlatformCeilingsand mutationcpSetComputePlatformCeilingsread and patch the nine platform ceilings the Game API'scomputeSetPolicyclamps per-app compute policies against (maxModules,maxTickHz,fuelPerTick,fuelPerInvoke,maxMemoryMb,maxRunMs,maxDbOpsPerTick,maxEgressMsgsPerMin,maxEgressBytesPerMin). Patch semantics: omitted = unchanged, explicitnull= clear the override (env/default bootstrap values apply), value > 0 = set. Requiresis_operator; changes are audited. Reference:cpComputePlatformCeilings,cpSetComputePlatformCeilings. - Ceiling edits replica-sync to every game-api and take effect in the
computeSetPolicyclamp within ~30 seconds — no game-api restart. TheCOMPUTE_PLATFORM_MAX_*environment variables remain bootstrap defaults. - Game API behavior change (non-breaking): the
computeSetPolicyceiling clamp now reflects operator-set values, so the ceiling named in the... exceeds the platform ceiling (N)error can change over time. - SDK coverage: CrowdyJS 8.14 (
client.operator.computePlatformCeilings()/setComputePlatformCeilings(input)) and CrowdyCPP v0.10.0 (operator_().computePlatformCeilings()/setComputePlatformCeilings) wrap the two fields with the same patch semantics.
2026-07-19
Flow-correlation query + SDK sweep (CrowdyJS 8.13 / CrowdyCPP 0.9)
- New Game API query
gameModelFlow(appId, flowId): stitch one flow correlation id into a single cross-engine timeline — thegameModelEventsrows,gameModelAutomationRunsandcomputeModuleRunssharing theflowIdminted at the entry edge, each array ordered by time ascending. A diagnostics surface gated by app-adminmanage_apps; see Tracing a flow. Partial indexes back theflow_idlookups on all three tables. - CrowdyJS 8.13 / CrowdyCPP 0.9: the default event/run selections now
include
flowId, andgameModel.flow({ appId, flowId })/gameModel().flow(appId, flowId)fetch the stitched timeline (parity 0 missing). Older servers reject the new field/operation with a validation error — everything else keeps working. - Kit invoke helpers treat
computeInvoke's typed contract violation (BAD_REQUEST"Invoke params violate …") as a gameplay verdict:kitInvokeresolves{ success: false, errorMessage }and engine invokes resolve{ success: false, reason }instead of throwing (newisKitVerdictErrorpredicate in CrowdyJS).
Compute fleet hardening: revision-guarded state, flow correlation, shared artifacts, lane codegen
- State-blob writes are revision-guarded: the tick-lease holder always wins
and a non-lease instance's stale
state_setis dropped with an observable module-log warning — keep referee-critical records in Model, not the blob (see the new state-contract warning in Compute Modules). - New
flowIdongameModelEvents,gameModelAutomationRunsandcomputeModuleRuns: one correlation id per entry call, carried acrossmodel_invoke, event triggers andemit_eventcascades — cross-engine flows ("what happened to this kill's reward") are now stitchable. wasm_module_artifacts: modules compile once per fleet; replicas fetch bytes by cache key instead of recompiling, and instances log a toolchain fingerprint at boot (COMPUTE_EXPECTED_RUST_VERSIONturns skew into a loud error).crowdy-compute lanes: declare a fixed-size actor-lane layout once (JSON) and generate matched little-endian codecs for Rust, TypeScript and C++ — no more hand-packing the same bytes on every side.
Container-change push, typed invoke contracts, optimistic-action kit
- New subscription
gameModelContainerChanged: post-commit, metadata-only container-change events (which container, which keys — pull the visibility-filtered state on receipt) with typeName/session filters, fanned out across API replicas. Replaces interval polling with pull-on-push; Blocks with Friends' NPC reconcile loop now rides it with a polling fallback for older servers. - Compute invoke triggers may declare a typed contract
(
contractJson): declared params are validated pre-sandbox (structuredBAD_REQUESTinstead of a guest runtime error), contracts surface oncomputeModuleTriggers, andcrowdy-compute typesgenerates TypeScript wrappers from them. - CrowdyJS 8.11 adds
gameModel.containerChanged(...)and therunOptimisticActionkit helper (the packaged optimistic apply → referee invoke → confirm/rollback loop with actionId receipts); CrowdyCPP 0.8 mirrors withcrowdy::kit::run_optimistic_action(parity 0 missing; the push stream is waived for native clients).
Container query predicates, automation compute actions, event deltas
gameModelContainersgainswhere(up to 8 AND-combined property predicates, the automation-selector shape, type defaults honored) pluslimit/offsetpaging; the compute host mirrors it ascontainers_list_where(SDK0.1.5).- Automations gain
actionKind: compute_invoke: bind a schedule/event/ manual automation directly to a compute module's invoke export (trusted server path,targetMode: global) — the first-class home for cron-shaped compute work, replacing the marker-function pattern. property_changedevent deliveries to compute modules now carry theoldValue/newValuedelta.- SDKs: CrowdyJS 8.11 / CrowdyCPP 0.8 expose the new arguments and
fields (
containersWhereconvenience in CPP); older servers reject the new arguments — omit them and everything else keeps working.
Compute SDK 0.1.4 — atomic world+model referee commits
- New host call
model_invoke_with_world: up to 16 voxel writes commit on the same SQL transaction as anautonomousInvocableModel function. A denied function touches no voxel; a failed voxel write rolls the Model commit back. Each write charges one data op. - Blocks with Friends'
mine/placereferee moved onto the atomic call — the earlier compensation/refund ordering and its bounded loss windows are retired (action receipts remain for client retry idempotency). - No GraphQL schema changes; see the Compute host API reference.
Docs: the "self-reported vitals" client-trust pattern
- Choosing Game APIs now names the
self-reported vitals pattern (client-committed survival stats under
owner_of_self) with its four guardrails: clamp every write, gate restoration on consumed resources, never gate grants or competitive results on self-reported state, and move abuse-sensitive writes behind a compute referee (the expression language deliberately has no clock builtin, so Model invoke policies cannot express cooldowns).
Choosing Game APIs + BWF/TMS authority dogfood
- The canonical five-tier API guide now maps mechanics and genre starters to platform primitives, Model functions, automations, compute engines and client conventions.
- Compute SDK
0.1.3adds app-scopedmodel_invoke, preserving Model transactions/events/notifications when a live referee commits durable results. - CrowdyJS 8.10 / CrowdyCPP 0.7 add atomic inventory crafting and barter, including a hardened server-grant posture.
- BWF schema v6 moves craft/smelt/trade/chests/quests to atomic Model transactions and PvP/fishing/mine/place/rewards to compute referees.
- TMS now routes all battle actions, turns, enemy AI and outcomes through
tms-battle; automations remain test fixtures only.
Compute hardening complete -- measured limits, calibrated billing, failure containment, and the Model-vs-Compute guide
The deferred Phase 10 production-confidence pass is complete:
- Load harness + matrix: up to 50 modules, 5 Hz, six host-call mixes and invoke storms. A 50-module db-heavy fleet sustained 2,500 db-ops/s at full cadence (~80% of one reference game-api process); invokes held 99 rps at p99 4 ms with zero errors.
- Compute billing's deterministic equivalent is now 22M fuel per unit (measured ~21.8M fuel/ms) instead of the Phase 4 placeholder 28M. The free allowance and rate were validated against the 27-engine kit fleet and live Blocks with Friends usage.
- Failure drills proved compile rollback, fuel/watchdog/OOM/panic containment, circuit reset, 256 KB state rejection, lease-holder death, deploy mid-tick, event cascade depth, spend-cap pausing, and environment-wide rollback/resume.
- Runtime fixes: trigger upserts no longer stack duplicate rows; tick-rate edits reload a live module; failed compiles restore the prior succeeded version.
- New Model API vs Compute decision guide, measured engine policy-footprint table, and calibrated billing/limits prose.
2026-07-19
Realtime + live-ops engines and the template registry -- the game-kit catalog complete (CrowdyJS 8.9.0, CrowdyCPP v0.6.0)
Wave 3 closes out the 30-abstraction game-kit catalog with the realtime/ competitive set (all additive):
- New GraphQL surface:
computeTemplates+computeDeployTemplate— the platform's engine-template registry. Deploy any canonical engine by NAME (source-hash-deduped, triggers bound, enabled in one call);moduleNameruns parameterizations side by side. SDK sugar:client.compute.deployTemplate(...)andkit.deploy(blueprints, { engines: [...] }). - Kit crates:
kit-playgainsabilities(cast books, sub-stepped projectiles, AoE falloff) andtiming(checkpoints/laps/ghost tracks);kit-sim::zonesgains shrinking circles (BR schedules with warning/shrink/settle events). - Engine templates:
abilities-engine(AbilityDef-driven casts, type-94 events),movement-warden(observe/flag envelopes, type-95),territory(capture/decay/siege/income, type-96),racing(server-timed laps, auto-boarded results, ghost replays, type-97) +possession(the authoritative ball),liveops-scheduler(window modifiers on the compute bus) — plus thearena-blitz(G6) andzone-rush(G14 BR-lite) acceptance examples. - CrowdyJS 8.9.0 / CrowdyCPP v0.6.0: new
kit.abilities/movement/territory/racing/liveops/moderation/telemetrysurfaces, thekit.lootengine path (pity rolls), liveops/moderation/telemetry blueprints, and event types 94–98 with parsers in both SDKs. Everything capability-detected; the movement warden observes and flags only — it never corrects (client prediction is untouched).
2026-07-19
Session-genre engines -- kit-play completion, kit-econ, six new engine templates, and SDK surfaces (CrowdyJS 8.8.0, CrowdyCPP v0.5.0)
Wave 2 of the game-kit program brings the session genres to the paved road (all additive):
- Kit crates:
crowdy-game-kit-playcompletes withturns(initiative, timeouts, simultaneous reveal),score(authoritative win conditions), andcards(server-held hidden hands, seeded shuffles);crowdy-game-kit-aiadds flow fields, a path cache, and budgeted turn-game movers; newcrowdy-game-kit-econships order-book markets, server-computed standings, production chains with offline catch-up, and pity-timer loot. All allowlisted + vendored. - Engine templates:
match-engine(server-driven lifecycle over MatchMeta),deck-engine(true hidden information),instance-engine(private world slices, seeded runs),director(wave schedules, boss phases, party scaling),matchmaking(rating buckets, party blocks, compute-event handoff to matches),market-engine+board-engine(escrowed order books; tie-aware server rankings with season snapshots), and theminigameinvoke-loop scaffold — plus playable examples per genre:card-duel,dungeon-run,tower-defense,gacha-shrine,idle-factory. The Tactical Model Simulator's enemy phase + outcome authority moved into atms-battlecompute referee (kit-ai). - CrowdyJS 8.8.0 / CrowdyCPP v0.5.0: engine paths on
kit.matches/kit.decks/kit.leaderboards, newkit.instances/kit.director/kit.matchmaking/kit.minigames,kit.economy.orderBook, quests FTUE tutorial sequencing, and reserved event types 91 (turn) / 92 (score) / 93 (proposal) with parsers in both SDKs. Everything capability-detected — model-only deployments keep their behavior.
2026-07-19
Compute Engines -- the game-kit crate family, engine templates, and SDK engine surfaces (CrowdyJS 8.7.0, CrowdyCPP v0.4.0)
Server-side game engines become a paved road (all additive):
- Three new platform-vendored kit crates join
crowdy-game-kit-coreon the module dependency allowlist:crowdy-game-kit-ai(budget-capped A* over aCostProvider, steering behaviors, FSM + JSON behavior-tree interpreter),crowdy-game-kit-sim(deterministic day cycle, weather fronts, resource nodes, timestamp growth/farming, wave schedules, rule zones), andcrowdy-game-kit-play(the combat referee: presence-based hit validation, damage pipeline, kill credit, contact damage). - Engine templates — deployable, data-driven reference engines in
compute-examples/engines/:npc-engine(behavior-tree agents + pets),mob-engine(pooled spawns, aggro/leash/packs, refereedattack_mob),world-engine(weather + nodes + farming). The CLI scaffolds a copy withcrowdy-compute new <name> --engine <npc|mob|world>; apetsexample ships alongside the original five. New docs page: Compute engines. - CrowdyJS 8.7.0 — engine kit surfaces: the
kit/wirepose/lane registry (engineLanes(),enginePoseCodec, type-77/90 event parsers),kit.mobs,kit.pets,kit.combat.attackRouted,kit.worldsim.forecast,kit.npcs.overlayLivePoses, and per-session engine capability detection (kit.engines) so the same client code runs on model-only deployments. - CrowdyCPP v0.4.0 — the same surfaces in C++ (
crowdy/kit/wire.hpp,kit.mobs(),kit.pets(),attackRouted,forecast), parity-tracked against CrowdyJS.
2026-07-18
Compute Modules -- developer tooling: crowdy-compute CLI, game-kit utility crate, examples + tutorial
The compute developer experience grows a paved road (all additive):
crowdy-computeCLI (in thecompute-examplesrepository folder):newscaffolds a module crate,checkmirrors the deploy validation locally (plus a realwasm32-wasip1build when a toolchain is present),deployruns the full upsert → compile-wait → triggers → enable flow idempotently,watch/invoke/statuscover the observe loop.crowdy-game-kit-core— a platform-vendored Rust utility crate for module authors: durable-state harness, actor-pose wire codecs, chunk math, player presence, cadence helpers, event framing, invoke routing, seeded RNG. Addcrowdy-game-kit-core = "0.1.0"to your module's dependencies.- SDK
0.1.2adds two host functions:container_get_batch(up to 32 containers + properties in one data-op) andactors_list_radius(a chunk box of actors in one call), plus a native test-host shim so module crates cancargo testoff-platform. - Five runnable examples (tick-counter, scoreboard, npc-pathfinder, world-weather, mini-game) and a new Compute tutorial — zero to a live module in under 30 minutes.
Game API -- Compute Modules: server-side Rust/WebAssembly logic (additive)
The Game API gains Compute Modules — studios write Rust, deploy the source through GraphQL, and the platform compiles it to WebAssembly and runs it server-side, sandboxed and fuel-metered:
- New GraphQL surface (additive): mutations
computeUpsertModule,computeDeployVersion,computeSetModuleEnabled,computeDeleteModule,computeUpsertTrigger,computeDeleteTrigger,computeSetPolicy,computeInvoke; queriescomputeModules,computeModule,computeModuleVersions,computeModuleTriggers,computeModulePolicy,computeModuleRuns,computeModuleStats,computeModuleLogs,computeAppDiagnostics. Full signatures in the GraphQL reference. - Triggers: fixed-rate ticks, model/compute event subscriptions, and
client-callable invoke exports (synchronous RPC via
computeInvoke, gated by the same authority-policy trees as model functions). - Host API: typed, app-scoped access to game-model data, app state blobs,
chunks/voxels/actors, and replication emits that arrive on the existing
udpNotificationsstream — see the Compute host API reference. Clients need no changes. - Permissions: two new org permission keys —
manage_compute(authoring) andview_compute_diagnostics(monitoring). Org owners hold both by default; existingmanage_appsgrants are unaffected. - Billing: three new shared-environment usage metrics with free hourly
allowances —
wasm_compute_units,wasm_egress_msgs,wasm_egress_bytes(see Shared environment). Rates are placeholders pending load-test calibration. - The management UI app dashboard gains a Compute tab (author, deploy, watch compiles, monitor runs) driven by the same public API.
No existing schema fields, wire messages, or behaviors changed.
Game API v0.13.13 -- invoke policy denials return results; userAppState round-trip fix
Two consumer-facing behavior fixes in gameModelInvoke and the per-user app
state store (no schema shape or wire change):
- Invoke policy denials are results, not errors. A
gameModelInvokerejected by the function's invoke policy (owner_of_self,condition,is_host, ...) now resolves withsuccess: falseand anerrorMessage, and writes a failure event visible ingameModelEvents— matching the documented kit contract ("authority denials are not exceptions — checksuccess"). Scope violations (aninvokeScope: "server"function called without app-admin rights) still throwFORBIDDEN. If your client caughtFORBIDDENto detect gameplay denials, checksuccessinstead;@crowdedkingdoms/crowdyjs@8.4.6and CrowdyCPP handle both server generations transparently in their kit helpers. updateUserAppStatestores what you send. The mutation now decodes its base64stateinput before storage, souserAppState/userAppStatesreturn exactly the base64 that was written. Previously reads returned a double-encoded value; rows written through older servers return the correct encoding after their next write.
CrowdyJS 8.4.5 / 8.4.6 (npm) — kitInvoke maps FORBIDDEN policy
denials from older Game API builds onto the documented
{ success: false, errorMessage } result (8.4.6 republishes 8.4.5 with the
runtime VERSION constant synced).
CrowdyCPP v0.1.0 -- initial public release of the native C++ SDK
CrowdyCPP is the official portable C++ SDK (C++20, CMake, Linux/Windows/macOS), now documented in the new CrowdyCPP docs tab:
- Native UDP replication. Unlike browser-first CrowdyJS, replication goes directly to the replication servers over the Replication API wire protocol — zero-copy framing, HMAC-signed sends, verified receives, automatic token refresh and reconnect. See Replication client.
- Full GraphQL surface parity with CrowdyJS (same domains, two-token model, and error codes), a WorldSession layer mirroring World Stores, and the full 15-layer Game Kit with blueprint equivalence — worlds deployed from either SDK are playable from both.
- Engine-wrappable by design: pluggable HTTP/crypto/clock/log interfaces and a thread-free manual-pump mode for engine plugins. See Engine integration.
SDK-only: no schema or wire change; servers need no changes.
2026-07-18
Game API v0.13.12.2 + CrowdyJS 8.4.1 -- schema hygiene + plot owner-mirror kinds (additive)
A description-only hygiene pass on the Game API schema (no wire, DDL, or behavior change) plus a small CrowdyJS Game Kit patch:
ActorUpdateResponse/VoxelUpdateResponseare formally marked legacy. TheseUdpNotificationunion members are never emitted — the game server retired their dedicated opcodes; an applied update arrives as your own*Notificationself-echo and failures arrive asGenericErrorResponse. Their type descriptions, the union description, and the UDP proxy guide now say so explicitly, and the guide's example subscription no longer selects them. They remain in the union for backward compatibility and will be removed in a future major version.- Deprecation reasons now carry removal dates (per the agent-readiness
checklist): the offset-pagination
limit/offsetargs onvoxelUpdateHistory/gameModelEvents(and their*Connectionvariants, where they are ignored) state removal no earlier than 2027-01-01. - CrowdyJS 8.4.1:
plotBlueprintgainsownerIdKind: 'int' | 'string'— string owner mirrors (the Blocks-with-Friends convention) now work with kit plots: guards compare viato_string($caller_user_id), buying writes the owner as a string, and""is the for-sale sentinel. The bundled schema/reference pick up the hygiene descriptions.
Published SDL + GraphQL reference regenerated. Requires nothing — additive documentation; clients need no changes.
2026-07-18
CrowdyJS 8.4.0 -- World Stores: SDK-managed game state (additive)
A new opt-in layer, @crowdedkingdoms/crowdyjs/stores, moves the client-side
bookkeeping every game hand-writes (actor registries, pose codecs, chunk
caches, chat rings, host polling — ~1,600+ LOC in the reference MMO) into the
SDK as typed, queryable, source-of-truth stores fed by ONE shared
udpNotifications subscription:
- Codecs:
StateCodec<T>withjsonCodec/textCodec/rawCodecandstructCodec— a declarative fixed-layout binary DSL for replication state (the 48-byte pose in ~10 lines). Developers register their custom types + encoders/decoders once; stores speak typed values everywhere. session.self(LocalActorStore): minted + persisted actor uuid, typed state, a 5 Hz send loop with send-on-change dedup + periodic keyframes, and queryablelastSent/lastAck(the applied self-echo) /lastError/status.session.actors(RemoteActorStore): decode-once registry with self-echo filtering, timestamped sample history for interpolation, read-time staleness + reaping, join/update/leave events, and lanes (players vs mobs from one stream).session.errors:GenericErrorResponses attributed to the tracked sends that caused them (per-actor lookup, ring buffer).session.chunks(ChunkStore): dedupedgetChunksByDistanceloading with automatic sparse-voxel-state hydration, realtimevoxelUpdatemerge, typed voxel/chunk-state codecs, optimisticsetVoxel, and the deterministic-worldgen write-back pattern (onMissing+ throttled queue).- Messaging:
channelInbox(per-channel typed history — inbound channel fan-out at last),actorInbox(typed direct messages),events(per-eventType codecs for client/server events +lastEvent). - Durable:
host(heartbeat tracker),save(typed app save blob with debounced autosave),avatar(typed public/private/app state),model(ContainerMirror — typed game-model snapshots with notify-to-pull channel binding).
Ergonomics: compile-time toggles — the core client never imports the
layer ("sideEffects": false; unimported stores tree-shake away) and the
session's TypeScript type is conditional on the config, so unconfigured
stores don't exist. Background-tab safe — writes ride unthrottled
WebSocket events; timer-driven work runs on an injectable Ticker with a
workerTicker() (dedicated Web Worker, exempt from background-tab timer
throttling). SDK-only: no schema or wire change. See
CrowdyJS → World Stores.
2026-07-18
CrowdyJS 8.3.0 -- Game Kit genre layers (additive)
The Game Kit grows from four building blocks to a genre-covering catalog — eleven new layers, each a blueprint builder + typed runtime helper, all pure composition over the existing GraphQL surface (no schema change):
- Economy (
economyBlueprint/kit.economy): multi-currency wallets, atomic shop buys,$self_owner_id-pinned escrow trades and player market, optional restock automation. Trusted mints default to server scope. - Progression (
kit.progression): xp/levels via thefn:curve-helper pattern, skill prerequisite chains, threshold achievements, host-gated rating for match results. - Loot (
kit.loot): weighted tables unrolled into seed-driven expression chains at build time, atomic single-claim grants, event-triggered pooled drops. - Quests (
kit.quests): event-automation progress, atomic claim-into-stack+wallet, cron daily resets. - Combat (
kit.combat): server-side damage/death, status-effect ticks via the selector-join pattern,turnBased/hostSynced/reviveGroupoptions. - Matches (
kit.matches): session-backed lobbies/rounds/turns/scores with a per-match notification channel (notify-to-pull;onMatchChanged) and counter-based turn ticks. - Decks (
kit.decks): hidden hands via owner-visibility properties (the two-property reveal trick) and shuffle-by-position automations. - World simulation (
kit.worldsim): day/night clock with a spatial notification, regenerating nodes, crops, host-read wave counters. - Social (
kit.social+guildBlueprint): parties/guilds/chat over teams + channels, grid territory grants, and a composite guild-hall + bank blueprint. - Leaderboards (
kit.leaderboards): trusted keep-best submits, client-side ranking, cron season rolls. - Monetization (
kit.features+featureGate): feature keys, tier grants, and*policyExtragating options on the plot/lock builders.
Cross-cutting: blueprints.ts split into per-concept modules (import paths
unchanged), shared KitTrustedAuthority / ownerIdKind conventions, and a
new pattern guide (simulation tiers, notify-to-pull, timers without a clock,
hidden information, anti-cheat checklist). See
CrowdyJS → Game Kit and the expanded
genre map. Requires
cks-game-api v0.13.12.1+.
2026-07-18
Game API -- permission-read builtins + selector permission predicates (additive)
Game-model logic can now read the runtime grid ACL and grid layout, completing the read+write loop that permission effects opened:
- Six new expression builtins, usable in mutations, return expressions,
notification args, permission-effect expressions, and policy
conditionrules:has_grid_permission(user, key[, grid]),grid_at(cx, cy, cz[, mode])(overlap modesfirst|smallest|largest),has_chunk_permission(user, key, cx, cy, cz[, mode]),grid_contains,grid_min,grid_max. Reads are app-scoped, cached per invocation, charged 25 gas per uncached lookup, and observe grants applied by the same invocation's permission effects (read-your-writes). - Automation selector permission predicates:
selfPermissionWhere/candidatePermissionWherefilter automation targets by whether the user behind a container has/lacks a grid permission (owner- or property-derived user id; literal, property-derived, or any-grid scope) — one batched ACL query per predicate. Validated atgameModelUpsertAutomationtime. - Upload static analysis warns on wrong builtin arity, invalid
mode/axis literals, and unknown permission keys.
Read-only feature: no schema migration and no wire change. See
Game Models → Reading permissions from expressions
and Autonomous processes → Permission predicates.
CrowdyJS 8.2.0 ships the matching Game Kit surface (plotBlueprint,
chunk-permission lock authority, typed selector predicates). Requires
cks-game-api v0.13.12+.
2026-07-17
Game API -- model permission effects (additive)
Game-model functions can now write runtime grid permissions as declared,
transactional effects. A new permissionEffects array on
gameModelUpsertFunction / gameModelSeed functions declares grants/revokes
({ action, permissionKeys, userExpression, gridIdExpression, ttlSecondsExpression? }) that apply in the same transaction as the
function's property mutations — "pay gold AND get plot access" is one atomic
invoke, immediately enforced by the replication layer on movement/voxel writes.
Details:
- Expressions are compiled server-side and evaluated in the invocation context;
the system params
$caller_user_id,$current_turn_user_id,$self_owner_id, and$session_idare now injected into function-body evaluation as well (previously policyconditionexpressions only) and cannot be spoofed by same-named caller params. - Effects are capped at 4 per function, gas-charged, validated against the
runtime_permissionscatalog, and require the grantee to hold app access; a failing effect rolls back the whole invocation (success: false). - New audit field
GmEvent.permissionEffectsAppliedJsonrecords every applied effect (player- and automation-driven alike). - New types:
FunctionPermissionEffectInput,GmFunctionPermissionEffect(returned onGmFunction.permissionEffects).
See Game Models → Permission effects
and the worked land-purchase example in
Modeling game concepts.
Requires cks-game-api with the 2026-07-17-model-permission-effects migration.
2026-07-10
Unreal SDK 2.1.0 -- Crowdy State, replicated subsystems, and host authority
A large, mostly additive release on the 2.0 architecture: a client-authoritative view plane for per-property replication, non-actor subsystem participants, and an explicit host-authority and ownership surface. New capabilities:
- Crowdy State property replication. Mark a
UPROPERTYor a Blueprint variable withmeta=(CrowdyState)and the owning client diffs and replicates just that value to peers on the client-authoritative view plane, with no snapshot struct or executor. Bare per-property markers tune it:CrowdyOnRep(a parameterless RepNotify),CrowdyOwnerOnly(deliver only to the entity's owner),CrowdyManualDirty(send on an explicitMarkStateDirtyrather than every tick), andCrowdyHeartbeat(opt into the periodic keyframe re-send for late joiners). See Crowdy State and the metadata keys reference. - Replicated subsystems. A host-owned UE Subsystem can take part in both view planes (Crowdy State properties and CrowdyEvents) without becoming an actor, via a function library or two abstract base classes. See Replicated subsystems.
- Host authority and explicit ownership transfer. New
Ownership,HostOverride, andStateHeartbeatfields onUCrowdyEntityComponentfor level-placed world entities and host super-user writes; a request/grant ownership-transfer flow (UCrowdyOwnershipTransfer); a server-validated host check (the Is Crowdy Entity Host (Server) node); and client-side ownership helpers (DoesCrowdyEntityOwn,IsCrowdyEntityHost,GetCrowdyEntityComponent). See Host authority and Entities and spawning.
Breaking changes
These are the only changes that touch an existing 2.0 project; everything above is additive.
CrowdyHasAuthorityrenamed. The Blueprint-pure "am I the host" check onUCrowdyUtilitiesis nowGetCrowdyHasAuthority(Blueprint DisplayName still "Crowdy Has Authority"). The oldCrowdyHasAuthorityname is now the exec/branch variant (Blueprint "Switch Crowdy Has Authority"). Update C++ callers fromCrowdyHasAuthority(this)toGetCrowdyHasAuthority(this); Blueprint nodes re-resolve on recompile. See Host authority.ECrowdyDecayRatecorrected. Removed the non-functionalLinear_100value (theCrowdyDecayoption on aSpatialMulticastCrowdyEvent). It shared an underlying value withLinear_50, so the two were indistinguishable on the wire. The ladder is nowNo_Decay(0),Exponential_Decay(1),Linear_50(2),Linear_25(3),Linear_10(4),Linear_5(5). A Blueprint that had selected "Linear 100 Decay" should re-select a rate; it behaved exactly like "Linear 50 Decay" before. See Recipients and routing.- RPC container parameters hardened. A CrowdyEvent parameter that buries a container
(
TArray/TSet/TMap) inside a struct is now rejected at registration, because a malformed packet could drive an unbounded allocation from its element count; pass the container as a top-level parameter instead. DirectTArray/TSet/TMapof supported element types still work. The set/map parameter wire format also changed (internal blob version 2), so every peer must run a build from this line -- a mixed 2.0/2.1 session drops set/map RPCs at the version gate. See RPC parameter types.
2026-07-01
Social and magic-link sign-in (Unreal SDK, additive)
- Three new Blueprint Async Action latent nodes round out the sign-in surface: Dev
Login, Magic Link Sign In, and Social Sign In, joining the existing
Login / Register / Restore Session nodes on
UCrowdyAuthentication. Each has Success/Error exec pins, so a Blueprint-only project no longer needs to wire the underlying delegates by hand. See Blueprint nodes. - Crowdy Studio's sign-in page now offers a federated social provider or an emailed magic link, alongside the existing email + password, dev sign-in, and organization token options. All four session-scoped methods (password, social, magic link, dev) grant full authoring access — teams, channels, grids, game models, Config Sync, and the Web Console; only the organization token remains management-only. See Crowdy Studio: Signing in.
No breaking changes — email + password sign-in (Login/Register) remains fully
supported side by side with the new methods.
2026-06-28
Dedicated environments available to all studios (Management API)
- You can now create multi-VM dedicated environments (
environmentClass: "dedicated", the default) directly — an isolated Game API fleet, database, and Buddy replication stack for your studio. Previously only the single-VM developer sandbox (environmentClass: "dev_single") was available and dedicated returned a "coming soon" error.createEnvironment/environmentQuotetake the four per-component flavors (databaseFlavor,gameApiFlavor,udpBuddyFlavor,caddyFlavor) plus scaling bounds; creation still gates on the org wallet (environmentQuote.canCreate) and requiresmanage_environments. See Dedicated environments. CksEnvironmentgains an additiveisSharedboolean (true only for the platform's shared environment; always false for your environments). No breaking changes. Clients still discover an app's runtime viaapp.gameApiUrl/platformConfig.sharedGameApiUrl— the shared Game API endpoint is resolved dynamically, so never hard-code it.
2026-06-26
CrowdyJS package — npm org move, v6 version line restored
- The SDK is published as
@crowdedkingdoms/crowdyjs(moved from the former@crowdedkingdomstudiosorg). The version line continues the v6 series: the current release is6.1.1(npmlatest), the direct successor to the old org's6.1.0— same code, new package name. Two interim1.0.xpublishes during the org move reset the version by mistake; they remain installable but are superseded by6.1.1. Install is unpinned, sonpm install @crowdedkingdoms/crowdyjsresolves to6.1.1. See the CrowdyJS SDK guide.
2026-06-26
Game model automations / NPCs (Game API, additive)
- Server-driven automations invoke your game model functions
on their own — on a schedule or in reaction to model activity — so you can build NPCs,
spawners, and ticking world systems that run with no client connected. New GraphQL:
gameModelUpsertAutomation,gameModelUpsertAutomationTrigger,gameModelRunAutomation,gameModelSetAutomationEnabled/Policy, and the monitoring queriesgameModelAutomations,gameModelAutomationRuns,gameModelAutomationStats, andgameModelAppDiagnostics. The entry-point function opts in withautonomousInvocable. All requiremanage_apps. See Autonomous processes (NPCs).
Model-driven realtime notifications (Game API, additive)
- A model function can now push a realtime notification to clients as part of its
invocation, via a
notificationsarray ongameModelUpsertFunction(andgameModelSeed). Each effect has akind(spatial|channel|actor) and arguments built from model expressions; the notification arrives on the existingudpNotificationsstream as aServerEventNotification,ChannelMessageNotification, orSingleActorMessageNotification. Player-invoked and automation-driven changes notify players identically. See Model-driven notifications.
deleteGrid (Game API, additive)
- New
deleteGrid(input: { appId, gridId })mutation removes a studio-created peer grid (e.g. to unblockGRID_OVERLAPS_EXISTING). Hybrid result likecreateGrid; refuses the default world grid and grids with nested children; requiresmanage_apps. See Grids and permissions.
Management API additions (additive)
environmentQuoteandorgEnvironment(s)now returnenvironmentClassandsingleBoxFlavor;appUsageSummarynow returns automation activity totals (automationRuns,automationInvocations,automationComputeUnits); newbuddyBillingTiers/graphqlBillingTiers/postgresBillingTierscatalogs withupdateEnvironmentBillingTiers; and aplayerPulselive-concurrency query.
CrowdyJS v6.1 (SDK, additive)
- The SDK now wraps the full public surface — every non-deprecated root field has a
typed method, including the above. New highlights:
client.gameApps.deleteGrid, the game-model automation +notificationswrappers, the game-model studio reads, and Relay*Connectioncursor-pagination variants alongside the offset lists.deleteGridrequires a server on releasev0.1.33+. See the CrowdyJS guides: Automations, Model-driven notifications, and Grids.
2026-06-13
Signed server→client notifications (Replication API)
- Buddy now signs server→client long-spatial notifications (actor / voxel / audio /
text / generic-spatial / single-actor) with a per-recipient HMAC-SHA256 keyed on
your 64-octet game token — the same scheme you already use to sign client→server
messages. Signed notifications arrive with
containsAuth = 1and a 32-byte HMAC in the spatial tail (the 8-byte slot after it carries server epoch-millis, not part of the HMAC). - Native (direct-UDP) clients: verify the HMAC and drop any
containsAuth = 1long-spatial notification whose tag doesn't match. See HMAC for the algorithm, key handling, and per-language libraries (OpenSSL/C++, .NET, Node, Python, Go, Rust), plus Send and receive. - Browser clients on the GraphQL UDP proxy are unaffected — the proxy handles the signed format transparently.
Additive to the wire layout (the HMAC slot already existed); no fields removed.
2026-06-13 (load shedding)
Resource-aware load shedding (additive)
- New
ServerStatevaluesNearCapacityandFull. Game servers now report a resource-overload state.serverWithLeastClientsalready returns onlyReadyForClientsservers, so an overloaded server is automatically skipped for new connections — no client change needed for host selection. - New Replication API opcode
COMMAND_RECONNECT(22). A server under hard overload asks a client to move:[22][32B HMAC], where the HMAC (HMAC-SHA256 keyed on your 64-octet game token over the type byte) authenticates the command as server-originated. Native (direct-UDP) clients should verify it, then re-queryserverWithLeastClientsand reconnect within the grace period; see Operations → Load shedding and Wire formats. Browser clients on the GraphQL UDP proxy are migrated automatically and never see this message.
No fields were removed; both changes are additive.
2026-06-13 (later)
Agent-readiness design changes (additive)
- Idempotency keys. Economy-sensitive and destructive mutations now accept an optional
idempotencyKey(on theinputobject or as a top-level argument). Replaying with the same key + identical parameters returns the first result instead of re-applying; a different payload under the same key returns the newIDEMPOTENCY_CONFLICTerror code. Covers Management API checkout/billing/grant/quota/app/environment/org mutations and Game APIrollbackVoxelUpdates,revokeGridPermissions, team and actor/avatar deletes. - Relay cursor pagination. New
*Connectionqueries (first/after,edges/pageInfo) for the largest lists (e.g.usersConnection,appsConnection,checkoutsConnection,paymentEventsConnection,walletTransactionsConnection,appUserAccessConnection,voxelUpdateHistoryConnection,actorsConnection,gameModelEventsConnection). The offset queries remain; theirlimit/offsetargs are now@deprecated. See Pagination. - Machine-readable permissions. Guarded fields now carry a
@requiresPermission(scope:, permission:, scopeArg:)directive in the SDL/introspection. - Structured errors. New error codes (
SCOPE_MISSING,CONFLICT,IDEMPOTENCY_CONFLICT,RATE_LIMITED, plus correctedUNAUTHENTICATED/NOT_FOUND) andextensions.remediation/extensions.requiredPermission. See Error codes. - Security fix.
effectiveQuotanow requiresview_usageon the most-specific scope (tier/app/org) instead of being readable by any authenticated user; metric-only lookups (free-tier defaults) remain open. This is a deliberate behavior change for cross-tenant callers.
No fields were removed. The ID/UUID scheme and the UDP wire-protocol versioning are unchanged by design.
2026-06-13
Documentation & schema self-description
- Every public GraphQL query, mutation, subscription, argument, field, and enum value now carries a description across the Management API and Game API — including the required permission and side effects on each operation. These flow into the GraphQL reference and the downloadable SDL.
- Published downloadable SDL at stable URLs:
/schema/management-api.graphql,/schema/game-api.graphql,/schema/crowdyjs.graphql. - Added an
/llms.txtindex and a For AI agents quickstart, plus consolidated Error codes, Pagination, and Rate limits references. - Replication API: published a consolidated opcode/byte-layout reference, documented the NAK-vs-silent-drop failure model and the best-effort reliability contract, and added a worked example packet.
Deprecations (Management API)
CheckoutPurpose.DONATIONandCheckoutPurpose.PROPERTY_TOKENSare deprecated — these products are no longer purchasable. UseORG_WALLET_TOPUPorAPP_ACCESS_PURCHASE. Existing historical checkouts are unaffected.- The
myDonationDataandmyPropertyTokensqueries are deprecated (legacy read paths retained for historical records only).
No fields were removed in this release. Deprecated fields continue to function.
Earlier
Prior releases predate this public changelog. For SDK breaking-change notes, see the CrowdyJS migration guide in the CrowdyJS docs.