Files
2026-10-24 01:16:49 -04:00

7.6 KiB

studio

The RecFlare Studio host (https://studio.<domain>).

Device login stays on Auth, GET /account/me stays on Accounts, and the approval page is WWW /device. This worker queues cloud builds, accepts completed bundles, and serves build status and co-owner presence. Rooms exposes playable bundles in CurrentSave.UnitySubAssets; their bytes are served by the CDN at /room/{filename}. The Rooms GET /rooms/{roomId}/subrooms/{subRoomId}/unityasset route separately returns the editable source manifest and available build metadata.

Method Path Purpose
GET /cloud-builds/for-room Cloud builds for that room and subroom, newest first (results, totalResults). Query: roomId, subRoomId, skip, take. A bad query is an empty page.
GET /cloud-builds/get-build-count-for-user Authenticated user's Studio build totals for the current UTC-hour rate-limit window.
POST /cloud-builds/from-editor Multipart Windows bundle (windows) and Android bundle (android), optional windowsStripped and androidStripped. Stores a finished build on the subroom's current published save and sets BecameRRStudioRoomAt the first time. Bearer required, and the token must include betastudio. Caller must be the creator or a co-owner.
GET /collaboration/owners-in-room Account ids of the room's co-owners (creator, or a Creator/CoOwner role) whose live presence is in that roomId and subRoomId. Body: { success: true, error: null, value: number[] }. Bearer required.

Development

Run in dev mode

pnpm dev

Run tests

pnpm test

Deploy

pnpm turbo deploy

Migrate

This worker owns studio_cloud_build on the shared recflare database (migrations/, tracked in its own d1_migrations_studio table). The bundles themselves are rows of the rooms worker's unity_asset (one per platform and kind: target 0 Windows / 2 Android, studio/<roomId>/<name>.assetbundle as filename — the bytes sit at room/<filename> in the bucket, the prefix the client adds — base64 SHA-256 as hash), so a stored build needs the rooms migrations too. Deploying does not apply either.

just migrate -F studio             # remote
just migrate -F studio -- --local  # dev db

Launcher template distribution

Set STUDIO_DISTRIBUTION_MANIFEST to an R2 catalog key to enable the optional PatchKit-compatible /1/apps/:secret/* routes. The catalog and ZIP parts are generated by studio-patch-2026/build_distribution.py; upload all parts through the existing CDN before publishing the catalog. No template bytes or operator configuration belong in this repository.

The catalog names the template application's SHA-256 identifier, latest release, HTTPS multipart content URL, file hashes, and download-chunk hashes. Optional legacy summaries supply comparison hashes without making old templates downloadable. The application identifier scopes requests; it is not an access credential. Missing or disabled catalogs return 404. Invalid catalogs or catalogs larger than 8 MiB return 503; responses use Cache-Control: no-store so a corrected publication can be retried immediately.

Editor build limits

GET /cloud-builds/get-rate-limit-config returns the editor's CloudBuildRateLimitConfigDTO directly: buildThrottleIntervalHours (1), warnAfterBuildsPerInterval (90), and maxBuildsPerInterval (100). These names matter: unknown keys leave the DTO's maximum at zero and block even a first build. The authenticated get-build-count-for-user route provides the user's counts.

Queued Studio builds

POST /cloud-builds/create accepts the SDK's room, subroom, save, auto-publish, and optional target fields. It requires Studio authorization and room management rights, validates the uploaded source manifest, and returns a numeric string build ID with a null completion time. Repeated requests for an in-progress save reuse its job. GET /cloud-builds?cloudBuildId=... reads the status; PUT /cloud-builds/cancel cancels a queued or running job.

Apply migration 0003_studio_cloud_build_job.sql. Create the private CLOUD_BUILD_KEY in the shared Secrets Store (the one JWT_SECRET lives in — see .env.example) and run the outbound worker from recflare/cloud-building with the same value as its STUDIO_WORKER_KEY. The binding must exist for the worker to deploy; a value of off disables cloud building, and creation then returns an explicit unavailable response. CLOUD_BUILD_TARGETS defaults to 0,2 (Windows and Android), and CLOUD_BUILD_TEMPLATE_VERSION defaults to 169 — the cloud-building worker claims only jobs for its own configured template version (171 by default), so set this to match or jobs queue and are never claimed. Match installed editor modules to the enabled targets.

The private /internal/cloud-builds/claim, /:id/heartbeat, and /:id/finish routes lease jobs to that worker. Only validated UnityFS artifacts for the allocated asset IDs and requested platforms are accepted. SDK bundle version 5 is retained. Completion links the submitted save; auto-publish does not replace a newer draft. Failed, cancelled, or expired jobs never become successful builds. Claims include a signed, short-lived SDK validation token with no account subject or roles. Bulk component-text validation and job-scoped grant reads accept this credential. It cannot authenticate as an account or publish a room.

Avatar Studio and consumable validation

Avatar authoring uses per-account Studio grants, source revisions, and the managed cloud queue. Apply migrations/0004_avatar_studio.sql to the shared database before enabling these routes. The API owns creator saves and explicit publication; the Studio service queues prefab builds and returns per-platform main/stripped bundles at version 5 and material bundles at version 6. Image badges publish directly. Changed body/configuration inputs receive distinct output IDs, and automatic publication cannot replace a newer revision. Deploy the paired cloud-building worker for prefab support; restricted validation credentials grant no account role.

The SDK's access override reads the target account's entitlement. Build-validation credentials can inspect only the current owners of their active job's room; peers can inspect grants only while they currently manage the same room.