Skip to content

Worker dashboard URLs are workspace-implicit: /app/workers/{id} carries no workspace, and worker_id is not globally unique #2078

Description

@federicodeponte

Problem

The canonical worker detail route is /app/workers/[id]params: { id } only, no workspace (or user) in the URL (engine/apps/web/app/workers/[id]/page.tsx).

The workspace is resolved at request time from get_active_workspace_id() (a session/context var set from the active workspace cookie/header), NOT from the URL. And worker_id is not globally unique — it is scoped by workspace (workspace_id_for_worker(worker_id); every Supabase query does .eq("workspace_id", ...); the run recipe lookup is keyed by (worker_id, user_id, workspace_id)).

Consequences:

  • Opening /app/workers/{id} with a different workspace active resolves to the wrong workspace's worker or 404s.
  • The same worker_id can exist in multiple workspaces → the bare link is ambiguous.
  • Links are not portable/shareable across sessions; they only work because the recipient's session happens to default to the right workspace.

This is the same defect class as the run-proxy silent-403 just fixed in #2075 (worker config resolved by worker_id without workspace scope). The routing layer has the same worker_id == globally-unique assumption.

Proper fix

Worker URLs must be workspace-deterministic. Options:

  • Path-scoped: /app/w/{workspace_id}/workers/{worker_id} (preferred), or
  • Query-scoped: /app/workers/{id}?ws={workspace_id}, or
  • Globally-unique opaque worker ids.

Requirements: keep back-compat (old /app/workers/{id} must still resolve — look up the worker's workspace for the authenticated user, redirect + pin the active workspace; handle the not-a-member / ambiguous cases), update all internal navigation links to the scoped URL, and have the API/active-workspace resolution prefer the URL's workspace when present.

Repo note: dashboard UI lives in the engine (engine/apps/web), so the fix is an engine change here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions