Scope Check
The scope check verifies that every Bazel target which ends up in a
dependable_element’s transitive implementation closure is covered by a
certified scope declared somewhere in that or another element. It catches the case
where a unit’s implementation silently starts depending on code that nobody
certified.
Declaring scope
Each unit declares the scope it certifies via its scope attribute —
labels, packages (//some/package:__pkg__), or packages-and-subpackages
(//some/package:__subpackages__), following normal Bazel visibility
patterns:
unit(
name = "MyUnit",
implementation = [":my_unit_lib"],
scope = ["//third_party/foo:__subpackages__"],
unit_design = [":MyUnit_design"],
tests = [],
)
scope is for dependencies that are not explicitly named as
implementation targets themselves (e.g. third-party libraries pulled in
transitively) but are still known and accepted as part of the unit. Every
unit and component also implicitly certifies its own explicitly named
targets (implementation, nested components).
Scopes are collected transitively: a component’s certified scope is the
union of its own units’ and nested components’ scopes, and a
dependable_element’s certified scope is the union of all its components’
scopes plus any scopes brought in through deps on other dependable
elements.
What is checked
For each unit, an aspect (cc_dependencies_aspect) walks the
deps / implementation_deps / exported_deps attributes of its
implementation targets and collects every transitively reached label.
dependable_element then checks each collected label against the tree of
certified scopes built from all scope declarations in the element: a
label is in scope if it (or an enclosing package / subpackage wildcard) was
declared somewhere. Any dependency that is not covered fails the check with:
Not in certified scope <label>, stopping at <path segment>
A certified scope that is declared more than once (e.g. by two units) is also rejected:
The same scope is covered twice: <label>
Implementation
bazel/rules/rules_score/private/
├── cc_dependency_aspect.bzl # CcDependencyInfo: transitive labels reached from a cc target
├── unit.bzl # CertifiedScope(transitive_scopes = scope attr)
├── component.bzl # aggregates CertifiedScope + dependent_labels from children
└── dependable_element.bzl # builds the scope tree and validates dependent_labels against it
See the CertifiedScope, UnitInfo.dependent_labels and
ComponentInfo.dependent_labels providers in
//bazel/rules/rules_score:providers.bzl for the exact data flow.