Skip to content

ui: open sandboxes from any identifier an operator has - #1242

Merged
ac-pplx merged 2 commits into
mainfrom
ac/admin-ui-sandbox-id-forms
Nov 2, 2026
Merged

ac-pplx merged 2 commits into
mainfrom
ac/admin-ui-sandbox-id-forms

Conversation

@ac-pplx

@ac-pplx ac-pplx commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The console now opens a sandbox from any identifier an operator is likely to hold. Before this change, two of its own links were broken.

The admin sandbox routes accept only sbx_<uuid>, but the console linked to sandboxes with bare UUIDs in two places:

  • the node sandboxes drawer, which renders GET /admin/api/v1/nodes/{id}/sandboxes rows;
  • Credential Rules, which renders admin list rows (id is a bare UUID there).

Both links opened "Sandbox not found" after a 400 sandbox id must be an sbx_ prefixed UUID. Operators also copy the sandbox pod name (space-sbx-<32 hex>-g<N>) from kubectl and node logs, and sandbox:<uuid> tags from logs; the detail URL accepted neither.

parseSandboxRef (ui/src/lib/sandbox-id.ts) resolves each of these to one canonical form:

  • sbx_<uuid> in any case;
  • a bare or undashed UUID;
  • sandbox:<uuid>;
  • the pod name, with or without the generation suffix.

It rejects names, short labels and partial IDs, so it never guesses. Changes:

  • /dashboard/sandboxes/<any of those> replaces the URL with the sbx_ ID before anything loads. The sandbox is then read once, and a slow load cannot send the operator back to the sandbox after they have left the page. Identifiers from the URL are decoded with a helper that keeps malformed percent-encoding as typed.
  • The node drawer and Credential Rules link with the canonical ID. Credential Rules shows the same short label as the sandbox list (the last 8 hex digits), and links to and copies the sbx_ ID.
  • Credential Rules search matches a full identifier in any of these forms.

The admin API itself still requires sbx_ on sandbox routes, and its debug route requires a bare UUID. Making the API accept every form is a separate backend change and is not part of this PR.

Validation

  • npm ci, npm test (69 pass, including the new src/lib/sandbox-id.test.mjs cases for each accepted and rejected form, the fallback for identifiers that do not parse, and malformed percent-encoding) and npm run build in ui/.
  • A Playwright loop against a local Kind stack with synthetic data, run on main (production build) and on this branch (the Kind space-ui image):
    • bare-UUID, pod-name and undashed detail URLs load and canonicalize, with one read of the sandbox;
  • leaving the page while a slow first load is pending stays on the page the operator chose;
    • the node drawer link and the Credential Rules link open the sandbox;
    • an unknown ID still shows "Sandbox not found".
  • The loop found no new console errors, page errors or failed requests, compared with main.
  • Not validated: external sign-in mode. This change does not touch the auth paths.

Visual confirmation

Following a sandbox link from the node drawer. Before, it lands on "Sandbox not found"; after, it opens the sandbox:

before: node drawer link
after: node drawer link

Videos: before, after.

Final screens:

Before After
before after

Opening /dashboard/sandboxes/space-sbx-<hex>-g1 (a pod name) after this change. It lands on the sandbox, and the URL becomes its sbx_ ID:

after: pod name URL

Severity and risk

Severity: medium. Two navigation paths in the operator console were broken outright, and identifier lookup is the first step of most support cases.

Risk: low.

  • Every input that worked before resolves to the same sbx_ ID.
  • Anything parseSandboxRef rejects now fails in the browser with the same not-found page, instead of reaching the API.
  • Roll back by reverting the commit.

AI assistance: Claude Code wrote the code, the tests and this description, and ran the validation; a maintainer reviews it.

The admin sandbox routes take only the `sbx_<uuid>` form, but the console
links to sandboxes with bare UUIDs in two places: the node sandboxes
drawer (from GET /nodes/{id}/sandboxes) and Credential Rules (from the
admin list, whose rows carry bare UUIDs). Both links opened "Sandbox not
found" with a 400 from the API. Operators also hold the pod name
(space-sbx-<hex>-g<N>) from kubectl and node logs, and `sandbox:<uuid>`
tags from logs, none of which the detail URL accepted.

parseSandboxRef resolves the public ID, a bare or undashed UUID, a
`sandbox:` tag and the sandbox pod name to one canonical form. The detail
page loads any of them and replaces the URL with the `sbx_` ID; the node
drawer and Credential Rules link with the canonical ID, and Credential
Rules search matches a full identifier in any of those forms.
@github-actions github-actions Bot added the triage:pending Waiting for a maintainer to triage label Oct 31, 2026
@github-actions

Copy link
Copy Markdown

Thanks for opening this pull request! A SPACE maintainer will take a look.

CONTRIBUTING.md explains how we review outside contributions.

A non-canonical sandbox link (bare UUID, pod name) now moves to the
sbx_ URL at the top of the detail page's effect, before any request,
instead of after the first load. Each such link loads the sandbox once,
and a slow load can no longer send the operator back to the sandbox
after they have left the page. URL identifiers are decoded with a
helper that keeps malformed percent-encoding as typed.

The publicSandboxIdFromAny test is named for what it checks, and a new
test covers its fallback for identifiers it cannot parse.
@ac-pplx
ac-pplx marked this pull request as ready for review October 31, 2026 18:43
zibi-pplx
zibi-pplx previously approved these changes Nov 1, 2026
@zibi-pplx
zibi-pplx dismissed their stale review November 1, 2026 22:29

Withdrawing this approval for now. Any feedback above still stands.

@ac-pplx
ac-pplx added this pull request to stack #1283 November 2, 2026 04:30

@johnlouie-pplx johnlouie-pplx left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approving at f18c09f. I rechecked the identifier parser against the server's pod naming, the redirect-before-load path, and the admin authorization checks. I found no blocker. All 69 UI tests pass at this head; the combined stack also builds at #1248. The list-search gap is covered by #1244. I haven't reproduced the author's browser tests.

@ac-pplx
ac-pplx added this pull request to the merge queue Nov 2, 2026
Merged via the queue into main with commit 488feda Nov 2, 2026
28 checks passed
@ac-pplx
ac-pplx deleted the ac/admin-ui-sandbox-id-forms branch November 2, 2026 06:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triage:pending Waiting for a maintainer to triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants