Project Metadata Contracts¶
Project metadata contracts enforce rules over statically declared project and assembly metadata surfaces: selected MSBuild properties, InternalsVisibleTo declarations, and declared ProjectReference targets discovered from .csproj files.
Two families are covered on this page:
- Project metadata (
strict_project_metadata/audit_project_metadata) — selected discovered projects must satisfy required property values, must not carry forbidden property values, may only expose explicitly allowed friend assemblies, and must not declare forbidden project references.
These contracts operate on project discovery output, so they require analysis.solution or analysis.projects to discover and parse matching .csproj files. Metadata-only policies may omit analysis.target_assemblies; the runner still parses project metadata even when no build output is available.
Example¶
analysis:
solution: ArchLinterNet.slnx
contracts:
strict_project_metadata:
- id: core-project-metadata
name: core-project-metadata
projects:
- src/ArchLinterNet.Core/ArchLinterNet.Core.csproj
required_properties:
Nullable: enable
TreatWarningsAsErrors: true
allowed_friend_assemblies:
- ArchLinterNet.Core.Tests
forbidden_project_references:
- tests/**/*.csproj
reason: Core packaging and friend-assembly boundaries must stay intentional.
Semantics¶
Project metadata contracts match discovered projects by their repo-relative .csproj path.
Required properties: every entry in required_properties must be present on the discovered project with the exact configured value. The value may come from the project file itself or from the nearest applicable Directory.Build.props chain that discovery can parse statically.
Forbidden properties: every entry in forbidden_properties forbids that exact property/value pair. A project that sets the same value is a violation.
Allowed friend assemblies: allowed_friend_assemblies may be omitted (the key is absent from the YAML), set to an empty list, or set to a non-empty list. Omitted means "do not check friend assemblies" (the contract has no friend-assembly expectation). An empty list ([]) means "deny all" — every discovered InternalsVisibleTo declaration is a violation. A non-empty list is an explicit allowlist: every discovered InternalsVisibleTo declaration must appear in that list. Discovery reads both MSBuild InternalsVisibleTo items in .csproj files and assembly-level [assembly: InternalsVisibleTo("...")] attributes in project .cs files.
Forbidden project references: every pattern in forbidden_project_references is matched against the discovered project's repo-relative referenced .csproj paths using the same project-path glob semantics as analysis.project_include / analysis.project_exclude.
Ignored violations / baselines: ignored_violations uses source_type = the discovered project path and a deterministic forbidden_reference such as required_property:IsPackable=false, forbidden_property:IsTestProject=true, friend_assembly:MyApp.Tools, or project_reference:tests/MyApp.Tests/MyApp.Tests.csproj.
Violations identify the project path, the metadata kind (required_property, forbidden_property, friend_assembly, or project_reference), the relevant key/value or matched path, and the source file path when discovery can determine it.
Configuration validation¶
Two safety checks run before execution:
- Missing project selector. A contract with no non-blank
projectsentry fails policy loading. - Missing expectation. A contract with no
required_properties,forbidden_properties,allowed_friend_assemblies, orforbidden_project_referencesfails policy loading.
CheckConfiguration also reports a visible no project metadata discovered configuration violation when a configured project path is not present in project discovery output. This avoids a silent false green where the contract can never evaluate because no .csproj metadata was discovered for that path.
Scope: what is and is not covered here¶
Project metadata contracts are static .csproj/Directory.Build.props analysis only:
- they do check statically declared scalar properties, friend assemblies declared through project items or source-level assembly attributes, and declared
ProjectReferenceitems; - they do not run MSBuild targets or build the project;
- they do not perform full conditional/import evaluation for every possible MSBuild construct;
- they do not replace package validation, signing validation, or runtime behavior checks.