Framework Reference Contracts¶
Framework reference contracts enforce rules over declared MSBuild FrameworkReference items (e.g. Microsoft.AspNetCore.App, Microsoft.WindowsDesktop.App) — independent of whether any compiled type actually references a type from that shared framework.
Two families are covered on this page:
- Framework dependency (
strict_framework_dependency/audit_framework_dependency) — a source project/assembly must not declare aFrameworkReferencematching any framework group in aforbiddenlist. - Framework allow-only (
strict_framework_allow_only/audit_framework_allow_only) — a source project/assembly may only declareFrameworkReferences matching framework groups in anallowedlist; any other declared framework reference is a violation.
Framework groups (framework_names/framework_name_prefixes) are declared in a top-level framework_references section — see framework references policy format for the YAML shape and matching rules.
Framework dependency example¶
framework_references:
forbidden_web:
framework_names: [Microsoft.AspNetCore.App]
contracts:
strict_framework_dependency:
- id: domain-no-aspnetcore
name: domain-must-not-reference-aspnetcore
source: MyApp.Domain
forbidden: [forbidden_web]
reason: Domain must stay free of the ASP.NET Core shared framework.
Framework allow-only example¶
framework_references:
core_only:
framework_names: [Microsoft.NETCore.App]
contracts:
strict_framework_allow_only:
- id: worker-allowed-frameworks
name: worker-may-only-reference-core
source: MyApp.Worker
allowed: [core_only]
reason: Worker projects may only reference the core shared framework.
The source of every framework dependency/allow-only contract must be listed in analysis.target_assemblies; a name that isn't a declared target assembly fails policy loading with an actionable error instead of silently being skipped.
Semantics¶
Both families detect direct, statically declared framework references only — but resolve them through a real, per-target-framework MSBuild design-time build (via Buildalyzer), not raw XML parsing. This means:
Conditionon both theFrameworkReferenceitem itself and its containingItemGroupis evaluated exactly asdotnet buildwould evaluate it, separately for each of the project's configured target frameworks.- Declarations contributed by imported
.props/.targetsfiles (includingDirectory.Build.propsand SDK-injected targets) are included, since MSBuild's own evaluation processes them. - Every discovered reference is classified explicit (authored by the project or one of its imports) or implicit (SDK-injected, e.g.
Microsoft.NETCore.App, via MSBuild'sIsImplicitlyDefineditem metadata).
FrameworkReference items carry no Version attribute, so there is no version resolution and no dependency_depth field — framework-reference governance has no transitive-dependency concept.
Framework dependency: for each framework group in forbidden, a violation is reported per matched FrameworkReference, aggregated into one violation per forbidden group naming every matched framework reference.
Framework allow-only: a violation is reported once per source, listing every declared FrameworkReference that does not match any framework group in allowed, sorted by framework name with duplicates removed.
Violations identify the source project/assembly, the forbidden framework group (for framework_dependency), and each matched framework reference by name and its real evaluated target framework (e.g. Microsoft.AspNetCore.App (net10.0)), so the same framework name applicable to two different target frameworks in one multi-targeted project is distinguishable in output and baseline identity. Structured evidence — framework name, target framework, explicit/implicit classification, and the declaring project's path — is carried separately from the human-formatted string, for JSON/SARIF/Testing API consumers.
ignored_violations entries use the same source_type/forbidden_reference/reason shape as other contract families; here source_type holds the source assembly name and forbidden_reference holds the framework name.
Configuration validation¶
Three safety checks run as part of CheckConfiguration (the same pass that already validates packages/external_dependencies group references), so misconfiguration or an evaluation failure surfaces as a visible failure instead of a contract silently matching nothing:
- Unknown or unusable framework groups. A framework group name referenced by a
forbidden/allowedlist that isn't declared inframework_references, or that is declared but has no non-emptyframework_names/framework_name_prefixesmatcher, is reported as anunknown framework group/invalid framework groupconfiguration violation. - Missing project metadata for
source. If a contract'ssourcedoes not correspond to any project discovered viaanalysis.solution/analysis.projects(including when project discovery never ran because neither is configured), ano project metadata discoveredconfiguration violation names the contract and its source. - MSBuild evaluation failure (fail closed). If the source project's real MSBuild design-time build does not succeed — for the whole project, or for any one of its configured target frameworks (e.g. that target framework isn't installed) — a
framework reference evaluation failedconfiguration violation names the contract, the source, and which target framework could not be evaluated. The contract's own check never reports a false-clean result on the basis of data it could not actually evaluate.
Framework reference contracts vs package dependency contracts vs external dependency contracts¶
These checks operate at different boundaries and are independent of one another:
- Framework reference dependency/allow-only contracts (this page) check declared MSBuild
FrameworkReferenceitems — the shared-framework surface a project opts into, independent ofPackageReference. - Package dependency contracts (
strict_package_dependency/audit_package_dependency) check declared NuGet package references. - External dependency contracts (
strict_external/audit_external) check observed type references to vendor/framework types in compiled code, including method-body IL scanning.
Scope: what's not covered here¶
Only single-source contracts are supported in this release — reusable multi-source/glob authoring across many projects from one contract is a deferred follow-up. Detecting actual framework API usage in compiled code (Roslyn/semantic analysis) is out of scope; this is a pure declaration-level check. Implicit SDK-provided framework availability that isn't declared via an explicit FrameworkReference item is not governed.