Skip to content

feat(workspace): stale-credential sweep at workspace create#37

Closed
escherize wants to merge 7 commits into
bcm/ghy-4050-workspace-commandsfrom
bcm/ghy-4054-stale-credential-sweep
Closed

feat(workspace): stale-credential sweep at workspace create#37
escherize wants to merge 7 commits into
bcm/ghy-4050-workspace-commandsfrom
bcm/ghy-4054-stale-credential-sweep

Conversation

@escherize

Copy link
Copy Markdown
Contributor

Refs GHY-4054 (Linear). Stacked on #33 + #34 (base shows #34's commits until it merges).

Tier 2 of the containment ladder: a stale full-power credential for the same parent (any api-key profile, any OAuth grant wider than mb:workspace-manager) would let a confused agent bypass the workspace-scoped token, so workspace create refuses while one exists in the profile store.

  • Interactive: offers revocation — durable local clear first, then best-effort server-side token revocation (logout's pattern); api-keys warn that the server-side key must be deleted in Admin settings.
  • Non-interactive (agent context): hard refusal listing the offenders. --keep-existing-auth is the human-only override, itself refused without a TTY — an agent can never talk itself past the sweep.
  • The profile the command runs as is exempt (deliberate use, not lying around); classification unit-tested (scope boundaries, host matching, cleared records), refusal branches e2e-tested with exact messages.

Known residual: the sweep sees the profile store only — env keys and .env files are tier 1's (GHY-4059) and the attestation idea's territory.

escherize added 7 commits July 6, 2026 14:14
…oped grant

The scoped token is the containment primitive for Option B: a parent
credential on an agent's machine that can only do workspace CRUD,
enforced server-side by default-deny scope middleware.

- scope threads through discovery gating, dynamic client registration,
  the authorize URL, the stored credential, and refresh (which sends no
  scope parameter, so a refresh can never widen the grant)
- pre-scope profile records resolve to mb:full, which is what every
  legacy login was minted with
- workspace login is browser-OAuth only: --api-key, MB_API_KEY, and
  non-TTY contexts are refused so a key can't masquerade as scoped
- a 403 on a scope-narrowed profile is enriched to name the scope and
  the fix instead of a bare "Forbidden."

Refs GHY-4053
Tier 2 of the containment ladder: a stale full-power credential for the
same parent (any api-key profile, any OAuth grant wider than
mb:workspace-manager) would let a confused agent bypass the scoped
token, so create refuses while one exists. Interactive runs offer
revocation (local clear + best-effort server-side token revocation);
non-interactive runs hard-refuse — --keep-existing-auth is the
human-only override and is itself refused without a TTY. The profile
the command runs as is exempt: it is in deliberate use, not lying
around.

connect gets the same sweep when it lands (GHY-4052).

Refs GHY-4054
Newer oxlint flags helpers that capture nothing from their describe.

Refs GHY-4053
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5fe62b4d-767b-450d-a21f-47e1f3ced486

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bcm/ghy-4054-stale-credential-sweep

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@escherize

Copy link
Copy Markdown
Contributor Author

Consolidated into #39.

@escherize escherize closed this Jul 8, 2026
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