@crowdedkingdoms/crowdyjs 17.14.0-dev.1 → 18.0.0-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. package/MIGRATION.md +92 -1
  2. package/README.md +93 -162
  3. package/dist/crowdy-client.d.ts +12 -31
  4. package/dist/crowdy-client.d.ts.map +1 -1
  5. package/dist/crowdy-client.js +15 -37
  6. package/dist/crowdy-dsh/bridge.d.ts.map +1 -1
  7. package/dist/crowdy-dsh/bridge.js +3 -6
  8. package/dist/crowdy-studio/controller.d.ts +34 -59
  9. package/dist/crowdy-studio/controller.d.ts.map +1 -1
  10. package/dist/crowdy-studio/controller.js +96 -225
  11. package/dist/crowdy-studio/diagnostics.d.ts +3 -12
  12. package/dist/crowdy-studio/diagnostics.d.ts.map +1 -1
  13. package/dist/crowdy-studio/dom-shell.d.ts +2 -4
  14. package/dist/crowdy-studio/dom-shell.d.ts.map +1 -1
  15. package/dist/crowdy-studio/dom-shell.js +16 -49
  16. package/dist/crowdy-studio/embed/hud-layer.d.ts +1 -2
  17. package/dist/crowdy-studio/embed/hud-layer.d.ts.map +1 -1
  18. package/dist/crowdy-studio/embed/panel.d.ts +3 -13
  19. package/dist/crowdy-studio/embed/panel.d.ts.map +1 -1
  20. package/dist/crowdy-studio/embed/panel.js +3 -6
  21. package/dist/crowdy-studio/index.d.ts +1 -3
  22. package/dist/crowdy-studio/index.d.ts.map +1 -1
  23. package/dist/crowdy-studio/index.js +0 -2
  24. package/dist/crowdy-studio/models.d.ts +3 -4
  25. package/dist/crowdy-studio/models.d.ts.map +1 -1
  26. package/dist/crowdy-studio/starter-projects.d.ts +8 -12
  27. package/dist/crowdy-studio/starter-projects.d.ts.map +1 -1
  28. package/dist/crowdy-studio/starter-projects.js +12 -103
  29. package/dist/domains/appAccess.d.ts +14 -1
  30. package/dist/domains/appAccess.d.ts.map +1 -1
  31. package/dist/domains/appAccess.js +37 -1
  32. package/dist/domains/host.d.ts +3 -3
  33. package/dist/domains/host.js +3 -3
  34. package/dist/domains/marketplace.d.ts +9 -70
  35. package/dist/domains/marketplace.d.ts.map +1 -1
  36. package/dist/domains/marketplace.js +9 -120
  37. package/dist/domains/playerWallet.d.ts +6 -12
  38. package/dist/domains/playerWallet.d.ts.map +1 -1
  39. package/dist/domains/playerWallet.js +6 -21
  40. package/dist/errors.d.ts +7 -13
  41. package/dist/errors.d.ts.map +1 -1
  42. package/dist/errors.js +6 -10
  43. package/dist/generated/graphql.d.ts +141 -7083
  44. package/dist/generated/graphql.d.ts.map +1 -1
  45. package/dist/generated/graphql.js +5 -313
  46. package/dist/grid-mods/exec-client-halves.d.ts +19 -3
  47. package/dist/grid-mods/exec-client-halves.d.ts.map +1 -1
  48. package/dist/grid-mods/exec-client-halves.js +17 -2
  49. package/dist/grid-mods/grid-host-calls.d.ts +29 -17
  50. package/dist/grid-mods/grid-host-calls.d.ts.map +1 -1
  51. package/dist/grid-mods/grid-host-calls.js +40 -46
  52. package/dist/grid-mods/mod-runtime.d.ts +18 -11
  53. package/dist/grid-mods/mod-runtime.d.ts.map +1 -1
  54. package/dist/grid-mods/mod-runtime.js +4 -2
  55. package/dist/grid-scope.d.ts +0 -189
  56. package/dist/grid-scope.d.ts.map +1 -1
  57. package/dist/grid-scope.js +0 -70
  58. package/dist/index.d.ts +11 -17
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +10 -16
  61. package/dist/kit/actions.d.ts +5 -9
  62. package/dist/kit/actions.d.ts.map +1 -1
  63. package/dist/kit/actions.js +5 -9
  64. package/dist/kit/index.d.ts +2 -33
  65. package/dist/kit/index.d.ts.map +1 -1
  66. package/dist/kit/index.js +1 -32
  67. package/dist/kit/kit.d.ts +8 -208
  68. package/dist/kit/kit.d.ts.map +1 -1
  69. package/dist/kit/kit.js +5 -163
  70. package/dist/kit/social.d.ts +1 -3
  71. package/dist/kit/social.d.ts.map +1 -1
  72. package/dist/kit/social.js +1 -3
  73. package/dist/kit/wire.d.ts +16 -5
  74. package/dist/kit/wire.d.ts.map +1 -1
  75. package/dist/kit/wire.js +19 -5
  76. package/dist/live-coding/assets/browser-authoring-index.json +1 -1
  77. package/dist/live-coding/assets/manifest.json +1 -1
  78. package/dist/live-coding/browser-authoring-index.generated.d.ts.map +1 -1
  79. package/dist/live-coding/browser-authoring-index.generated.js +1496 -4386
  80. package/dist/live-coding/rust-analysis.d.ts.map +1 -1
  81. package/dist/live-coding/rust-analysis.js +30 -34
  82. package/dist/player-runtime/client-host-calls.d.ts +8 -0
  83. package/dist/player-runtime/client-host-calls.d.ts.map +1 -0
  84. package/dist/player-runtime/client-host-calls.js +28 -0
  85. package/dist/player-runtime/glue-runtime.d.ts +24 -20
  86. package/dist/player-runtime/glue-runtime.d.ts.map +1 -1
  87. package/dist/player-runtime/glue-runtime.js +26 -55
  88. package/dist/player-runtime/glue-sab.d.ts +2 -2
  89. package/dist/player-runtime/glue-sab.js +2 -2
  90. package/dist/player-runtime/player-code-broker.d.ts +70 -43
  91. package/dist/player-runtime/player-code-broker.d.ts.map +1 -1
  92. package/dist/player-runtime/player-code-broker.js +159 -64
  93. package/dist/player-runtime/player-glue-worker.d.ts +8 -9
  94. package/dist/player-runtime/player-glue-worker.d.ts.map +1 -1
  95. package/dist/player-runtime/player-glue-worker.js +26 -11
  96. package/dist/stores/inbox.d.ts +1 -1
  97. package/dist/stores/inbox.d.ts.map +1 -1
  98. package/dist/stores/index.d.ts +0 -11
  99. package/dist/stores/index.d.ts.map +1 -1
  100. package/dist/stores/index.js +0 -4
  101. package/dist/stores/session.d.ts +0 -2
  102. package/dist/stores/session.d.ts.map +1 -1
  103. package/package.json +1 -1
  104. package/dist/crowdy-studio/model-lint-log.d.ts +0 -76
  105. package/dist/crowdy-studio/model-lint-log.d.ts.map +0 -1
  106. package/dist/crowdy-studio/model-lint-log.js +0 -93
  107. package/dist/crowdy-studio/model-lint.d.ts +0 -61
  108. package/dist/crowdy-studio/model-lint.d.ts.map +0 -1
  109. package/dist/crowdy-studio/model-lint.js +0 -45
  110. package/dist/domains/compute.d.ts +0 -208
  111. package/dist/domains/compute.d.ts.map +0 -1
  112. package/dist/domains/compute.js +0 -274
  113. package/dist/domains/controlPlane.d.ts +0 -38
  114. package/dist/domains/controlPlane.d.ts.map +0 -1
  115. package/dist/domains/controlPlane.js +0 -43
  116. package/dist/domains/gameModel.d.ts +0 -1174
  117. package/dist/domains/gameModel.d.ts.map +0 -1
  118. package/dist/domains/gameModel.js +0 -1333
  119. package/dist/domains/playerCompute.d.ts +0 -91
  120. package/dist/domains/playerCompute.d.ts.map +0 -1
  121. package/dist/domains/playerCompute.js +0 -136
  122. package/dist/domains/playerModel.d.ts +0 -20
  123. package/dist/domains/playerModel.d.ts.map +0 -1
  124. package/dist/domains/playerModel.js +0 -54
  125. package/dist/kit/abilities.d.ts +0 -66
  126. package/dist/kit/abilities.d.ts.map +0 -1
  127. package/dist/kit/abilities.js +0 -71
  128. package/dist/kit/blueprints/combat.d.ts +0 -81
  129. package/dist/kit/blueprints/combat.d.ts.map +0 -1
  130. package/dist/kit/blueprints/combat.js +0 -357
  131. package/dist/kit/blueprints/core.d.ts +0 -222
  132. package/dist/kit/blueprints/core.d.ts.map +0 -1
  133. package/dist/kit/blueprints/core.js +0 -185
  134. package/dist/kit/blueprints/decks.d.ts +0 -50
  135. package/dist/kit/blueprints/decks.d.ts.map +0 -1
  136. package/dist/kit/blueprints/decks.js +0 -163
  137. package/dist/kit/blueprints/economy.d.ts +0 -88
  138. package/dist/kit/blueprints/economy.d.ts.map +0 -1
  139. package/dist/kit/blueprints/economy.js +0 -533
  140. package/dist/kit/blueprints/guild.d.ts +0 -51
  141. package/dist/kit/blueprints/guild.d.ts.map +0 -1
  142. package/dist/kit/blueprints/guild.js +0 -50
  143. package/dist/kit/blueprints/index.d.ts +0 -23
  144. package/dist/kit/blueprints/index.d.ts.map +0 -1
  145. package/dist/kit/blueprints/index.js +0 -22
  146. package/dist/kit/blueprints/inventory.d.ts +0 -84
  147. package/dist/kit/blueprints/inventory.d.ts.map +0 -1
  148. package/dist/kit/blueprints/inventory.js +0 -257
  149. package/dist/kit/blueprints/leaderboards.d.ts +0 -49
  150. package/dist/kit/blueprints/leaderboards.d.ts.map +0 -1
  151. package/dist/kit/blueprints/leaderboards.js +0 -126
  152. package/dist/kit/blueprints/liveops.d.ts +0 -42
  153. package/dist/kit/blueprints/liveops.d.ts.map +0 -1
  154. package/dist/kit/blueprints/liveops.js +0 -170
  155. package/dist/kit/blueprints/locks.d.ts +0 -82
  156. package/dist/kit/blueprints/locks.d.ts.map +0 -1
  157. package/dist/kit/blueprints/locks.js +0 -155
  158. package/dist/kit/blueprints/loot.d.ts +0 -90
  159. package/dist/kit/blueprints/loot.d.ts.map +0 -1
  160. package/dist/kit/blueprints/loot.js +0 -229
  161. package/dist/kit/blueprints/matches.d.ts +0 -84
  162. package/dist/kit/blueprints/matches.d.ts.map +0 -1
  163. package/dist/kit/blueprints/matches.js +0 -349
  164. package/dist/kit/blueprints/moderation.d.ts +0 -32
  165. package/dist/kit/blueprints/moderation.d.ts.map +0 -1
  166. package/dist/kit/blueprints/moderation.js +0 -140
  167. package/dist/kit/blueprints/npcs.d.ts +0 -78
  168. package/dist/kit/blueprints/npcs.d.ts.map +0 -1
  169. package/dist/kit/blueprints/npcs.js +0 -125
  170. package/dist/kit/blueprints/plots.d.ts +0 -63
  171. package/dist/kit/blueprints/plots.d.ts.map +0 -1
  172. package/dist/kit/blueprints/plots.js +0 -151
  173. package/dist/kit/blueprints/progression.d.ts +0 -68
  174. package/dist/kit/blueprints/progression.d.ts.map +0 -1
  175. package/dist/kit/blueprints/progression.js +0 -324
  176. package/dist/kit/blueprints/quests.d.ts +0 -72
  177. package/dist/kit/blueprints/quests.d.ts.map +0 -1
  178. package/dist/kit/blueprints/quests.js +0 -285
  179. package/dist/kit/blueprints/worldsim.d.ts +0 -91
  180. package/dist/kit/blueprints/worldsim.d.ts.map +0 -1
  181. package/dist/kit/blueprints/worldsim.js +0 -468
  182. package/dist/kit/combat.d.ts +0 -141
  183. package/dist/kit/combat.d.ts.map +0 -1
  184. package/dist/kit/combat.js +0 -196
  185. package/dist/kit/decks.d.ts +0 -157
  186. package/dist/kit/decks.d.ts.map +0 -1
  187. package/dist/kit/decks.js +0 -186
  188. package/dist/kit/director.d.ts +0 -88
  189. package/dist/kit/director.d.ts.map +0 -1
  190. package/dist/kit/director.js +0 -86
  191. package/dist/kit/economy.d.ts +0 -289
  192. package/dist/kit/economy.d.ts.map +0 -1
  193. package/dist/kit/economy.js +0 -427
  194. package/dist/kit/engine.d.ts +0 -48
  195. package/dist/kit/engine.d.ts.map +0 -1
  196. package/dist/kit/engine.js +0 -113
  197. package/dist/kit/features.d.ts +0 -60
  198. package/dist/kit/features.d.ts.map +0 -1
  199. package/dist/kit/features.js +0 -65
  200. package/dist/kit/instances.d.ts +0 -52
  201. package/dist/kit/instances.d.ts.map +0 -1
  202. package/dist/kit/instances.js +0 -60
  203. package/dist/kit/inventory.d.ts +0 -129
  204. package/dist/kit/inventory.d.ts.map +0 -1
  205. package/dist/kit/inventory.js +0 -200
  206. package/dist/kit/leaderboards.d.ts +0 -86
  207. package/dist/kit/leaderboards.d.ts.map +0 -1
  208. package/dist/kit/leaderboards.js +0 -133
  209. package/dist/kit/liveops.d.ts +0 -112
  210. package/dist/kit/liveops.d.ts.map +0 -1
  211. package/dist/kit/liveops.js +0 -183
  212. package/dist/kit/loot.d.ts +0 -128
  213. package/dist/kit/loot.d.ts.map +0 -1
  214. package/dist/kit/loot.js +0 -160
  215. package/dist/kit/matches.d.ts +0 -301
  216. package/dist/kit/matches.d.ts.map +0 -1
  217. package/dist/kit/matches.js +0 -458
  218. package/dist/kit/matchmaking.d.ts +0 -57
  219. package/dist/kit/matchmaking.d.ts.map +0 -1
  220. package/dist/kit/matchmaking.js +0 -59
  221. package/dist/kit/minigames.d.ts +0 -30
  222. package/dist/kit/minigames.d.ts.map +0 -1
  223. package/dist/kit/minigames.js +0 -38
  224. package/dist/kit/mobs.d.ts +0 -90
  225. package/dist/kit/mobs.d.ts.map +0 -1
  226. package/dist/kit/mobs.js +0 -98
  227. package/dist/kit/moderation.d.ts +0 -73
  228. package/dist/kit/moderation.d.ts.map +0 -1
  229. package/dist/kit/moderation.js +0 -103
  230. package/dist/kit/movement.d.ts +0 -78
  231. package/dist/kit/movement.d.ts.map +0 -1
  232. package/dist/kit/movement.js +0 -103
  233. package/dist/kit/notifications.d.ts +0 -45
  234. package/dist/kit/notifications.d.ts.map +0 -1
  235. package/dist/kit/notifications.js +0 -67
  236. package/dist/kit/npcs.d.ts +0 -226
  237. package/dist/kit/npcs.d.ts.map +0 -1
  238. package/dist/kit/npcs.js +0 -141
  239. package/dist/kit/objects.d.ts +0 -116
  240. package/dist/kit/objects.d.ts.map +0 -1
  241. package/dist/kit/objects.js +0 -119
  242. package/dist/kit/pets.d.ts +0 -85
  243. package/dist/kit/pets.d.ts.map +0 -1
  244. package/dist/kit/pets.js +0 -96
  245. package/dist/kit/plots.d.ts +0 -85
  246. package/dist/kit/plots.d.ts.map +0 -1
  247. package/dist/kit/plots.js +0 -113
  248. package/dist/kit/progression.d.ts +0 -181
  249. package/dist/kit/progression.d.ts.map +0 -1
  250. package/dist/kit/progression.js +0 -265
  251. package/dist/kit/quests.d.ts +0 -171
  252. package/dist/kit/quests.d.ts.map +0 -1
  253. package/dist/kit/quests.js +0 -237
  254. package/dist/kit/racing.d.ts +0 -85
  255. package/dist/kit/racing.d.ts.map +0 -1
  256. package/dist/kit/racing.js +0 -99
  257. package/dist/kit/shared.d.ts +0 -73
  258. package/dist/kit/shared.d.ts.map +0 -1
  259. package/dist/kit/shared.js +0 -101
  260. package/dist/kit/telemetry.d.ts +0 -66
  261. package/dist/kit/telemetry.d.ts.map +0 -1
  262. package/dist/kit/telemetry.js +0 -133
  263. package/dist/kit/territory.d.ts +0 -97
  264. package/dist/kit/territory.d.ts.map +0 -1
  265. package/dist/kit/territory.js +0 -114
  266. package/dist/kit/worldsim.d.ts +0 -263
  267. package/dist/kit/worldsim.d.ts.map +0 -1
  268. package/dist/kit/worldsim.js +0 -268
  269. package/dist/stores/model.d.ts +0 -81
  270. package/dist/stores/model.d.ts.map +0 -1
  271. package/dist/stores/model.js +0 -163
package/MIGRATION.md CHANGED
@@ -1,3 +1,88 @@
1
+ # CrowdyJS v18 — the legacy engines are gone
2
+
3
+ **Breaking.** The game API deleted its legacy developer-code engines on dev (cks-game-api #417,
4
+ ck-api `v2.27.0`): Studio compute, the game model and its automations, player compute (its
5
+ browser CLIENT modules too) and the player model. `18.0.0` removes their SDK surface. Their
6
+ code moves to ck-exec (`client.exec`): an app's server code as hubs and spokes, a player's grid
7
+ code as mods, and a mod's browser code as its CLIENT half. Nothing is migrated for you; port the
8
+ code, then upgrade.
9
+
10
+ **What it needs.** 18.0.0 calls nothing the legacy engines served, so it runs against any API
11
+ with ck-exec CLIENT halves (ck-api `v2.24.0`, as 17.14.0 did). **Crowdy Studio's CLIENT
12
+ projects need ck-api `v2.25.1` or later:** `v2.24.0` and `v2.25.0` refuse to save a
13
+ `crowdy-client-sdk` crate in a Studio project (`CROWDY_STUDIO_MANIFEST_INVALID`, cks-game-api
14
+ #425). The other way round, a 17.x SDK against `v2.27.0` fails every call into a deleted field
15
+ as a GraphQL validation error.
16
+
17
+ | 17.x | 18.0 |
18
+ | --- | --- |
19
+ | `client.gameModel` (containers, properties, functions, `invoke`, sessions, events, timers, automations, `seed`, lint, the player-count feed) | A hub's own state and endpoints: `client.exec.connect(appId, { nodeType, key })`, then `call` / `subscribe`; timers are `ctx.timer_after` / `ctx.timer_every` in the hub; sessions are a keyed hub (the `session` starter) |
20
+ | `gameModel.defineFeature`, `grantTierFeature`, `revokeTierFeature`, `features`, `tierFeatures` | `client.appAccess.defineFeature`, `grantTierFeature`, `revokeTierFeature`, `features(appId)`, `tierFeatures(appId, tierId?)` (same fields; a hub reads them with `players.features`) |
21
+ | `client.compute` (modules, `invoke`, templates, runs, logs) | `client.exec.starters` / `build` / `waitForBuild` / `deploy`, `logs`, `instances`, `versions`, `activateVersion`, `setEnabled`; manual calls through `connectAsDeveloper` |
22
+ | `client.playerModel` (containers, automations) | A mod's own state and timers |
23
+ | `client.playerCompute` SERVER side (`deploy` with `target: SERVER`, `setEnabled`, `setRequires`, `invoke`, `runs`, `logs`) | Mods: `client.exec.modBuild` / `waitForModBuild` / `modDeploy` / `modSetEnabled`, calls through `connect(appId, { nodeType: execModType(name), key: gridId })`, `modLogs` |
24
+ | `client.playerCompute` CLIENT modules (`deploy`, `versions`, `artifact`, `artifactBytes`, `usage`, `myModules`, `delete`, `setSwitch`, `switches`) | A mod's CLIENT half: `client.exec.modClientBuild` (polled with `modBuildStatus` / `waitForModBuild`), `modClientDeploy` / `modClientDelete`, `modClientArtifactBytes`; its kill ladder is the mod's, `modSetSwitch` |
25
+ | `marketplace.gridClientMods`, `consentGridClientMod`, `trustGridAuthor`, `clientArtifact`, `clientArtifactBytes`, and `client.grid(...).compute.clientMods` | `client.exec.gridClientMods`, `consentClientMod`, `trustAuthor`, `modClientArtifactBytes` (which checks the bytes against their digest); `ExecClientHalves` runs a grid's CLIENT halves |
26
+ | `marketplace.listings` / `versions` / `publishListing` / `publishVersion` / `acquire` / `install` / `uninstall` / `myAcquisitions` / `myInstalls` | `client.exec.modPublish` / `modListings` / `modInstall` / `modUnpublish`; a listing carries its mod's CLIENT half |
27
+ | `playerWallet.policies` / `setPolicy` / `deletePolicy` (`playerWasmPolicies`) | Mods run under the platform's mod limits; the kill ladder is `client.exec.modSetSwitch` |
28
+ | `client.operator` (`computePlatformCeilings`, `setComputePlatformCeilings`) | ck-exec code is bounded by its manifest limits within the platform's; there is nothing to call |
29
+ | `client.kit(appId)` blueprints, `kit.deploy`, engines, `kit.inventory` … `kit.minigames`, `kit.features` | Hubs; the starters for NPCs and mobs, sessions and matchmaking. `kit.social` stays; `kit/wire.ts` codecs and `runOptimisticAction` stay |
30
+ | `createWorldSession({ model })` (`ContainerMirror`) | Subscribe to the hub's topic |
31
+ | `client.grid(...).sessions`, `.model`, `.compute` | A mod on the grid (`client.exec.mod*`) |
32
+ | `PlayerCodeBroker` / `startGridMod` without `engine` (a legacy CLIENT module: unmetered, with the whole client catalog), `ALLOWED_HOST_CALLS` | A CLIENT half, the only kind of player module: `artifactHash`, `fuelPerDispatch` and `consentedHostCalls` are required, the allowlist is `EXEC_CLIENT_HOST_CALLS`, and the module must carry the `ck_fuel` meter |
33
+ | `MODEL_LINT_QUERY`, `modelLintDiagnostics`, `CrowdyModelLintLog`, the `'model-lint'` diagnostic source | The Rust compiler's diagnostics from the build |
34
+
35
+ - **The player runtime runs CLIENT halves only.** `PlayerCodeBroker`'s `artifactHash` (the
36
+ served `digest`), `fuelPerDispatch` and `consentedHostCalls` are required, and `engine` is
37
+ `'ck-exec'` or absent; a broker without them, or asked for another engine, does not start.
38
+ The glue offers exactly `EXEC_CLIENT_ABI_IMPORTS` and refuses a module without the `ck_fuel`
39
+ meter; its inert wasi stubs and the `wasi_unstable` alias are gone. `ALLOWED_HOST_CALLS` is
40
+ gone, and `GLUE_HOST_FUNCTIONS` names the CLIENT allowlist. `startGridMod`'s wasm spec needs
41
+ the same three values.
42
+ - **CLIENT host calls the legacy engines answered are refused** by the broker as not allowed:
43
+ the Game Model group (`container_*`, `containers_list`, `property_set`, `edge_*`,
44
+ `model_invoke`), `sessions_list`, and `grid_state_get` / `grid_state_set`. A mod's server
45
+ half, a hub keyed by the grid, holds grid state now. `createGridHostCalls` / `startGridMod`
46
+ lost `allowModelInvoke` and the client's `gameModel`.
47
+ - **What a CLIENT half says and answers, on the page** (new):
48
+ - `onLog`: its `crowdy::log` lines (crowdy-client-sdk levels 0 debug, 1 info, 2 warn,
49
+ 3 error), at most `PLAYER_CODE_LOG_LINES_PER_SECOND` (20) a second and
50
+ `PLAYER_CODE_LOG_MAX_CHARS` (1,000) characters each, then a `warn` counting what was
51
+ dropped. On `PlayerCodeBroker`, `ExecClientHalves` (with the mod) and `startGridMod`. The
52
+ text is the mod author's: render it as text. Crowdy Studio shows its preview's lines in
53
+ Logs.
54
+ - `invoke(payload)`: the module's `handle_invoke` export, called by the page:
55
+ `PlayerCodeBroker.invoke`, `ExecClientHalves.invoke(modId, payload)` and
56
+ `RunningGridMod.invoke`, up to `PLAYER_CODE_INVOKE_MAX_BYTES` (256 KiB) each way. The reply
57
+ is the module's: treat it as untrusted input.
58
+ - `createGridHostCalls` answers `avatar_state_get` and `grid_permission_check` as the host
59
+ catalog scopes them: an avatar whose live actor the game places inside the grid
60
+ (`local.avatarChunk`, then the public `avatarAppState`), and the visiting player
61
+ (`userId`) on this grid, from the permission keys the game knows
62
+ (`local.gridPermissionKeys`). Without those they are refused as not offered, as
63
+ `actors_list` is without `local.actorsInChunk`.
64
+ - **Crowdy Studio runs on ck-exec only.** Drop `serverEngine` from the embed, the controller
65
+ and `mountCrowdyStudio`, and `playerCompute` from the embed's services and the controller's
66
+ and `mountCrowdyStudio`'s options (`CrowdyStudioPlayerCompute` is gone); they require
67
+ `mods: client.exec`, and the embed requires `client.exec`. `CrowdyStudioState` loses
68
+ `serverEngine`, `runs` (the Runs panel went) and `usage` (`CrowdyStudioUsageSnapshot`:
69
+ nothing on ck-exec spends player compute quota, and the `'usage'` surface reads the
70
+ wallet); `logs` are `CrowdyStudioLogLine`s (`id`, `source` `'mod' | 'preview'`,
71
+ `moduleName`, `level`, `at`, `text`); `CrowdyStudioInvokeResult` is
72
+ `{ resultJson, durationUs }`. `createCrowdyStudioStarterProject` needs `modStarter` for a
73
+ kind with a SERVER target and has no `engine`: a CLIENT target is a `crowdy-client-sdk`
74
+ CLIENT half. The pairing control went: a mod has no pairing.
75
+ - A CLIENT crate still on `crowdy-compute-sdk` is refused before any build, with what to
76
+ change: `crowdy-client-sdk = "0.1.0"` in `Cargo.toml` and `crowdy_client_sdk` in place of
77
+ `crowdy_compute_sdk` in `src/`. Its host calls are the same less the Game Model, sessions and
78
+ grid state (`grid_state_get` / `grid_state_set`).
79
+ - `ENGINE_SWITCHED_OFF` left `CrowdyFaultCode`: nothing raises it now.
80
+ - The kit's type-98 parser is `parseZoneChangeEvent` beside the other wire parsers.
81
+
82
+ `schema.gql` and the generated types follow the game API: the release carries cks-game-api
83
+ `dev`'s SDL after #417 merged (`npm run schema:sync:paths -- --schema <that schema.gql>`, then
84
+ `npm run codegen`).
85
+
1
86
  # 17.14.0 ck-exec CLIENT halves
2
87
 
3
88
  Dev-tier preview (cks-game-api #422, P3 W1). **The release needs a game API that has #422:**
@@ -65,9 +150,15 @@ trust its author. It replaces the legacy grid-attached client mods, which keep w
65
150
  Existing CLIENT projects keep their files: a CLIENT crate on `crowdy-compute-sdk` is refused on
66
151
  ck-exec before any build, with what to change (the SDK line becomes
67
152
  `crowdy-client-sdk = "0.1.0"`, `crowdy_compute_sdk` becomes `crowdy_client_sdk`; the host
68
- calls are the same less the Game Model and sessions). `serverEngine: 'player-compute'` keeps
153
+ calls are the same less the Game Model, sessions and grid state, `grid_state_get` /
154
+ `grid_state_set`, which a mod's server half holds now). `serverEngine: 'player-compute'` keeps
69
155
  both targets on legacy player compute until 18.0.
70
156
 
157
+ **Studio's CLIENT target on ck-exec needs ck-api `v2.25.1` or later.** `v2.24.0` and
158
+ `v2.25.0` refuse to save a `crowdy-client-sdk` crate in a Studio project
159
+ (`CROWDY_STUDIO_MANIFEST_INVALID`, cks-game-api #425), so a CLIENT project cannot start there;
160
+ the SDK calls themselves need only `v2.24.0`.
161
+
71
162
  # 17.13.0 ck-exec observability
72
163
 
73
164
  Additive (dev-tier preview; ck-api `v2.22.0`).
package/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  The official browser-first TypeScript SDK for **Crowded Kingdoms**. CrowdyJS
4
4
  gives you typed clients for the whole platform: identity and
5
- studio administration (the Management surface), world data and the abstract
6
- game model (the Game surface), and the UDP proxy realtime stream — all over
7
- one unified GraphQL API.
5
+ studio administration (the Management surface), world data (the Game surface),
6
+ the UDP proxy realtime stream, and ck-exec, where an app's server code runs —
7
+ all behind one unified GraphQL API.
8
8
 
9
9
  Authentication follows a two-token model: an identity **session token** for
10
10
  account and admin operations, and short-lived **app-scoped tokens** for
@@ -225,23 +225,19 @@ never told about, so a native refresh without it is a re-placement.
225
225
  | `client.platform` | Public platform configuration (`config()`). |
226
226
  | `client.serverStatus` | `gameClientBootstrap(appId)` — per-app version info, UDP status, spatial limits. |
227
227
  | `client.chunks`, `client.voxels`, `client.actors`, `client.avatars`, `client.state` | World data reads + writes: terrain/LODs, voxel edit + history/rollback, durable actors, avatars, per-user app state blobs. |
228
- | `client.host` | Game-host election (`get`, `amIHost`) + actor liveness `heartbeat`. `amIHost` is UI convenience only — authoritative host gating uses `gameModelInvoke`'s `is_host` policy. |
228
+ | `client.host` | Game-host election (`get`, `amIHost`) + actor liveness `heartbeat`. `amIHost` is UI convenience only — a hub decides host-only actions from its caller. |
229
229
  | `client.teleport` | Teleport requests. |
230
230
  | `client.channels`, `client.teams` | Messaging channels and app-scoped player teams (membership + roles). |
231
- | `client.gameModel` | Abstract game model: containers, properties, functions (incl. model-driven `notify_*` effects), sessions, app-scoped active-session counts (`activePlayerCount`, `activePlayerCountChanged`), container-change push (`containerChanged`), flow-correlation timelines (`flow`), automations / NPCs (`upsertAutomation`, `runAutomation`, `automationRuns`, `automationStats`, …), and one-shot timers (`scheduleInvoke`, `cancelTimer`, `timers`). |
232
- | `client.compute` | Compute Modules — server-side Rust/WASM logic: author + deploy source (`upsertModule`, `deployVersion`, `deployTemplate`, `waitForCompile`), triggers + policy, synchronous `invoke`, and monitoring (`moduleRuns`, `moduleStats`, `moduleLogs`, `appDiagnostics`). See [Compute Modules](https://docs.crowdedkingdoms.com/game-api/compute-modules). |
233
- | `client.exec` | **ck-exec (dev-tier preview, 17.9.0):** `connect(appId, { nodeType, key })` opens a player's connection to an execution host; the `ExecConnection` it returns has `call`, `callRaw`, `subscribe`, `ping`, `onReconnect` and `close`, with MessagePack payloads, and it reconnects and renews subscriptions by itself. `deploy({ appId, root, types })` deploys an app's hubs and spokes (`manage_compute`). Players' mods (`modBuild`, `modDeploy`, ...) and, since 17.14.0, their CLIENT halves (`modClientBuild`, `modClientDeploy`, `gridClientMods`, `consentClientMod`, `trustAuthor`, `modClientArtifactBytes`). See [ck-exec](#ck-exec-dev-tier-preview). |
234
- | `client.playerCompute` | Player-authored SERVER/CLIENT Rust/WASM bound to player-owned grids: deploy source, activate/deactivate, list modules/versions, delete self-authored modules. |
235
- | `client.playerModel` | Player-owned flexible model containers and grid-confined automations (`containers`, `createContainer`, `setProperty`, `automations`, `createAutomation`, …). |
236
- | `client.playerWallet` | Player spend: balance, spend caps, card setup, policy, charges. |
237
- | `client.marketplace` | Player-code store/install/consent flows plus player-authorized grid claims (`claimGridOwnership`, `claimGridChunk`, `releaseClaimedGrid`) and client-mod artifact fetches. The grid-attached client mods (`gridClientMods`, `consentGridClientMod`, `trustGridAuthor`, `clientArtifact(Bytes)`) are superseded by ck-exec CLIENT halves and go in 18.0. |
231
+ | `client.exec` | **ck-exec (dev-tier preview):** an app's server code as hubs and spokes. `connect(appId, { nodeType, key })` opens a player's connection to an execution host; the `ExecConnection` it returns has `call`, `callRaw`, `subscribe`, `ping`, `onReconnect` and `close`, with MessagePack payloads, and it reconnects and renews subscriptions by itself. `starters` / `build` / `deploy` build and deploy an app (`manage_compute`); `logs`, `instances`, `versions`, `activateVersion` and `setEnabled` operate it; `mod*` are players' mods on grids they own, and `modClient*`, `gridClientMods`, `consentClientMod` and `trustAuthor` their CLIENT halves. See [ck-exec](#ck-exec-dev-tier-preview). |
232
+ | `client.playerWallet` | Player spend: balance, ledger, hourly charges, spend caps, card setup, auto-recharge. A ck-exec mod's compute is billed here, to its owner. |
233
+ | `client.marketplace` | Player-authorized grid claims (`claimGridOwnership`, `claimGridChunk`, `releaseClaimedGrid`, requests and invites) and studio moderation of player code (admission queue, listing administration, claim policy). Mods publish and install through `client.exec`. |
238
234
  | `client.crowdyStudio` | Cloud project, personal-library, and common-file APIs for Crowdy Studio: target-scoped files, metadata/module names, optimistic revisions, copy-by-value imports, atomic saves. |
239
235
  | `client.crowdyStudioGitHub` | Optional GitHub repository for a Crowdy Studio project: status, `bind` (push the project in, or take the repository), `unbind`, `refresh`, `layout`, `tree`, `getFile`, commit-guarded `putFile` / `deleteFile`. While bound the repository is the working tree and every Studio save commits; the project's `files` are the server's mirror at `github.sha`. Never required. |
240
236
  | `client.udp` | UDP proxy subscriptions + spatial mutations (`sendActorUpdate`, `sendVoxelUpdate`, `sendAudioPacket`, `sendVideoPacket` / `sendVideoFrame`, `sendTextPacket`, `sendClientEvent`, `sendSingleActorMessage`, `sendChannelMessage`). |
241
237
  | `client.realtime` | Connection status, manual `connect()` / `disconnect()`, `onStatus()` listener. |
242
238
  | `client.refreshGameplayToken()` | Safely rotates an active game client's app token (see [Token refresh](#token-refresh-during-gameplay)). |
243
239
  | `client.world(appId)` | Higher-level helpers for browser games (`actor.join`, `actor.sendState`, `actor.sendText`, `actor.sendToActor`). |
244
- | `client.kit(appId)` | Game Kit: ready-made mappings of game concepts onto the game model — see [Game Kit](#game-kit). |
240
+ | `client.kit(appId)` | Game Kit: parties, guilds and chat over teams and channels (`kit.social`) — see [Game Kit](#game-kit). |
245
241
  | `createWorldSession(client, appId, config)` | World Stores: opt-in, SDK-managed game state from the `@crowdedkingdoms/crowdyjs/stores` subpath — see [World Stores](#world-stores). |
246
242
 
247
243
  **Studio-admin surface** (privileged; drive with a server-side / studio token,
@@ -251,7 +247,7 @@ grouped under `client.admin` and mirrored at the top level):
251
247
  |---|---|
252
248
  | `client.organizations` | Orgs, members, RBAC roles, org API tokens. |
253
249
  | `client.apps` | App registry, discovery + routing (`create`, `routeFor`, `marketplace`), visibility, and player-code admission mode / allow-list administration. |
254
- | `client.appAccess` | Access tiers + per-user grants. |
250
+ | `client.appAccess` | Access tiers + per-user grants, and the feature keys a tier grants (`defineFeature`, `grantTierFeature`, `tierFeatures`, …), which a hub checks with the node API's `players.features`. |
255
251
  | `client.billing` | Org wallet + per-app spend budgets. |
256
252
  | `client.payments` | Payment checkouts (wallet top-ups, plan purchases). |
257
253
  | `client.quotas` | Usage quotas at the org/app scope. |
@@ -259,15 +255,13 @@ grouped under `client.admin` and mirrored at the top level):
259
255
  | `client.sharedEnvironment` | Publish to shared, runtime gating, spend caps, auto-billing. |
260
256
  | `client.gameApps` | App grids (`createGrid` / `deleteGrid`), first-class grid ownership (`ownership` / `assignOwnership` / `transferOwnership`), and grid runtime-permission administration. |
261
257
 
262
- **Operator surface** (platform operations; requires `is_operator`):
258
+ There is no operator surface: `client.operator` held only the legacy compute ceilings and
259
+ went with them in 18.0.0 (ck-exec code is bounded by its manifest limits within the
260
+ platform's), and infrastructure operations live in the separate infra-control-plane service.
263
261
 
264
- | Sub-client | What it does |
265
- |---|---|
266
- | `client.operator` | Platform compute ceilings (`computePlatformCeilings`, `setComputePlatformCeilings`). Infrastructure operations live in the separate infra-control-plane service, not this SDK. |
267
-
268
- Auth, user reads and the studio-admin / operator surfaces use the **identity
269
- session token**; the world/UDP surfaces require an **app-scoped token** for that
270
- app. Both go to the same endpoint.
262
+ Auth, user reads and the studio-admin surface use the **identity session token**; the
263
+ world/UDP surfaces require an **app-scoped token** for that app. Both go to the same
264
+ endpoint.
271
265
 
272
266
  CrowdyJS wraps the full public API surface — every
273
267
  non-deprecated public root field has a typed method, with Relay `*Connection`
@@ -485,16 +479,14 @@ pre-bound — convenient for browser games. Advanced callers can always use
485
479
 
486
480
  ## Grids: player code inside one grid
487
481
 
488
- A grid is a box of chunks a player can own. Everything an app-scoped Studio
489
- module can do, code running in a grid can do too, confined to that grid:
490
- spatial messages that originate in it, the grid's own channels, a grid event
491
- bus, sessions hosted in it, and the player-tier Game Model.
482
+ A grid is a box of chunks a player can own. Code running in a grid is confined
483
+ to it: spatial messages that originate in it, the grid's own channels, and a
484
+ grid event bus. Its server side is a ck-exec mod (`client.exec.mod*`).
492
485
 
493
486
  ```ts
494
487
  const plot = client.grid(appId, gridId);
495
488
  await plot.mintToken(); // learns the box; a grid-scoped token
496
489
  await plot.channels.create('plot-chat'); // a grid channel (owner only)
497
- await plot.sessions.create({ name: 'race' }); // a game within the game
498
490
  await plot.send.text({ chunk: { x: 4, y: 0, z: 0 }, uuid, text: 'hi', distance: 2 });
499
491
  plot.send.text({ chunk: { x: 9, y: 0, z: 0 }, uuid, text: 'x' }); // throws GridScopeError
500
492
  ```
@@ -512,11 +504,17 @@ import { hostGridProgram } from '@crowdedkingdoms/crowdyjs/grid-program';
512
504
  await hostGridProgram({ port, scope: client.grid(appId, gridId), graphqlUrl, graphqlWsUrl });
513
505
  ```
514
506
 
515
- `startGridMod` runs either a Rust CLIENT mod (WASM) or a JS grid program
516
- behind one interface; `createGridHostCalls` answers every CLIENT host call in
517
- the platform catalog through CrowdyJS for a mod's broker. A ck-exec mod's
518
- CLIENT half is `engine: 'ck-exec'`, and `ExecClientHalves` runs a whole grid's
519
- (see [A mod's CLIENT half](#a-mods-client-half)).
507
+ `startGridMod` runs either a mod's CLIENT half (WASM) or a JS grid program
508
+ behind one interface, and `ExecClientHalves` runs a whole grid's CLIENT halves
509
+ (see [A mod's CLIENT half](#a-mods-client-half)). `createGridHostCalls` answers
510
+ a CLIENT half's host calls through CrowdyJS confined to the grid. The ones only
511
+ the game can answer need its knowledge: `local.actorsInChunk` for
512
+ `actors_list*`, `local.avatarChunk` (where an avatar's live actor is) for
513
+ `avatar_state_get`, `local.gridPermissionKeys` with the visiting player's
514
+ `userId` for `grid_permission_check`, and `local.drainPointerClicks` for
515
+ `pointer_clicks`; without its hook such a call is refused as not offered. The
516
+ Game Model, sessions and grid state calls went with the legacy engines in
517
+ 18.0.0: the broker refuses them.
520
518
 
521
519
  ## World Stores
522
520
 
@@ -573,8 +571,8 @@ The available stores are `self` (your actor + send loop), `actors` (remote
573
571
  actor registry with lanes/history/staleness), `errors` (attributed send
574
572
  errors), `chunks` (chunk/voxel cache with realtime merge + worldgen
575
573
  write-back), `channelInbox` / `actorInbox` (message inboxes), `events` (typed
576
- event router), `host` (host tracking), `save` / `avatar` (typed durable
577
- state), and `model` (game-model container mirror).
574
+ event router), `host` (host tracking), and `save` / `avatar` (typed durable
575
+ state).
578
576
 
579
577
  Every store is **opt-in twice over**: only configured stores are constructed
580
578
  (and only they exist on the session's TYPE — `session.host` without
@@ -588,101 +586,25 @@ keep timer-driven sends at full rate while hidden. See the
588
586
 
589
587
  ## Game Kit
590
588
 
591
- `client.kit(appId)` maps traditional game concepts onto the abstract game
592
- model + automations API. Studios **deploy blueprints** (the admin "load the
593
- state/rules" step, requires `manage_apps`); game clients then use the typed
594
- runtime helpers. Everything composes `client.gameModel` — no new server
595
- surface.
596
-
597
- ```ts
598
- // Studio setup (admin context):
599
- import { inventoryBlueprint, lockBlueprint, npcBlueprint } from '@crowdedkingdoms/crowdyjs';
600
-
601
- await admin.kit(appId).deploy([
602
- inventoryBlueprint(),
603
- lockBlueprint({ objectTypeName: 'Door', authority: { kind: 'key' } }),
604
- npcBlueprint({
605
- behaviors: [{
606
- name: 'npc-wander',
607
- role: 'wanderer',
608
- trigger: { intervalMs: 60000 },
609
- mutations: [
610
- { target: 'self', property: 'x', expression: 'self.x + rand_int(-2, 2)' },
611
- { target: 'self', property: 'z', expression: 'self.z + rand_int(-2, 2)' },
612
- ],
613
- }],
614
- }),
615
- ]);
616
-
617
- // Game client (player token):
618
- const kit = game.kit(appId);
619
- const bag = await kit.inventory.ensure(me.userId);
620
- const result = await kit.objects.open(doorId, { keyId });
621
- if (!result.success) console.warn('locked:', result.errorMessage);
622
- ```
623
-
624
- Land sale closes the permission loop end to end:
589
+ `client.kit(appId).social` gives parties, guilds and chat rooms in familiar
590
+ words over teams (membership and roles) and channels (messaging), with
591
+ realtime delivery on the UDP notification subscription:
625
592
 
626
593
  ```ts
627
- // Studio: sell a plot over a grid; doors on it honor the purchase automatically.
628
- await admin.kit(appId).deploy([
629
- plotBlueprint({ rentable: true }),
630
- lockBlueprint({ objectTypeName: 'PlotDoor',
631
- authority: { kind: 'chunkPermission', key: 'access', mode: 'smallest' } }),
632
- ]);
633
-
634
- // Game client: buying spends gold AND grants enforced grid access atomically.
635
- const buy = await kit.plots.buy(plotId, walletId);
636
- if (buy.success) await kit.objects.open(doorId); // has_chunk_permission passes now
594
+ const kit = game.kit(appId, { social: { actorUuid: me.uuid } });
595
+ const party = await kit.social.party.create('raid'); // team + paired channel
596
+ const room = await kit.social.chat.room('lobby');
597
+ kit.social.chat.onMessage(room.groupId, (m) => log(m.senderUuid, m.text));
637
598
  ```
638
599
 
639
- NPC blueprints can target by permissions too — e.g. a guard automation whose
640
- selector has `candidatePermissionWhere: [{ userFrom: { property: 'owner_user_id' },
641
- op: 'lacks', key: 'access', grid: { property: 'grid_id' } }]` reacts only to
642
- intruders.
643
-
644
- The kit covers the common genre staples end to end — each layer is a blueprint
645
- builder plus a typed runtime helper:
646
-
647
- | Layer | Builder → helper | Highlights |
648
- | --- | --- | --- |
649
- | Inventory | `inventoryBlueprint` → `kit.inventory` | bags/stacks, grant/consume/transfer, craft, barter |
650
- | Objects | `lockBlueprint` → `kit.objects` | lockable doors/chests with key or permission authority |
651
- | NPCs | `npcBlueprint` → `kit.npcs` | automation-driven NPC instances (spawn, runNow, enable) |
652
- | Plots | `plotBlueprint` → `kit.plots` | buy/rent land with transactional, replication-enforced grid grants |
653
- | Economy | `economyBlueprint` → `kit.economy` | multi-currency wallets, atomic shop buys, escrow trades, player market, escrowed order book (`kit.economy.orderBook`) |
654
- | Progression | `progressionBlueprint` → `kit.progression` | xp/levels via the `fn:` curve helper, skill prerequisite chains, achievements, host-gated rating |
655
- | Loot | `lootBlueprint` → `kit.loot` | weighted tables unrolled into seed-driven expressions, atomic single-claim, event-triggered drops |
656
- | Quests | `questsBlueprint` → `kit.quests` | event-automation progress, atomic claim into stack+wallet, cron daily resets, tutorial sequencing |
657
- | Combat | `combatBlueprint` → `kit.combat` | server-side damage/death, status-effect tick automation, `turnBased`/`hostSynced`, routed attacks |
658
- | Matches | `matchesBlueprint` → `kit.matches` | session lobbies/rounds/turns/scores, per-match channel + `onMatchChanged` (notify-to-pull) |
659
- | Decks | `decksBlueprint` → `kit.decks` | hidden hands via owner-visibility `card_id`, shuffle-by-position automation |
660
- | World sim | `worldsimBlueprint` → `kit.worldsim` | day/night clock with spatial notify, node regen + atomic gather, crops, wave counters, forecasts |
661
- | Social | `guildBlueprint` → `kit.social` | parties/guilds/chat over teams+channels, grid territory grants, guild hall + bank composite |
662
- | Leaderboards | `leaderboardsBlueprint` → `kit.leaderboards` | trusted keep-best submits, client-side ranking, cron seasons |
663
- | Live ops | `liveopsBlueprint` → `kit.liveops` | timed event windows and seasons |
664
- | Moderation | `moderationBlueprint` → `kit.moderation` | reports, queues, mutes |
665
- | Telemetry | `telemetryBlueprint` → `kit.telemetry` | counters and lightweight event tracking |
666
- | Monetization | `featureGate` → `kit.features` | feature keys, tier grants, `*policyExtra` gating on builders |
667
- | Abilities | — → `kit.abilities` | ability definitions, casts, loadouts |
668
- | Movement | — → `kit.movement` | movement warden configs + violation parsing |
669
- | Territory | — → `kit.territory` | control points, factions, enrollment |
670
- | Racing | — → `kit.racing` | courses, entries, possession (claim/pass/shoot) |
671
-
672
- Engine-aware layers talk to compute-module game engines when they are
673
- deployed, and degrade gracefully on model-only apps via capability detection
674
- (`kit.engines`): `kit.mobs` (refereed attacks, defs/slots, contact-damage
675
- parsing), `kit.pets` (adopt/summon/dismiss/rename), `kit.instances` (private
676
- world slices, seeded runs), `kit.director` (encounter runs),
677
- `kit.matchmaking` (queues/proposals/rating), `kit.minigames` (invoke-loop
678
- wrapper), plus engine paths on `kit.matches` / `kit.decks` /
679
- `kit.leaderboards` and the `kit/wire` pose codec + event parsers. Deploy
680
- engines alongside blueprints with `kit.deploy(blueprints, { engines })`.
681
-
682
- See the docs guides [Modeling game concepts](https://docs.crowdedkingdoms.com/game-api/modeling-game-concepts)
683
- (the underlying model + genre map) and [Game Kit](https://docs.crowdedkingdoms.com/crowdyjs/game-kit)
684
- (the SDK surface + the simulation-tier / notify-to-pull / timer / hidden-info
685
- / anti-cheat patterns).
600
+ Game rules and state are ck-exec hubs (`client.exec`, below). Two kit pieces
601
+ stand alone: the wire codecs (`encodeEnginePose` / `decodeEnginePose`, the
602
+ 48-byte engine pose, `engineLanes`, and `parseEngineEvent` with the typed
603
+ parsers for server events 77 and 90-98) for games whose hubs keep that wire,
604
+ and `runOptimisticAction`, which applies an action locally, asks a referee
605
+ (a hub endpoint, say) and rolls back on a denial. The blueprints,
606
+ `kit.deploy`, the engines and the model-backed helpers went with the game
607
+ model in 18.0.0; see [MIGRATION.md](MIGRATION.md).
686
608
 
687
609
  ## ck-exec (dev-tier preview)
688
610
 
@@ -742,7 +664,8 @@ Integers above 2^53 decode as `number` and lose precision unless you pass
742
664
  A mod (a player's code on a grid they own: `modBuild`, `modDeploy`) can carry a **CLIENT
743
665
  half** (17.14.0): browser WASM from one `crowdy-client-sdk` crate, which the mod's grid serves
744
666
  to visitors who consent to it or trust its author. It runs in the visitor's
745
- `PlayerCodeBroker`, sandboxed like a legacy CLIENT module.
667
+ `PlayerCodeBroker`, in a worker with no DOM, token or network, and it is the only kind of
668
+ player module the broker runs since 18.0.0.
746
669
 
747
670
  ```ts
748
671
  // The mod's owner builds one crowdy-client-sdk crate and attaches it to the mod.
@@ -770,24 +693,30 @@ const halves = new ExecClientHalves({
770
693
  workerUrl, // the platform glue worker, same origin
771
694
  onHostCall: (call) => hostCalls(call), // e.g. createGridHostCalls({ scope, client })
772
695
  onPresentation: (p, mod) => hud.set({ source: mod.modId, label: mod.name, payload: p.payload }),
696
+ onLog: (line, mod) => devConsole.append(mod.name, line.level, line.message), // text, never HTML
773
697
  confirm: (prompt) => window.confirm(describe(prompt)), // once per author; ask: 'mod' for each
774
698
  onStopped: (mod) => hud.remove(mod.modId),
775
699
  });
776
700
  halves.enterGrid({ gridId, low, high }); // the grid the player stands in; null to leave
777
701
  setInterval(() => void halves.refresh().catch(console.warn), 10_000);
702
+
703
+ // The page calls a running CLIENT half's handle_invoke; the reply is the module's bytes.
704
+ const reply = await halves.invoke(modId, new TextEncoder().encode('{"ask":"score"}'));
778
705
  ```
779
706
 
780
707
  Each refresh stops the CLIENT halves whose mod is gone or whose digest, capability hash or
781
- tick interval changed, asks about the rest, and starts the consented ones in a broker with
782
- `engine: 'ck-exec'`. That engine allows exactly the host calls crowdy-client-sdk makes
783
- (`EXEC_CLIENT_HOST_CALLS`: no Game Model, sessions or `grid_state_*`), offers exactly the CLIENT
784
- ABI imports (`EXEC_CLIENT_ABI_IMPORTS`) and runs a module only with its digest, its fuel budget
785
- and `consentedHostCalls`, the host calls of the summary the player consented to: a call outside
786
- them is refused, even one whose name the module assembled at run time.
787
- `NOT_FOUND` holds a CLIENT half back 15 s and `RATE_LIMITED` 60 s. The grid's owner is asked
788
- about their own CLIENT halves like anyone; answer yes in `confirm` when `prompt.authorId` is
789
- the player. The legacy grid-attached client mods (`marketplace.gridClientMods` and the rest)
790
- keep working until 18.0.
708
+ tick interval changed, asks about the rest, and starts the consented ones in a broker. The
709
+ broker allows at most the host calls crowdy-client-sdk makes (`EXEC_CLIENT_HOST_CALLS`: no Game
710
+ Model, sessions or `grid_state_*`), offers exactly the CLIENT ABI imports
711
+ (`EXEC_CLIENT_ABI_IMPORTS`) and runs a module only with its digest, its fuel budget and
712
+ `consentedHostCalls`, the host calls of the summary the player consented to: a call outside them
713
+ is refused, even one whose name the module assembled at run time. A CLIENT half's
714
+ `crowdy::log` lines reach `onLog` at most 20 a second and 1,000 characters each (then a `warn`
715
+ counts what was dropped); `invoke` sends at most 256 KiB each way and is refused while the
716
+ module is not running. `NOT_FOUND` holds a CLIENT half back 15 s and `RATE_LIMITED` 60 s. The
717
+ grid's owner is asked about their own CLIENT halves like anyone; answer yes in `confirm` when
718
+ `prompt.authorId` is the player. See
719
+ [CLIENT halves](https://docs.dev.crowdedkingdoms.com/exec/client-halves).
791
720
 
792
721
  ## Hosting a game on Crowdy Games
793
722
 
@@ -827,28 +756,32 @@ Crowdy Studio is the in-game SERVER/CLIENT Rust authoring surface for player
827
756
  code: cloud projects with target-scoped files, optimistic-concurrency
828
757
  autosave, draft/live/stop orchestration, and a Monaco editor backed by a local
829
758
  Rust language worker. The worker receives source files and the embedded
830
- platform index only — never a credential and never a server connection.
831
- Compiled CLIENT artifacts run through `PlayerCodeBroker`, which keeps tokens
832
- on the page, allow-lists host calls, and locally clamps chunk-targeted effects
833
- to the owned grid before the normal SDK path reaches server authorization.
834
- The host only ticks a CLIENT mod when `tickIntervalMs` is set (omit or `0`
835
- is invoke-only):
759
+ platform index (the `ckx-sdk` and `crowdy-client-sdk` symbols) only — never a
760
+ credential and never a server connection. A CLIENT half runs through
761
+ `PlayerCodeBroker`, which keeps tokens on the page, allow-lists host calls
762
+ (narrowed to what the player consented to), and locally clamps chunk-targeted
763
+ effects to the owned grid before the normal SDK path reaches server
764
+ authorization. It takes what the platform served with the module, and ticks it
765
+ only when `tickIntervalMs` is set (omit or `0` is invoke-only):
836
766
 
837
767
  ```ts
838
768
  import { PlayerCodeBroker } from '@crowdedkingdoms/crowdyjs';
839
769
 
770
+ const half = await client.exec.modClientArtifactBytes(appId, modId);
840
771
  const broker = new PlayerCodeBroker({
841
772
  workerUrl,
842
773
  grid,
843
774
  onHostCall,
844
- tickIntervalMs: 1000, // required for on_tick; omit for invoke-only
775
+ moduleName: half.name,
776
+ artifactHash: half.digest,
777
+ fuelPerDispatch: half.fuelPerDispatch,
778
+ consentedHostCalls: half.capabilitySummary.hostFunctions,
779
+ tickIntervalMs: half.tickIntervalMs, // omit for invoke-only
780
+ onLog: (line) => console.log(`[${line.moduleName}] ${line.level}: ${line.message}`),
845
781
  });
846
- await broker.start(artifactBytes);
782
+ await broker.start(half.bytes);
847
783
  ```
848
784
 
849
- The Studio embed defaults `clientTickIntervalMs` to `1000` when you do not
850
- pass one; a raw `PlayerCodeBroker` does not.
851
-
852
785
  Most games embed the ready-made shell rather than hand-rolling window chrome
853
786
  around `mountCrowdyStudio`:
854
787
 
@@ -859,7 +792,7 @@ import { createCrowdyStudioEmbed } from '@crowdedkingdoms/crowdyjs/crowdy-studio
859
792
  import workerUrl from '@crowdedkingdoms/crowdyjs/player-glue-worker?worker&url';
860
793
 
861
794
  const studio = createCrowdyStudioEmbed({
862
- client: game, // CrowdyClient: crowdyStudio, exec, playerCompute, playerWallet, crowdyStudioGitHub
795
+ client: game, // CrowdyClient: crowdyStudio, exec, playerWallet, crowdyStudioGitHub
863
796
  appId,
864
797
  gameName: 'My Game',
865
798
  suppressGameplayInput: () => pauseInput(),
@@ -882,29 +815,27 @@ fullscreen modal on narrow screens. For custom chrome, call
882
815
  `new CrowdyStudioController(options)`. New games should start SERVER-only.
883
816
  Untrusted HUD payloads always render as text, never HTML.
884
817
 
885
- **The SERVER target runs as a ck-exec mod.** The embed's `serverEngine` defaults to
886
- `'ck-exec'` when the client has `exec` (a `CrowdyClient` always does): a new project's
887
- SERVER target starts from the platform's mod starter (`client.exec.modStarter(appId)`, a
888
- `ckx-sdk` crate), Test draft and Deploy live build it with `modBuild` and deploy it to the
889
- grid as the mod `mod:<server module name>`, Invoke calls one of its endpoints (`state` by
890
- default) over an exec connection, and Logs shows its `ctx.log` lines.
818
+ **The SERVER target runs as a ck-exec mod.** A new project's SERVER target starts from
819
+ the platform's mod starter (`client.exec.modStarter(appId)`, a `ckx-sdk` crate), Test draft
820
+ and Deploy live build it with `modBuild` and deploy it to the grid as the mod
821
+ `mod:<server module name>`, Invoke calls one of its endpoints (`state` by default) over an
822
+ exec connection, and Logs shows its `ctx.log` lines.
891
823
 
892
824
  **The CLIENT target is that mod's CLIENT half** (17.14.0). A new CLIENT target starts from a
893
825
  `crowdy-client-sdk` crate; Test draft and Deploy live build it with `modClientBuild`, attach
894
826
  it to the project's mod with `modClientDeploy`, consent to it as its author (the API serves a
895
827
  CLIENT half only to players who consented, its author too) and preview the served module in
896
- the HUD layer. A CLIENT-only project's CLIENT half rides the mod named for its CLIENT module:
828
+ the HUD layer; the preview's `crowdy::log` lines show in Logs beside the mod's own. A
829
+ CLIENT-only project's CLIENT half rides the mod named for its CLIENT module:
897
830
  when the player has no mod of that name on the grid, Studio deploys the mod starter's server
898
831
  half under it first and says so in the build log, and Stop switches that mod off. The
899
- preview loads only while the player stands in the grid with `run_client_code`. A CLIENT crate
900
- still on the legacy `crowdy-compute-sdk` is refused with what to change.
901
-
902
- `mountCrowdyStudio` and the controller take the same `serverEngine` with
903
- `mods: client.exec`; without `mods` they stay on legacy player compute, and
904
- `serverEngine: 'player-compute'` keeps it explicitly for both targets. The platform is
905
- switching legacy player compute off, so that option lasts only until 18.0 removes it.
832
+ preview loads only while the player stands in the grid with `run_client_code`, and saving a
833
+ CLIENT project needs ck-api `v2.25.1` or later. A CLIENT crate still on the legacy
834
+ `crowdy-compute-sdk` is refused with what to change. The embed takes `exec` from the client;
835
+ `mountCrowdyStudio` and the controller take `mods: client.exec`. Crowdy Studio runs nothing
836
+ on legacy player compute since 18.0.0.
906
837
 
907
- See [Crowdy Studio & player client mods](https://docs.crowdedkingdoms.com/crowdyjs/player-client-mods)
838
+ See [CLIENT halves](https://docs.dev.crowdedkingdoms.com/exec/client-halves), [mods](https://docs.dev.crowdedkingdoms.com/exec/mods)
908
839
  and [Embed Crowdy Studio in your game](https://docs.crowdedkingdoms.com/crowdyjs/crowdy-studio-embed).
909
840
 
910
841
  ### The Studio agent (DeepSeek Harness in the browser)
@@ -43,7 +43,6 @@ import { PaymentsAPI } from './domains/payments.js';
43
43
  import { QuotasAPI } from './domains/quotas.js';
44
44
  import { UsageAPI } from './domains/usage.js';
45
45
  import { SharedEnvironmentAPI } from './domains/sharedEnvironment.js';
46
- import { ControlPlaneAPI } from './domains/controlPlane.js';
47
46
  import { AdminAPI } from './domains/admin.js';
48
47
  import { ChunksAPI } from './domains/chunks.js';
49
48
  import { AvatarsAPI } from './domains/avatars.js';
@@ -59,15 +58,11 @@ import { GridsAPI } from './domains/grids.js';
59
58
  import { GridScope, type GridBox } from './grid-scope.js';
60
59
  import { TeamsAPI } from './domains/teams.js';
61
60
  import { UdpAPI } from './domains/udp.js';
62
- import { GameModelAPI } from './domains/gameModel.js';
63
- import { ComputeAPI } from './domains/compute.js';
64
61
  import { ExecAPI } from './domains/exec.js';
65
- import { PlayerComputeAPI } from './domains/playerCompute.js';
66
62
  import { CrowdyStudioAPI } from './domains/crowdyStudio.js';
67
63
  import { CrowdyStudioGitHubTransport } from './crowdy-studio/github/transport.js';
68
64
  import { PlayerWalletAPI } from './domains/playerWallet.js';
69
65
  import { MarketplaceAPI } from './domains/marketplace.js';
70
- import { PlayerModelAPI } from './domains/playerModel.js';
71
66
  import { DiscoveryDomain } from './domains/discovery.js';
72
67
  export interface CrowdyClientConfig {
73
68
  /**
@@ -258,8 +253,6 @@ export declare class CrowdyClient {
258
253
  readonly usage: UsageAPI;
259
254
  /** Shared-environment publishing, runtime gating, auto-billing (studio admin). */
260
255
  readonly sharedEnvironment: SharedEnvironmentAPI;
261
- /** Operator (control-plane) surface — requires `is_operator`. */
262
- readonly operator: ControlPlaneAPI;
263
256
  /**
264
257
  * Studio-admin facade grouping the privileged management-surface sub-clients
265
258
  * (`organizations`, `appAccess`, `billing`, `payments`, `quotas`,
@@ -286,24 +279,19 @@ export declare class CrowdyClient {
286
279
  readonly teams: TeamsAPI;
287
280
  /** UDP proxy: spatial sends + the shared realtime notification subscription. */
288
281
  readonly udp: UdpAPI;
289
- /** Abstract game model: containers, properties, functions, sessions. */
290
- readonly gameModel: GameModelAPI;
291
- /** Compute Modules: server-side Rust/WASM logic (manage, invoke, observe). */
292
- readonly compute: ComputeAPI;
293
- /** ck-exec (dev-tier preview): connect players to an app's hubs and spokes; deploy them. */
282
+ /**
283
+ * ck-exec: an app's server code as hubs and spokes (connect, call, subscribe, build,
284
+ * deploy, operate) and players' mods on the grids they own.
285
+ */
294
286
  readonly exec: ExecAPI;
295
- /** Player-authored Rust/WASM bound to player-owned grids. */
296
- readonly playerCompute: PlayerComputeAPI;
297
287
  /** Crowdy Studio cloud projects, libraries, and common source files. */
298
288
  readonly crowdyStudio: CrowdyStudioAPI;
299
289
  /** GitHub repository loop for Crowdy Studio projects (same session; the API resolves the repo from the bind). */
300
290
  readonly crowdyStudioGitHub: CrowdyStudioGitHubTransport;
301
- /** P4a marketplace (free mode): store, installs, consent, claim flows. */
291
+ /** Grid claim flows and the app's player-code administration. */
302
292
  readonly marketplace: MarketplaceAPI;
303
293
  /** Player wallet, spend caps, hourly usage charges, and player policy (P2). */
304
294
  readonly playerWallet: PlayerWalletAPI;
305
- /** Player-owned flexible model data and grid-confined automations. */
306
- readonly playerModel: PlayerModelAPI;
307
295
  /** Durable avatars + per-app avatar state (owner-aware reads). */
308
296
  readonly avatars: AvatarsAPI;
309
297
  /** Game-host election + actor liveness heartbeat. */
@@ -361,27 +349,20 @@ export declare class CrowdyClient {
361
349
  */
362
350
  world(appId: string): WorldClient;
363
351
  /**
364
- * One grid, bound once: its channels, sessions, player-tier model, player
365
- * compute and origin-checked replication, all with the app and grid filled
366
- * in (DN-10: grid scope is app scope intersected with grid confinement).
367
- * Pass the box if you know it; otherwise `mintToken()` learns it.
352
+ * One grid, bound once: its channels and origin-checked replication, with the
353
+ * app and grid filled in (DN-10: grid scope is app scope intersected with grid
354
+ * confinement). Pass the box if you know it; otherwise `mintToken()` learns it.
368
355
  *
369
356
  * @param appId - The app (BigInt as a decimal string).
370
357
  * @param gridId - The grid (BigInt as a decimal string).
371
358
  */
372
359
  grid(appId: string, gridId: string, box?: GridBox): GridScope;
373
360
  /**
374
- * App-scoped **Game Kit** facade over `client.gameModel`: high-level
375
- * building blocks that map traditional game concepts onto Game Models +
376
- * Automations — `kit.inventory` (bags/item stacks), `kit.objects` (lockable
377
- * doors/chests with custom permissions), `kit.npcs` (server-driven NPCs),
378
- * and the studio-side `kit.deploy(blueprints)` that loads the matching
379
- * rules/state into the app (requires `manage_apps`). See
380
- * {@link GameKitClient} and the "CrowdyJS → Game Kit" docs guide.
361
+ * App-scoped **Game Kit**: parties, guilds and chat rooms over teams and channels
362
+ * (`kit.social`). See {@link GameKitClient}.
381
363
  *
382
- * @param appId - The app to scope model calls to (BigInt as a decimal string).
383
- * @param options - Optional per-helper config when your blueprints use
384
- * non-default type names/prefixes.
364
+ * @param appId - The app (BigInt as a decimal string).
365
+ * @param options - Optional name prefixes and the chat sender's actor uuid.
385
366
  */
386
367
  kit(appId: string, options?: GameKitOptions): GameKitClient;
387
368
  /** Closes the WebSocket and clears the in-memory auth token. */