Skip to content

Display sandbox projects with ancestor chain in credentials UI - #5110

Open
brandonjackson wants to merge 2 commits into
mainfrom
claude/linear-con-147-sort-fwpqhl
Open

Display sandbox projects with ancestor chain in credentials UI#5110
brandonjackson wants to merge 2 commits into
mainfrom
claude/linear-con-147-sort-fwpqhl

Conversation

@brandonjackson

@brandonjackson brandonjackson commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Description

This PR fixes how sandboxes are listed in the credentials UI. The "Projects with access" column on the credentials page, the OAuth clients table, and the project chips in the credential and OAuth client forms showed sandboxes by bare name, so a sandbox looked identical to a top-level project. Sandboxes are now labelled with their ancestor chain, e.g. parent/sandbox, matching the convention used by Project.display_name/1 in the breadcrumbs and project picker.

Key changes:

  1. Projects.preload_ancestors/1 now also accepts a list of projects and loads every ancestor chain in a single recursive CTE query, so the credentials page does not issue one query per sandbox.
  2. CredentialIndexComponent resolves display names once for all distinct projects across credentials and OAuth clients.
  3. The shared projects_picker component and the credential / OAuth client form components label selected projects, dropdown options, and the revoke-access confirmation with the ancestor chain.
  4. Deletion behaviour is unchanged but now covered by tests: purging a project removes its project_credentials, so purged sandboxes drop out of the list, while soft-deleted sandboxes remain visible during their grace period.

Closes CON-147

Validation steps

  1. Create a project and a sandbox under it.
  2. Create a credential and grant both the parent and the sandbox access.
  3. On /credentials, check the credential row shows chips parent-name and parent-name/sandbox-name.
  4. Open the credential's edit modal and check the selected project chip for the sandbox shows parent-name/sandbox-name.
  5. Schedule the sandbox for deletion and confirm it still appears; purge it and confirm it disappears.
  6. Repeat step 3 with an OAuth client granted to the parent and sandbox.

Additional notes for the reviewer

  1. The Linear ticket describes the convention as parent:sandbox with a colon. The existing Project.display_name/1, breadcrumbs, and project picker all join with /, so this PR follows the slash for consistency. Switching to a colon would be a one-line change in Project.display_name/1.
  2. No authorization changes: the lists only render projects the credential or client is already associated with.

AI Usage

Please disclose whether you've used AI anywhere in this PR (it's cool, we just
want to know!):

  • I have used Claude Code
  • I have used another model
  • I have not used AI

You can read more details in our
Responsible AI Policy

Pre-submission checklist

  • I have performed an AI review of my code (we recommend using /review
    with Claude Code)
  • I have implemented and tested all related authorization policies.
    (e.g., :owner, :admin, :editor, :viewer)
  • I have updated the changelog.
  • I have ticked a box in "AI usage" in this PR

🤖 Generated with Claude Code

https://claude.ai/code/session_019QvkXbFNgyfpGMBosr4qP1

The "Projects with access" column on the credentials page and the
project picker in the credential and OAuth client forms listed sandboxes
by bare name, so they were indistinguishable from top-level projects.
Sandboxes are now labelled with their ancestor chain (parent/sandbox),
matching Project.display_name/1 used elsewhere in the app.

Projects.preload_ancestors/1 accepts a list of projects and loads every
ancestor chain in a single recursive query so the credentials table does
not issue one query per sandbox.

Purged sandboxes already drop out of these lists because deleting a
project removes its project_credentials; a test now covers that, along
with soft-deleted sandboxes still appearing during their grace period.

Closes CON-147

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019QvkXbFNgyfpGMBosr4qP1
@github-project-automation github-project-automation Bot moved this to New Issues in Core Sep 2, 2026
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Security Review ✅

  • S0 (project scoping): Display-only change; ancestors are loaded only for projects already surfaced by the existing list_credentials/1 and list_clients/1 scoping paths, and reuses the same Project.display_name/1 pattern applied elsewhere in the app.
  • S1 (authorization): N/A — no new web-layer events, controllers, or policy branches; only rendering helpers changed.
  • S2 (audit trail): N/A — no writes to workflows, credentials, project settings, or other config resources are introduced.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: New Issues

Development

Successfully merging this pull request may close these issues.

2 participants