Skip to content

Release Trust and Loader

ReleaseLoader is the shared verifier for local packaged releases, compiled publication previews, PostgreSQL-backed release snapshots, and MCP runtime scopes. It is implemented in src/rimthan_workflow_registry/loader.py and relies on canonical JSON, digest checks, path safety, schema validation, instruction linting, workflow catalogue validation, and optional Ed25519 trust roots.

Load flow

This flow applies before an active release can be served by MCP or inserted as a compiled release.

Path and byte safety

The loader is constructed with an explicit release_root. It rejects a symlink release root, resolves the path, requires it to be a directory, and reads manifest.json with a configurable maximum size. Artifact loading uses safe relative paths from the manifest, byte limits, and digest/size verification. JSON artifacts must be canonical JSON with trailing newline and must match their manifest identity fields.

Registry assets get an extra content check: the asset's embedded content string is encoded as UTF-8, and its byte_length and sha256 must match. Non-schema instruction assets are linted through security.lint_instructions.

Manifest sections

ReleaseLoader.load supports both legacy and workflow-engine manifest sections:

  • modules into ModuleDefinition;
  • presentation_bundles into PresentationBundle;
  • workflow_definitions into immutable JSON artifacts keyed by workflow ID/version;
  • workflow_steps keyed by workflow ID/version/step ID;
  • registry_assets keyed by kind/asset ID/version;
  • validator_definitions keyed by validator ID/version.

It checks ordering, duplicate identities, one presentation bundle per route/locale, orphaned steps, alias collisions, and then delegates workflow cross-reference and graph invariants to validate_workflow_catalogue in rimthan_workflow_registry.workflow_engine.

Trust roots and signatures

Published release trust is implemented in src/rimthan_workflow_registry/trust.py and documented in docs/reference/release-trust.md. The signed payload is:

text
rimthan.workflow-registry.manifest.v1 + NUL + canonical_json(manifest with signatures = [])

verify_manifest_signatures validates the trust-root schema, rejects duplicate key IDs and duplicate physical Ed25519 public keys, requires manifest signatures sorted by key ID with no duplicates, ignores unknown/revoked/out-of-scope/invalid signatures, and succeeds only when the number of verified active signatures meets minimum_valid_signatures.

Keys are scoped to explicit registry IDs and publishers. Public keys and signatures use unpadded base64url with exact byte-length checks. Ed25519ManifestSigner in src/rimthan_publication/signer.py is the narrow signing counterpart used by Admin API publication.

Local versus published releases

Local development releases can be trusted by explicit path and optional --trusted-manifest-sha256. They may have no signatures. Published releases must have source revision, canonical manifest bytes, and enough valid signatures for the configured trust root. A manifest digest pin does not substitute for signature verification on a published release.

The CLI exposes this through rimthan-workflow verify-release --registry ... --trust-root ... and optional --trusted-manifest-sha256. When a release verifies, RegistryRelease.verified_signing_key_ids carries the trusted key IDs into downstream resolution/materialization: legacy ProjectMaterializer.build_lock writes registry_verified_signing_key_ids into workflow.lock.json, and workflow-engine Resources/checkpoints expose the verified release identity and manifest digest rather than trusting unverified bytes.

Runtime relationships

  • Publication Pipeline compilers verify compiled releases by writing a temporary release directory and loading it with ReleaseLoader before insertion.
  • PostgreSQL Store reconstructs database releases into temporary exact-byte snapshots and loads them with ReleaseLoader for MCP.
  • McpScope.load uses ReleaseLoader for local and database-backed scopes.
  • ImmutableResourceCatalogue serves only bytes from a loaded RegistryRelease.

Tests

  • tests/test_loader.py covers release loading, manifest and artifact integrity, canonical encoding, and path safety.
  • tests/test_trust.py covers signature verification, trust-root scoping, threshold behavior, duplicate keys, revoked/unknown keys, and invalid signatures.
  • tests/test_workflow_engine.py covers workflow catalogue validation, immutable workflow resources, and corrupt active refresh retaining last-good scope.
  • tests/test_postgres_publication_e2e.py covers database byte and artifact identity triggers in addition to loader verification.

Focused validation

  • uv run pytest tests/test_loader.py tests/test_trust.py
  • uv run pytest tests/test_workflow_engine.py -k "corrupt_active_refresh or compiles_to_verified"
  • CLI smoke: uv run rimthan-workflow verify-release --registry registry/releases/0.2.0 for a local release path that is not excluded in the current checkout.

Generated from the committed OpenWiki knowledge bundle.