The library model - vendor-at-fetch

modusops-templates is a source, not a live dependency. The tooling pulls a template from a GitHub Release and writes it into your repo as a committed, pinned file. Think npm, but the package is vendored and reviewed in your own PR.

npm modusOps templates
registry modusops-templates releases
npm install <pkg> Add-MOTemplate
npm update Update-MOTemplate
package-lock.json .modusops.lock
npm ci integrity check Test-MOTemplate (offline)
editing node_modules (don’t) editing a vendored template (managed; reported as drift)

Why releases, not a package feed

YAML has no package ecosystem, and PSResourceGet is module/script-centric - you cannot cleanly put raw YAML in a NuGet feed and pull it without wrapping it as a module, which would conflate module-install with template-fetch and lose the vendored-file + lockfile-SHA + PR-review properties. GitHub Release assets + vendor-at-fetch keeps all three.

The lockfile is the trust anchor

.modusops.lock records, per template: the source URL, the version/tag, the asset name, and a SHA256. That hash - not the release tag - is the integrity anchor, because release assets are mutable.

{
  "lockfileVersion": 1,
  "source": "https://github.com/adrian-andersson/modusops-templates",
  "defaults": { "platform": "gh" },          // set once; commands stop re-taking -Platform
  "templates": {
    "registerModusOpsFeeds": {               // a pipeline building block
      "version": "v1", "platform": "gh", "category": "pipeline", "kind": "compositeAction",
      "asset": "gh.registerModusOpsFeeds.zip",
      "path": "templates/registerModusOpsFeeds/action.yml",
      "sha256": "....",
      "url": "https://github.com/.../gh.registerModusOpsFeeds.zip"
    },
    "templatesRepoPRValidation": {            // repo furniture, vendored to a fixed dest
      "version": "v1", "platform": "gh", "category": "repoScaffold", "kind": "workflow",
      "repoType": "templatesRepo",
      "asset": "gh.workflow.templatesRepoPRValidation.yml",
      "path": ".github/workflows/prValidation.yml",
      "sha256": "....",
      "archetype": "templateLibrary", "archetypeVersion": "v1"
    }
  }
}

The anchor is always a single file SHA256 — for a composite action it’s the inner action.yml. Test-MOTemplate recomputes each vendored file’s hash and compares it to the lock - entirely offline, so it is a cheap CI gate, and it reports the pinned Version per row (add -CheckUpdate to also flag when a newer release is available). repoScaffold entries also carry a repoType naming the kind of repo they furnish. (Versions are rolling integers, vN - see Authoring templates.)

The verbs

Verb Does
Find-MOTemplate Discover templates / versions in a release.
Add-MOTemplate Vendor a pinned template + record it in the lockfile (always pin; never blind “latest”).
Update-MOTemplate Re-pull at a newer version, rewriting only files whose bytes changed.
Test-MOTemplate Offline integrity check against the lockfile.
Get-MOTemplate List installed templates (reads the lockfile).

To set a default platform once (Set-MOPlatform), or stamp a whole set of furniture in one call (Find-MOArchetype / Add-MORepoScaffold), see Repo scaffolding (archetypes).

Configurable source

The library defaults to the public repo but accepts an override URL, so an enterprise can vendor from an internal mirror it controls - the same code path, no public fetch. See The security-prominent stance.