[studio] beta studio (#114)

* rrs stuff

* studio service yay

* rrs whitelist

* moree studiooooooo fellowwww

* rec room studio room loading yay

* fixes yay

* fix 2 because idk  yayuh

* Update cdn.app.ts

* ccontent length fix?

* Preserve content-length and upgrade metadata

Return a real zero-filled byte array for CDN HEAD responses so the runtime preserves Content-Length while still sending no payload. In notify, re-create the Request with its original headers, set OWNER_HEADER from the validated token, and forward that Request to hub.fetch to avoid losing WebSocket upgrade metadata (which could trigger 500s in Durable Objects). These changes ensure the editor's size checks and WebSocket upgrades remain reliable.

* fix x524234

* shirt thing?

* [auth] remove grant table as we already have audit_log for now

* rename table to generic device_grant

* cleanup/lint

---------

Co-authored-by: Devin Zuczek <devin.zuczek@gmail.com>
This commit is contained in:
Crasho
2026-10-05 19:39:22 +01:00
committed by GitHub
parent 0900bcac25
commit 26270e9c25
52 changed files with 18231 additions and 103 deletions
+25
View File
@@ -27,9 +27,11 @@ import {
usernamesFor,
where,
} from './api'
import { DeviceLinkPage } from './DeviceLink'
import { customAvatarItemIdFromPath, ItemPage } from './Item'
import { ModerationPage } from './Moderation'
import { StatsPage } from './Stats'
import { StudioAccessPage } from './StudioAccess'
import type { ReactNode } from 'react'
import type { Hosts } from './api'
@@ -1598,6 +1600,10 @@ export function App() {
navigate={navigate}
onAuthed={setAccount}
/>
) : path === '/device' ? (
// Studio opens this from verification_uri_complete. The code was minted by
// auth; this page only approves it with the website session.
<DeviceLinkPage account={account} search={search} navigate={navigate} />
) : path === '/account' ? (
<AccountPage account={account} config={config} navigate={navigate} onChange={setAccount} />
) : path === '/claim' ? (
@@ -1615,6 +1621,12 @@ export function App() {
// on any of them falls through to the SPA shell; the page then gates itself on
// the token's role, and every endpoint behind it re-checks.
<ModerationPage account={account} path={path} search={search} navigate={navigate} />
) : path === '/settings/recroomstudio' || path === '/settings/recroomstudio/' ? (
// The URL Studio already opens from the "not authorized to upload" dialog.
// A client-side route like /moderation: not in run_worker_first, so a cold
// load falls through to the SPA shell. The page shows one account's own
// status to whoever is signed in, and the whitelist editor only to staff.
<StudioAccessPage account={account} navigate={navigate} />
) : path === '/stats' ? (
// Unlinked on purpose — nothing in the nav or footer points here; it's for whoever
// is handed the URL. Public all the same, and a client-side route like the rest:
@@ -1706,6 +1718,19 @@ function NavBar({
Moderation
</Link>
)}
{isAdmin() && (
<Link
to="/settings/recroomstudio"
navigate={navigate}
className={
path === '/settings/recroomstudio' || path === '/settings/recroomstudio/'
? 'active'
: ''
}
>
Studio access
</Link>
)}
<Link to="/account" navigate={navigate} className={path === '/account' ? 'active' : ''}>
My account
</Link>