Skip to content

Add /:org/:workspace context for web and API#508

Draft
RhysSullivan wants to merge 2 commits intors/cloud-workspaces-06-web-orgfrom
rs/cloud-workspaces-08-workspace-context
Draft

Add /:org/:workspace context for web and API#508
RhysSullivan wants to merge 2 commits intors/cloud-workspaces-06-web-orgfrom
rs/cloud-workspaces-08-workspace-context

Conversation

@RhysSullivan
Copy link
Copy Markdown
Owner

Add /:org/:workspace context for web and API

Workspace context is the URL-addressed sibling to org/global. The
URL determines which executor scope stack the server builds; reads
operate against that stack. The same ProtectedCloudApi schema serves
both /api/:org/... and /api/:org/:workspace/... mounts.

API:

  • Mount ProtectedCloudApi twice (/api/:org and /api/:org/:workspace)
    via prefixed router views.
  • ExecutionStackMiddleware reads :org and optional :workspace
    from URL params, resolves the workspace via resolveWorkspaceContext,
    and routes through buildWorkspaceScopeStack vs buildGlobalScopeStack.
    Auth check is unchanged: org membership only — workspaces have no
    separate ACLs in v1.
  • Test harness: dual-mount mirrors production. seedTestWorkspace()
    inserts the workspace row lazily inside the request pipeline (no
    extra DbService.Live to leak sockets). asWorkspace(orgId, slug, …)
    pre-registers the slug so the URL-segment parser treats it as a
    workspace prefix; the row is created on first request.
  • New workspace-context.node.test.ts pins down: (1) workspace-scoped
    writes are visible from workspace context only, (2) workspace
    context inherits org/global sources via the scope stack.

Web:

  • Routes: /:org/:workspace layout + index/connections/secrets/policies/
    tools/sources.$namespace/sources.add.$pluginKey. Layout resolves
    the slug from workspacesAtom, redirects to /$org if unknown,
    re-points the executor base URL at the workspace-prefixed mount,
    and provides WorkspaceRouteContext to descendants.
  • Shell nav: when in workspace context, NavItem to/params target the
    /$org/$workspace/... routes; org-admin items (Settings, Billing)
    are hidden. SourceList builds workspace-scoped detail links too.
  • Context switcher: per active org, pinned Global entry +
    separator + workspaces. Trigger label is <org> / Global or
    <org> / <workspaceName>. New "Create workspace" item opens a
    dialog that POSTs and navigates to the new /$org/$slug.
  • workspacesAtom queries OrgHttpApi.workspaces.listWorkspaces;
    CloudApiClient now adds the WorkspacesApi group so the call types.
  • workspaceWriteKeys reactivity key invalidates the list on create.

Strip /api in start.ts means router prefixes are /:org and /:org/:workspace

Adds a URL-context-aware fetch wrapper in the react package so the
ExecutorApiClient and CloudApiClient rewrite /api/ -> /api//
(or /api///) at fetch time based on
window.location.pathname. AtomHttpApi.Service snapshots baseUrl at module
load, so setBaseUrl in routes/$org.tsx couldn't repoint it; the wrapper
makes the per-org URL effective without rebuilding the service.

Auth/sentry/autumn endpoints stay unprefixed via UNPREFIXED_API_PATHS.

Workspace context is the URL-addressed sibling to org/global. The
URL determines which executor scope stack the server builds; reads
operate against that stack. The same ProtectedCloudApi schema serves
both `/api/:org/...` and `/api/:org/:workspace/...` mounts.

API:
- Mount ProtectedCloudApi twice (`/api/:org` and `/api/:org/:workspace`)
  via prefixed router views.
- ExecutionStackMiddleware reads `:org` and optional `:workspace`
  from URL params, resolves the workspace via resolveWorkspaceContext,
  and routes through buildWorkspaceScopeStack vs buildGlobalScopeStack.
  Auth check is unchanged: org membership only — workspaces have no
  separate ACLs in v1.
- Test harness: dual-mount mirrors production. seedTestWorkspace()
  inserts the workspace row lazily inside the request pipeline (no
  extra DbService.Live to leak sockets). asWorkspace(orgId, slug, …)
  pre-registers the slug so the URL-segment parser treats it as a
  workspace prefix; the row is created on first request.
- New workspace-context.node.test.ts pins down: (1) workspace-scoped
  writes are visible from workspace context only, (2) workspace
  context inherits org/global sources via the scope stack.

Web:
- Routes: /:org/:workspace layout + index/connections/secrets/policies/
  tools/sources.$namespace/sources.add.$pluginKey. Layout resolves
  the slug from workspacesAtom, redirects to /$org if unknown,
  re-points the executor base URL at the workspace-prefixed mount,
  and provides WorkspaceRouteContext to descendants.
- Shell nav: when in workspace context, NavItem to/params target the
  /$org/$workspace/... routes; org-admin items (Settings, Billing)
  are hidden. SourceList builds workspace-scoped detail links too.
- Context switcher: per active org, pinned `Global` entry +
  separator + workspaces. Trigger label is `<org> / Global` or
  `<org> / <workspaceName>`. New "Create workspace" item opens a
  dialog that POSTs and navigates to the new /$org/$slug.
- workspacesAtom queries OrgHttpApi.workspaces.listWorkspaces;
  CloudApiClient now adds the WorkspacesApi group so the call types.
- workspaceWriteKeys reactivity key invalidates the list on create.
…kspace

Adds a URL-context-aware fetch wrapper in the react package so the
ExecutorApiClient and CloudApiClient rewrite /api/<rest> -> /api/<org>/<rest>
(or /api/<org>/<workspace>/<rest>) at fetch time based on
window.location.pathname. AtomHttpApi.Service snapshots baseUrl at module
load, so setBaseUrl in routes/$org.tsx couldn't repoint it; the wrapper
makes the per-org URL effective without rebuilding the service.

Auth/sentry/autumn endpoints stay unprefixed via UNPREFIXED_API_PATHS.
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 4, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
executor-marketing 0865ef9 Commit Preview URL

Branch Preview URL
May 04 2026, 05:15 PM

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 4, 2026

Open in StackBlitz

@executor-js/cli

npm i https://pkg.pr.new/@executor-js/cli@508

@executor-js/config

npm i https://pkg.pr.new/@executor-js/config@508

@executor-js/execution

npm i https://pkg.pr.new/@executor-js/execution@508

@executor-js/sdk

npm i https://pkg.pr.new/@executor-js/sdk@508

@executor-js/storage-core

npm i https://pkg.pr.new/@executor-js/storage-core@508

@executor-js/codemode-core

npm i https://pkg.pr.new/@executor-js/codemode-core@508

@executor-js/runtime-quickjs

npm i https://pkg.pr.new/@executor-js/runtime-quickjs@508

@executor-js/plugin-file-secrets

npm i https://pkg.pr.new/@executor-js/plugin-file-secrets@508

@executor-js/plugin-google-discovery

npm i https://pkg.pr.new/@executor-js/plugin-google-discovery@508

@executor-js/plugin-graphql

npm i https://pkg.pr.new/@executor-js/plugin-graphql@508

@executor-js/plugin-keychain

npm i https://pkg.pr.new/@executor-js/plugin-keychain@508

@executor-js/plugin-mcp

npm i https://pkg.pr.new/@executor-js/plugin-mcp@508

@executor-js/plugin-onepassword

npm i https://pkg.pr.new/@executor-js/plugin-onepassword@508

@executor-js/plugin-openapi

npm i https://pkg.pr.new/@executor-js/plugin-openapi@508

executor

npm i https://pkg.pr.new/executor@508

commit: 0865ef9

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 4, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
executor-cloud 0865ef9 May 04 2026, 05:16 PM

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.

1 participant