Skip to content

fix(server): scope signed links to their methods and give new installs their own computer name - #204

Merged
jerelvelarde merged 2 commits into
CopilotKit:mainfrom
ayuxy027:fix/signed-links-and-computer-name
Oct 26, 2026
Merged

jerelvelarde merged 2 commits into
CopilotKit:mainfrom
ayuxy027:fix/signed-links-and-computer-name

Conversation

@ayuxy027

@ayuxy027 ayuxy027 commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

What

Docker computer name. When COMPUTER_DEPLOYMENT_ID is unset, a new install now gets a random deployment name, kept in DATA_DIR/computer-deployment-id. Two installs on one Docker engine no longer derive the same container and volume from the default PUBLIC_API_URL.

  • An install that already has a session-signing-key and no name file started before this change. It keeps the PUBLIC_API_URL-derived name, so its existing /workspace volume stays attached. Nothing is migrated or orphaned.
  • A separate task worker already shares DATA_DIR (README), so it reads the same name. The file is created with the same atomic create-or-read the signing key uses, which this PR extracts as readOrCreate. Concurrent first starts therefore agree on one name.
  • The name is resolved in createApp before createAuth, so a new install writes its name before its signing key.
  • An explicit COMPUTER_DEPLOYMENT_ID (and E2B, which requires one) is untouched.
  • A blank COMPUTER_DEPLOYMENT_ID= (Node's .env loader reads an uncommented, unfilled line as "") now counts as unset. Before, ?? kept "", so every such install hashed the same empty name.
  • .env.example no longer suggests the copyable my-openmuse.

Signed links. The /api/* middleware accepts a signature only for GET/HEAD on the three signed paths, and for POST on the console, whose page posts input to its own URL. Any other method on those paths needs a session, so a route added there later cannot inherit link access. I didn't bind the method into the HMAC, because the console page uses one signed URL for both GET and POST.

Tests

  • tests/api.test.ts: signed GET, HEAD and console POST still reach their handlers. Signed PUT/DELETE/POST/PATCH on those paths get 401. Against the previous app.ts this fails (404 instead of 401).
  • tests/auth-startup.test.ts:
    • 8 concurrent first starts agree on one random name, and a second install with the same URL gets a different volume.
    • A new install started through createApp keeps its name across a restart. This fails if resolution moves after createAuth.
    • An existing install (signing key present) and an explicit name keep their computer, and no file is written.
  • tests/config.test.ts: a blank COMPUTER_DEPLOYMENT_ID reads as unset (fails against the previous config.ts).
  • Test fixtures now set an explicit computerDeploymentId.

Not changed

  • E2B still requires an explicit ID; unchanged.
  • Existing Docker installs keep the PUBLIC_API_URL-derived name. Set COMPUTER_DEPLOYMENT_ID to move off it; doing so starts a new workspace volume.

Tested

  • pnpm lint, pnpm typecheck, pnpm --dir apps/worker typecheck, pnpm build:server
  • pnpm test: 513 passed, 0 failed
  • I didn't run the real Docker or E2B smoke tests. Native/web builds and browser suites weren't run, because this is a server-only change.

@jerelvelarde jerelvelarde left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 120f2cb71da2c1bf05afef1f4d475a0f865f81ec.

New installations receive persistent distinct computer deployment names, while existing installations keep their previous volume identity. Signed links are limited to the methods their pages need. Security: checked atomic create-or-read, concurrent first startup, API/worker initialization through createApp, blank environment handling, owner-scoped computer identity and signed-route method gating. No actionable security finding. Console POST remains intentionally authorized by its bearer URL; legacy installs retain the documented URL-derived identity until explicitly migrated. Verification: 26 API/auth-startup/config tests passed. No real Docker/E2B provisioning or native devices were exercised.

Local execution used read-only, network-disabled Linux containers with synthetic data and Node 24.17.0. Root dependency fixtures came from main’s manifest rather than the lockfile; exact-head GitHub CI covers locked full checks where green. No production credentials were supplied.

@jerelvelarde
jerelvelarde merged commit 62be601 into CopilotKit:main Oct 26, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants