# Catalog component contract — content-addressed distribution (ADR-046) # # Producer: publish the contract schema as a content-addressed OCI Domain # artifact — an immutable referrers anchor (once per id) plus one referrer per # version carrying its org.opencontainers.image.version annotation. # Consumer: resolve a catalog's requires.contract to an immutable digest pinned # in catalog.lock.ncl, and validate manifests against the pulled contract. # # Registry credentials resolve from the active workspace's .ontoref manifest + # SOPS via the same machinery as `prvng integration` (ADR-042). Run producer # recipes from a workspace whose scope includes domains//. _contract_cli := "core/nulib/platform/oci/contract_cli.nu" _nulib := justfile_directory() / "core" / "nulib" # Publish the referrers anchor for a contract id (run once) — prints subject digest [doc("Publish the referrers anchor for a contract id; prints the subject digest for requires.contract.subject")] contract-publish-anchor id participant="provisioning" registry="": PROVISIONING="{{justfile_directory()}}" NU_LIB_DIRS="{{_nulib}}" nu "{{_contract_cli}}" publish-anchor "{{id}}" --participant "{{participant}}" --registry "{{registry}}" # Attach a contract version as a referrer to the anchor [doc("Attach a contract version as a referrer — args: contract_file id version subject")] contract-publish-version contract_file id version subject participant="provisioning" registry="": PROVISIONING="{{justfile_directory()}}" NU_LIB_DIRS="{{_nulib}}" nu "{{_contract_cli}}" publish-version "{{contract_file}}" "{{id}}" "{{version}}" "{{subject}}" --participant "{{participant}}" --registry "{{registry}}" # Select the push registry from a pluggable source — apply with: eval "$(just contract-use-registry ...)" [doc("Resolve push registry from a source (sops|api|literal|env) and emit export lines to eval")] contract-use-registry kind value="" endpoint_key="endpoint" user_key="username" pass_key="password" vault_id="": @PROVISIONING="{{justfile_directory()}}" NU_LIB_DIRS="{{_nulib}}" nu "{{_contract_cli}}" select-registry --kind "{{kind}}" --value "{{value}}" --endpoint-key "{{endpoint_key}}" --user-key "{{user_key}}" --pass-key "{{pass_key}}" --vault-id "{{vault_id}}" # Resolve a catalog's requires.contract to a digest and pin catalog.lock.ncl [doc("Resolve requires.contract to an immutable digest and write catalog.lock.ncl")] contract-resolve catalog_root manifest: PROVISIONING="{{justfile_directory()}}" NU_LIB_DIRS="{{_nulib}}" nu "{{_contract_cli}}" resolve "{{catalog_root}}" "{{manifest}}" # Validate a manifest against its declared contract (resolve + typecheck) — CI gate [doc("CI gate: resolve a manifest's contract and typecheck the manifest against it")] contract-validate manifest catalog_root="": PROVISIONING="{{justfile_directory()}}" NU_LIB_DIRS="{{_nulib}}" nu "{{_contract_cli}}" validate "{{manifest}}" --catalog-root "{{catalog_root}}"