Skip to content

workspaces.json accumulates inverted/poisoned catalog rows (id=rw_ handle, relayWorkspaceId=UUID) #323

Description

@khaliqgant

Follow-up from #321 / PR #322. #322 makes delegated-credential resolution robust despite poisoned catalog rows (union alias probe + heal-forward). This issue tracks the upstream source that writes those rows, so the catalog stops accumulating poison (and the per-resolve "not uniquely resolved" warning #322 emits stops firing on a permanently-polluted catalog).

Symptom

Live ~/.relayfile/workspaces.json contains an inverted row where id and relayWorkspaceId are swapped relative to the normal rows:

  • Normal: name="default", id="50587328-…uuid", relayWorkspaceId="rw_7ccfea89"
  • Inverted: name="rw_7ccfea89", id="rw_7ccfea89", relayWorkspaceId="50587328-…uuid"
  • plus a no-cross-link twin: name="rw_7ccfea89", id="rw_7ccfea89", relayWorkspaceId=""

Because matching is by Name or ID, the rw_-named record and the UUID-id'd record never reconcile → duplicates + the inverted twin accumulate. For input rw_7ccfea89, canonicalization then sees two different record.IDs and (correctly, post-#322) fails closed to raw-shard hashing.

Root cause (cmd/relayfile-cli/main.go)

  1. upsertWorkspaceDetails (main.go:7771-7773) defaults record.ID = record.Name when ID is empty. If a workspace is ever created/keyed with the rw_ handle as its Name (any command that accepts rw_… as a workspace selector and upserts it), record.ID becomes the rw_ handle — never a UUID.
  2. Later persistDelegatedWorkspace (main.go:1823-1830): relayWorkspaceID := bundle.Workspace() returns the canonical UUID (firstNonEmpty(RelayfileWorkspaceID, WorkspaceID), delegatedauth.go:70). Since record.ID is already non-empty (the rw_ handle) and != UUID, it assigns record.RelayWorkspaceID = UUID. Net: id=rw_handle, relayWorkspaceId=UUID → the inverted row.

This is the same app-UUID↔rw_ identity split that produced #321: the local catalog conflates "the string the user typed to select a workspace" (which can be a rw_ handle) with "the canonical workspace ID" (UUID).

Proposed fix direction

record.ID should be the canonical workspace identity (UUID) and must never be defaulted from a rw_ handle. Options:

  • (a) In upsertWorkspaceDetails, if the would-be ID has the rw_ prefix, route it to RelayWorkspaceID and leave ID empty/uncanonicalized until the UUID is known.
  • (b) In persistDelegatedWorkspace, if bundle.Workspace() is a UUID and record.ID is a rw_ handle, treat the UUID as the authoritative ID and demote the rw_ to RelayWorkspaceID (correct the swap), then de-dupe against the canonical-ID record.
  • Plus a one-time catalog migration to collapse existing inverted/duplicate rows.

Severity

Non-blocking. #322 already prevents this from breaking mounts; this is hygiene to stop poison accumulation and silence the cosmetic per-resolve warning.

Filed by cloud-expert per review of #321 / #322.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions