Skip to content

feat(workspace): scope-trust list for aspect loading#10347

Merged
davidfirst merged 13 commits intomasterfrom
workspace/scope-trust
May 7, 2026
Merged

feat(workspace): scope-trust list for aspect loading#10347
davidfirst merged 13 commits intomasterfrom
workspace/scope-trust

Conversation

@davidfirst
Copy link
Copy Markdown
Member

@davidfirst davidfirst commented May 6, 2026

Opt-in workspace policy. When the workspace declares trustedScopes in workspace.jsonc, Bit checks the scope of every aspect (env, generator, etc.) before loading it. Without that key, behavior is unchanged — anything loads.

Once enabled, the effective trust set is:

  • builtin: teambit.*, bitdev.*, learn-bit-react.*, bitdesign.*, frontend.* (the bit.cloud orgs that ship official + community-blessed components most users already pull from)
  • the owner of defaultScope (e.g. acme.frontendacme.*)
  • entries listed under trustedScopes in workspace.jsonc

If an aspect's scope isn't on that list, an interactive shell prompts the user to add it; non-interactive contexts (CI) get an error pointing at bit scope trust add <scope> or workspace.jsonc.

Surface

  • trustedScopes?: string[] on teambit.workspace/workspace
  • bit scope trust [action] [pattern] — single command with action positional
    • list (default) — status; if on, the effective list
    • enable — opt-in (writes trustedScopes: [])
    • disable — opt-out (removes the key)
    • add <pattern> — add pattern (auto-enables)
    • remove <pattern> — remove pattern (does NOT auto-disable on empty)
  • aspect-load hook on ScopeMain; both scope-aspects-loader and workspace-aspects-loader honor it before require()-ing aspects

The workspace can now declare which scopes it trusts when loading aspects
(envs, generators, etc.). Effective trust = builtin (`teambit.*`,
`bitdev.*`) + the owner of `defaultScope` + entries listed under
`trustedScopes` in workspace.jsonc.

When an aspect comes from a scope outside that list, an interactive shell
prompts to extend the list; in non-interactive contexts it surfaces a
clear error pointing to `bit scope trust <scope>` or workspace.jsonc.

Adds:
- `trustedScopes?: string[]` on the workspace config
- `bit scope trust [pattern]` (lists effective trust when called bare)
- `bit scope untrust <pattern>`
- aspect-load hook on ScopeMain so scope-aspects-loader and
  workspace-aspects-loader honor the same gate
Copilot AI review requested due to automatic review settings May 6, 2026 13:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a workspace-level “scope trust” policy that gates aspect loading (envs/generators/etc.) based on a computed allowlist of trusted scope patterns, with interactive prompting in TTY contexts and an actionable error in non-interactive runs. It integrates this guard into both the scope and workspace aspect-loader paths and adds CLI commands to manage the trust list in workspace.jsonc.

Changes:

  • Adds a ScopeMain pre-require() hook (aspectLoadGuard) and invokes it from both scope-aspects-loader and workspace-aspects-loader.
  • Introduces workspace trustedScopes?: string[] configuration plus bit scope trust / bit scope untrust commands to manage it.
  • Adds an e2e test to verify that an env from an untrusted scope is not required (marker file not written).

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
scopes/workspace/workspace/workspace.main.runtime.ts Wires ScopeTrust into ScopeMain and registers scope trust/untrust subcommands.
scopes/workspace/workspace/workspace-aspects-loader.ts Calls the new aspectLoadGuard before requiring workspace-loaded aspects.
scopes/workspace/workspace/types.ts Adds trustedScopes?: string[] to the workspace extension config interface/docs.
scopes/workspace/workspace/scope-trust/scope-trust.ts Implements trust resolution, pattern matching, interactive TOFU prompt, and config persistence.
scopes/workspace/workspace/scope-trust/scope-trust.cmd.ts Implements bit scope trust (add/list) and bit scope untrust (remove).
scopes/workspace/workspace/scope-trust/index.ts Exposes the scope-trust module exports for runtime wiring.
scopes/scope/scope/scope.main.runtime.ts Adds setAspectLoadGuard() / getAspectLoadGuard() to ScopeMain.
scopes/scope/scope/scope-aspects-loader.ts Invokes the guard before requiring an aspect from a scope-aspects capsule.
e2e/harmony/scope-trust.e2e.ts Adds an end-to-end test for refusing to load an env aspect from an untrusted scope.

Comment thread scopes/workspace/workspace/scope-trust/scope-trust.ts Outdated
Comment thread scopes/workspace/workspace/scope-trust/scope-trust.ts
Comment thread scopes/workspace/workspace/scope-trust/scope-trust.ts Outdated
Comment thread scopes/workspace/workspace/scope-trust/scope-trust.ts Outdated
Comment thread scopes/workspace/workspace/scope-trust/scope-trust.cmd.ts
Comment thread e2e/harmony/scope-trust.e2e.ts
davidfirst added 2 commits May 6, 2026 13:45
The aspect-load gate now runs only when `trustedScopes` is present in
workspace.jsonc. Without that key, no gate and no prompts (default
behavior).

CLI consolidated to one command that takes an action positional:
- bit scope trust              # same as list
- bit scope trust list         # status; if on, the effective list
- bit scope trust enable       # opt-in (writes trustedScopes: [])
- bit scope trust disable      # opt-out (removes the key)
- bit scope trust add <p>      # add pattern (auto-enables)
- bit scope trust remove <p>   # remove pattern (does NOT auto-disable)

`bit scope untrust` is gone (replaced by `bit scope trust remove`).
- support dotless scopes (legacy `defaultScope: my-scope`): both the auto-trust
  derivation and `bit scope trust add my-scope` now accept exact dotless names
- preserve workspace.jsonc comments on add/remove/enable by using
  mergeIntoExisting (matching how setDefaultScope updates the same aspect)
- bit scope trust: loadAspects=false, so the command stays usable as a recovery
  path when the workspace already references an aspect outside the trust list
- e2e: assert the import error message contains the refusal text instead of
  swallowing all errors (avoids false positive on unrelated import failures)
Copilot AI review requested due to automatic review settings May 6, 2026 19:40
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Comment thread scopes/workspace/workspace/types.ts Outdated
Comment thread scopes/workspace/workspace/scope-trust/scope-trust.ts Outdated
Comment thread scopes/workspace/workspace/scope-trust/scope-trust.ts Outdated
davidfirst added 2 commits May 6, 2026 16:39
- types.ts comment: point users at the actual command surface
  (`bit scope trust [enable|disable|add|remove]`)
- prompt: say "Aspect ..." instead of "uses an env" since the gate fires
  for any aspect (envs, generators, etc.)
- isValidPattern: disallow `/` in scope patterns (scope names don't contain
  slashes — that's the scope/component separator)
Copilot AI review requested due to automatic review settings May 6, 2026 20:41
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Comment thread scopes/workspace/workspace/scope-trust/scope-trust.cmd.ts Outdated
Comment thread scopes/workspace/workspace/scope-trust/scope-trust.cmd.ts Outdated
davidfirst added 2 commits May 6, 2026 17:11
Code reuse:
- isValidPattern delegates to isValidScopeName from @teambit/legacy-bit-id
  instead of a hand-rolled regex (also picks up the canonical character set)
- list output uses formatSection / formatTitle / formatHint from
  @teambit/cli, matching the project's CLI style guide

Code quality:
- consolidate workspace.jsonc reads through one private readExt helper
  (was duplicated across 5 methods)
- collapse addTrustedScope/removeTrustedScope into a single
  mutateConfiguredList helper that takes a list mutator
- extract a deny() closure in createGuard so the same throw isn't repeated
- drop unreachable default arm in the action switch (validated upfront)
- extract requirePattern() helper for add/remove arg validation
- narrow `as any` cast on enquirer prompt to Parameters<typeof prompt>[0]
- drop unused TrustedScopesGroups public re-export
- rename getOwnerWildcardFromDefaultScope -> getInferredOwnerPattern
  (the dotless branch returns an exact match, not a wildcard)

UX polish:
- listing's "configured" section now disappears cleanly when empty,
  with a separate hint instead of a "(1)"-counted placeholder

e2e:
- pull the duplicated env source string into a top-level constant
- action arg: replace "|" with "," so the CLI docs Markdown table doesn't
  break on pipe characters
- extendedDescription: replace "<p>" with "PATTERN" so MDX doesn't parse it
  as an unclosed JSX/HTML tag
Copilot AI review requested due to automatic review settings May 6, 2026 21:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

add learn-bit-react.*, bitdesign.*, and frontend.* to the auto-trusted
builtin scopes so users importing common community/design components
don't have to opt-in those scopes manually.
Copilot AI review requested due to automatic review settings May 7, 2026 14:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Comment thread scopes/workspace/workspace/scope-trust/scope-trust.cmd.ts Outdated
Comment thread scopes/workspace/workspace/scope-trust/scope-trust.ts
davidfirst added 2 commits May 7, 2026 15:09
scope-trust adds 3 new files (workspace/dist/scope-trust/*) loaded during
bit-bootstrap. snapshot refresh is left for a follow-up PR.
Copilot AI review requested due to automatic review settings May 7, 2026 19:12
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Comment thread scopes/workspace/workspace/scope-trust/scope-trust.ts
Comment thread scopes/workspace/workspace/scope-trust/scope-trust.ts Outdated
pattern is typed string|undefined; passing it directly to chalk.bold
relied on a runtime guarantee. assigning the requirePattern() result to
a local makes both the mutation and the success-message use the
narrowed string type.
isValidPattern now rejects multi-dot wildcards like `acme.frontend.*`.
The matcher only consults scope owners, so anything beyond a single
owner segment can't match a real Bit scope; reject up front rather
than persist a pattern that will never apply.
Copilot AI review requested due to automatic review settings May 7, 2026 19:40
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Comment thread scopes/workspace/workspace/scope-trust/scope-trust.ts
@davidfirst davidfirst enabled auto-merge (squash) May 7, 2026 20:03
@davidfirst davidfirst merged commit 502b137 into master May 7, 2026
16 checks passed
@davidfirst davidfirst deleted the workspace/scope-trust branch May 7, 2026 20:17
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.

3 participants