fix(server): materialize cloud providers before the first workspace exists - #3625
fix(server): materialize cloud providers before the first workspace exists#3625benjaminshafii wants to merge 7 commits into
Conversation
…xists Cloud provider sync threw workspace_missing when a Den session landed before any workspace was created (fresh sign-in on a clean profile). Materialize providers and credentials globally right away and defer the engine runtime-config write + reload until the first workspace appears. Also drop the stale sharp .d.ts path mapping in den-api's tsconfig: it pointed at a path removed in sharp 0.35, which crashed tsx-run Den API boots that resolve tsconfig paths at runtime. Adds a server regression test and an app-driving testkit spec that signs in before any workspace exists, proves sync succeeds, then creates the first workspace and proves the managed model is selectable without a restart.
Daytona now mints a fresh preview hostname on every preview-url call, so origins baked into DEN_BETTER_AUTH_TRUSTED_ORIGINS at boot go stale immediately and the testkit's Den seed proof fails with INVALID_ORIGIN. Trust the preview proxy domain by wildcard; local hosts are unaffected.
…nstalls esbuild 0.28.1 (pinned repo-wide in #3588) refuses to lower plain destructuring for browser-name target lists, which are exactly Vite's optimizeDeps defaults — so every fresh install since the pin boots a dev server that dies with ~3000 esbuild errors and a blank renderer. Stale node_modules kept older 0.25.x binaries, which is why local checkouts still worked while every Daytona sandbox failed its Vite prewarm gate. 0.25.12 keeps the >=0.25.0 dev-server CORS fix that motivated the pin.
…t workspace On the welcome route with zero workspaces the renderer never pushes its Den session to the local server, so the spec now performs the same PUT /den-session the desktop runtime does and asserts the sync run directly: pre-fix it returns failed/workspace_missing, post-fix applied|noop.
location.reload() detached the CDP session and every later evaluate timed out. The server already emits onWorkspacesChanged, so re-navigate to the session route in a bounded loop until the composer appears.
An API-seeded workspace is a state the product never produces (no engine, no model catalog) and the session route never becomes the task UI. After sign-in the paved createAndSelectWorkspace path drives organization onboarding and the app's own workspace.create action.
A long pnpm install streaming progress over a single daytona exec session was observed wedging past every local timeout, leaving the install gate stuck for 40+ minutes on a sandbox whose install had already finished. Run the install detached with its output in a file and poll a childless exit sentinel instead — the same shape as the first-boot and Vite prewarm gates.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Photo roll — managed-models-survive-sign-in-before-the-first-workspace-exists — 0/0 frames passed · 4 facts✅ 0/0 frames passed · 4 facts · 4 expectations passed · 0 failed ℹ️ FACT — 1. A sync with zero workspaces no longer fails with workspace_missingRun result: {"status":"noop"}
ℹ️ FACT — 2. Provider sync succeeds before a workspace existsSync status: {"hasSession":true,"lastRun":{"at":"2026-08-07T17:15:25.761Z","status":"noop"},"providers":[{"cloudProviderId":"lpr_01kzekcxrne3kar0jt7sz92782","providerId":"lpr_01kzekcxrne3kar0jt7sz92782","sourceProviderId":"first-workspace-models","name":"First Workspace Models","source":"custom","updatedAt":"2026-08-07T17:12:42.005Z","modelIds":["first-workspace-proof-model"],"importedAt":1786122924642}]}
ℹ️ FACT — 3. The first workspace receives the already-synced model without restartingSelectable model: {"id":"first-workspace-proof-model","name":"First Workspace Proof Model","providerName":"First Workspace Models","selected":false,"selectable":true}
ℹ️ FACT — 4. Workspace creation does not reintroduce the sync failureFinal sync status: {"hasSession":false,"lastRun":null,"providers":[]}
Roll created 2026-08-07T17:11:25.569Z · Source: |
| PREVIEW_PROXY_WILDCARD="https://*.${PREVIEW_PROXY_HOST#*.}" | ||
| ;; | ||
| esac | ||
| export DEN_BETTER_AUTH_TRUSTED_ORIGINS="${DEN_BETTER_AUTH_TRUSTED_ORIGINS:-$CORS_ORIGINS${PREVIEW_PROXY_WILDCARD:+,$PREVIEW_PROXY_WILDCARD}}" |
There was a problem hiding this comment.
Wildcard trusts attacker-controlled Daytona preview origins
Deriving a wildcard from the preview host trusts every HTTPS subdomain of the shared Daytona domain, allowing an attacker with their own preview URL to bypass Better Auth origin checks and perform cross-site authenticated requests against another sandbox.
Evidence
- The changed default sets
DEN_BETTER_AUTH_TRUSTED_ORIGINStohttps://*.${PREVIEW_PROXY_HOST#*.}for non-local multi-label hosts. ee/apps/den-api/src/auth.tspasses these values directly to Better Auth astrustedOrigins.- Daytona preview URLs are minted per sandbox, while other users can obtain preview subdomains under the same parent domain.
- Better Auth therefore treats an attacker-owned Daytona preview origin as trusted for authenticated requests; use the exact rotated origin or a dedicated isolated suffix instead of a shared-domain wildcard.
Identified by Warden · diff-security-review · LPZ-RD6
Problem
Signing in to OpenWork Cloud on a clean profile — before any workspace exists — made every cloud provider sync fail with
workspace_missing. Managed models never materialized until an app restart.Fix
CloudProviderSync.apply()no longer requires an engine workspace: providers and credentials materialize into the global runtime config and env store immediately, and the engine runtime-config write + reload are deferred (reloadPending) until the first workspace exists. The first post-workspace sync (or the embedded-server restart that workspace creation triggers on desktop) delivers the providers and auth.Also in this branch, required to build/validate at all:
fix(deps): pin esbuild to 0.25.12 — 0.28.x refuses to lower plain destructuring for Vite's browser-target lists, killingpnpm devon fresh installs (pre-existing ondev, reproduced locally and in every Daytona sandbox).fix(evals): trust rotated Daytona preview origins (Den seed sign-in 403INVALID_ORIGIN), detach the Daytona install gate from the exec channel (observed wedging 40+ min)..d.tspath mapping (crashed tsx-run Den boots;tsc --noEmitclean without it).Regression coverage
apps/server/src/cloud-provider-sync.e2e.test.ts: sync with zero workspaces returnsnoop, materializes providers globally, performs no engine calls; after the first workspace appears the next run isappliedwith exactly one reload andPUT /auth/<provider>.evals/specs/cloud-provider-before-workspace.slow.test.ts: real Den + desktop app; signs in before any workspace, proves sync succeeds, creates the first workspace through the product, and proves the managed model is selectable without a restart.Verification (agent-first, real Daytona)
Verdict: Passed (on PR head 3f1b9c7)
bun test src/cloud-provider-sync.e2e.test.ts(apps/server): 2 pass / 0 fail, 55 expects.pnpm --dir apps/server typecheck: clean.tsc -p ee/apps/den-api/tsconfig.json --noEmit: clean.repro/cloud-provider-before-workspace-unfixed= dev + infra fixes only):OPENWORK_EVAL_APP_SPECS=1 OPENWORK_EVAL_DAYTONA=1 OPENWORK_EVAL_REF=repro/cloud-provider-before-workspace-unfixed pnpm --dir evals exec vitest run --config vitest.config.ts --project stack specs/cloud-provider-before-workspace.slow.test.ts→ 1 failed, exactly on the target assertion:
{"status":"failed","message":"workspace_missing"}.OPENWORK_EVAL_REF=fix/cloud-provider-sync-before-first-workspace(cold boot, no reuse):→ 1 passed (270s); tape 4/4 facts passed.
Evidence tape for the PR head follows in the sticky comment.