Skip to content

apm-policy.yml schema

The apm-policy.yml schema. One file per org or repo. Loaded by apm install, apm audit --ci, apm policy status, and the install preflight before any package is written to disk.

For the workflow (where to put the file, how to roll it out), see Govern with apm-policy.yml. For CLI usage of apm policy status, see apm policy. For the wider governance picture (rulesets, registry proxy, CI gating), see Governance overview.

Discovery order, in priority:

  1. --policy <ref> flag on apm install or apm audit.
  2. Auto-discovery from the project’s git remote — fetches <owner>/.github/apm-policy.yml via the GitHub Contents API.

The <ref> accepts:

  • A local file path.
  • An https:// URL (plain http:// is rejected).
  • The literal string org (force git-remote auto-discovery).
  • <owner>/<repo> shorthand (defaults to github.com).
  • <host>/<owner>/<repo> for GHES or other hosts.
FieldTypeDefaultRequiredNotes
namestring""noHuman label. Surfaces in apm policy status.
versionstring""noFree-form. Useful for change tracking.
extendsstring or nullnullnoParent policy reference. See Inheritance.
enforcementenumwarnnooff / warn / block. See Enforcement modes.
fetch_failureenumwarnnowarn / block. Behavior when a remote policy cannot be fetched or parsed.
cacheobject{ttl: 3600}noCache settings for remote policy fetches.
dependenciesobjectsee sectionnoRules over APM dependencies.
mcpobjectsee sectionnoRules over MCP servers (direct and transitive).
compilationobjectsee sectionnoRules over apm compile outputs.
manifestobjectsee sectionnoRules over apm.yml content.
unmanaged_filesobjectsee sectionnoRules over files in target directories not tracked by the lockfile.

Unknown top-level keys produce a warning, never an error — so newer policy files load on older clients.

enforcement is the global outcome dial. Per-rule severities feed into this dial:

ModeBehavior
offPolicy is loaded and reported, but never blocks. Useful during rollout.
warnViolations print [!] warnings but exit code stays 0. Default.
blockViolations print [x] errors and exit non-zero. apm install aborts before writing to disk.

fetch_failure controls fail-closed behavior on the policy fetch itself (network down, malformed YAML, host mismatch). Set to block in production CI to refuse to run when policy cannot be loaded.

FieldTypeDefaultNotes
ttlinteger3600Seconds. Must be > 0. Applies to remote extends: and URL fetches.

Rules over the dependencies: and mcp: blocks declared in consumer apm.yml files.

FieldTypeDefaultNotes
allowlist of patterns or nullnullnull = no opinion. [] = nothing allowed. [...] = only these.
denylist of patterns[]Always wins over allow.
requirelist of refs[]Packages every consumer manifest must include.
require_resolutionenumproject-winsproject-wins / policy-wins / block — how to resolve version conflicts on required packages.
max_depthinteger50Maximum transitive dependency depth. Must be > 0.

Patterns are matched against <owner>/<repo> (or <host>/<owner>/<repo>). Wildcards via shell-style globs, e.g. contoso/*.

Rules over MCP server references, including transitive ones declared by deep dependencies.

FieldTypeDefaultNotes
allowlist or nullnullSame null/empty/list semantics as dependencies.allow.
denylist[]Always wins.
transport.allowlist or nullnullAllowed transports: stdio, sse, http, streamable-http. null = no opinion.
self_definedenumwarnallow / warn / deny — treatment of MCP servers defined inline in apm.yml.
trust_transitivebooleanfalseWhen false, transitive MCP servers must be explicitly allow-listed.
FieldTypeDefaultNotes
target.allowlist or nullnullAllowed apm compile targets, e.g. vscode, claude, all.
target.enforcestring or nullnullIf set, apm compile must select this target.
strategy.enforceenum or nullnulldistributed / single-file. Pins the compilation strategy.
source_attributionbooleanfalseRequire source-attribution headers in compiled outputs.
FieldTypeDefaultNotes
required_fieldslist of strings[]Top-level keys every apm.yml must declare (e.g. description, license).
scriptsenumallowallow / deny — whether scripts: blocks are permitted.
content_typesobject or nullnull{allow: [...]}. Restricts primitive content types (e.g. skill, prompt).
require_explicit_includesbooleanfalseWhen true, manifests must declare an explicit includes: list rather than rely on directory globs.

Files in primitive target directories that are not recorded in apm.lock.yaml.

FieldTypeDefaultNotes
actionenumignoreignore / warn / deny. deny blocks installs that would leave drift.
directorieslist of paths[]Subset of target directories to check. Empty = all known target directories.

extends: resolves a parent policy. Maximum chain depth is 5; cycles are rejected.

extends: accepts:

  • org — the same org’s .github/apm-policy.yml.
  • <owner>/<repo> — another repo on the same host.
  • https://... — a direct URL.

For supply-chain safety, extends: references are pinned to the leaf policy’s host — a policy fetched from github.com cannot extend one on evil.example.com.

The child can tighten the parent but never relax it:

Field familyMerge rule
enforcementStricter wins (block > warn > off).
fetch_failureChild overrides if set.
cache.ttlmin(parent, child).
*.allow listsSet intersection. null is transparent (no opinion).
*.deny / require listsUnion, deduplicated, parent order preserved.
dependencies.max_depthmin(parent, child).
dependencies.require_resolutionStricter wins (block > policy-wins > project-wins).
mcp.self_definedStricter wins (deny > warn > allow).
mcp.trust_transitiveLogical AND (true only if both sides true).
manifest.scriptsStricter wins (deny > allow).
unmanaged_files.actionStricter wins (deny > warn > ignore).
compilation.*.enforceFirst non-null wins (parent precedence).
compilation.source_attributionLogical OR.

A merged chain is reported by apm policy status with each layer’s source attributed.

For every allow: field, the three states are distinct:

ValueMeaningInheritance behavior
omitted”no opinion”Transparent during merge.
[]”explicitly nothing”Intersects to nothing downstream.
[...]”only these patterns”Intersected with child list.

deny and require lists are always tuples (omitted = empty); they accumulate by union during merge.

# .github/apm-policy.yml -- shipped from contoso/.github
name: contoso-baseline
version: "2025.05"
extends: contoso-enterprise/policy
enforcement: block
fetch_failure: block
cache:
ttl: 1800
dependencies:
allow:
- contoso/*
- microsoft/apm-skills-*
deny:
- "*/legacy-*"
require:
- contoso/security-baseline
require_resolution: policy-wins
max_depth: 25
mcp:
allow:
- github/github-mcp-server
- contoso/internal-mcp-*
transport:
allow:
- stdio
- streamable-http
self_defined: deny
trust_transitive: false
compilation:
target:
allow:
- vscode
- claude
strategy:
enforce: distributed
source_attribution: true
manifest:
required_fields:
- description
- license
scripts: deny
content_types:
allow:
- skill
- prompt
- instruction
require_explicit_includes: true
unmanaged_files:
action: deny
directories:
- .github/instructions
- .github/prompts