Contract Registry
The contract registry is the network allowlist for smart-contract packages. It records the exact package versions, hashes, runtime, review metadata, and status that the network has approved for use.
The registry is different from Package Provenance:
- provenance proves who signed a package descriptor and whether it still matches the WASM, manifest, and runtime being instantiated;
- registry approval proves the network has accepted that signed package for new contract instances or release workflows.
Production networks usually use both. Provenance establishes package identity and integrity. The registry decides whether that package is allowed.
Where It Fits
Registry validation happens during transaction INSTANTIATE_CONTRACT after provenance validation:
- The instantiate payload is checked against the deployed code and manifest.
- Package provenance is validated when present or required.
- Accepted provenance produces package name, package version, descriptor hash, and accepted signer metadata.
- Registry validation looks for a matching registry entry.
- If the entry exists and its status is allowed, a registry reference is stored in the contract metadata.
This ordering matters. The registry lookup uses accepted provenance. Without accepted provenance, required registry mode cannot know which package descriptor to match and fails with CONTRACT_REGISTRY_APPROVAL_REQUIRED.
What Gets Registered
A registry entry identifies one approved package by exact hashes:
{
"id": "pkg-report-store-0.1.0",
"packageName": "report-store",
"packageVersion": "0.1.0",
"codeHash": "<sha256-of-wasm>",
"manifestHash": "<canonical-manifest-sha256>",
"descriptorHash": "<sha256-of-package-descriptor>",
"runtime": "wasm-assemblyscript-v1",
"status": "approved",
"auditMetadata": {
"reviewId": "SEC-1234"
},
"approvalMetadata": {
"approvedFor": "production"
}
}| Field | Meaning | Review guidance |
|---|---|---|
id | Registry entry id. | Use a stable id that includes package name, version, and environment when useful. |
packageName | Package identity from the descriptor. | Must match the signed package descriptor. |
packageVersion | Package version from the descriptor. | Must match the signed package descriptor and release record. |
codeHash | SHA-256 hash of the approved WASM bytes. | Must match the descriptor and deployed code hash. |
manifestHash | Canonical hash of the approved manifest. | Must match the descriptor and instantiate manifest hash. |
descriptorHash | SHA-256 hash of the canonical package descriptor. | Must match accepted package provenance. |
runtime | Runtime accepted for the package. | Current registry payloads accept wasm-assemblyscript-v1. |
status | Approval status for new use. | approved, suspended, or retired. |
auditMetadata | Security/review evidence. | Use for audit ids, reviewer notes, risk classification, or review timestamps. |
approvalMetadata | Governance/release evidence. | Use for change ids, approval scope, environment, or launch tickets. |
The registry row also records the approving actor, transaction hash, creation height, and update height. Those fields are written by consensus execution, not by the package author.
Matching Rules
During registry validation, NOOSChain searches contract_package_registry by:
- package name;
- package version;
- code hash;
- manifest hash;
- descriptor hash.
All five must match. This prevents a package name and version from being reused with different bytecode, a different manifest, or a different signed descriptor.
The lookup comes from accepted provenance:
accepted provenance
packageName
packageVersion
descriptorHash
+
instantiate payload
codeHash
manifestHash
=
registry lookup keyIf a package has the same name and version but a different hash, it is a different package for registry purposes and needs its own review and registry entry.
Statuses
| Status | Meaning | Typical use |
|---|---|---|
approved | The package is allowed for new instantiations when registry policy permits approved entries. | Normal production use after review. |
suspended | The package is temporarily blocked from new use. | Incident investigation, audit expiry, key concern, or pending review. |
retired | The package is intentionally withdrawn from new use. | Replaced package, deprecated behavior, or end-of-life version. |
Status changes affect new instantiations and release checks. They do not rewrite old blocks, delete deployed contracts, or make historical replay impossible.
Registry Policy
The default registry policy is:
{
"mode": "optional",
"allowedStatuses": ["approved"]
}mode controls whether registry approval is mandatory:
| Mode | Behavior |
|---|---|
optional | Instantiation can proceed without accepted provenance or without a matching registry entry. If accepted provenance matches an entry with a disallowed status, instantiation fails. |
required | Instantiation must have accepted provenance, must match a registry entry, and that entry must have an allowed status. |
allowedStatuses controls which registry statuses are valid for use. Production policy normally allows only approved.
Unlike package provenance policy, which is now loaded from contract_provenance_policies/default, registry policy is currently supplied by the protocol execution context, with the default above when no explicit policy is provided. Treat it as a protocol/network configuration decision: if the network wants registry approval to be a hard gate, run with required registry policy.
Instantiate Outcomes
When registry validation succeeds, the contract metadata includes a compact registry reference:
{
"contractRegistry": {
"entryId": "pkg-report-store-0.1.0",
"packageName": "report-store",
"packageVersion": "0.1.0",
"status": "approved"
}
}When it fails, common deterministic failure codes are:
| Failure code | Meaning |
|---|---|
CONTRACT_REGISTRY_APPROVAL_REQUIRED | Registry policy is required, but there is no accepted provenance to identify the package. |
CONTRACT_REGISTRY_ENTRY_NOT_FOUND | Registry policy is required and no entry matched package name, version, code hash, manifest hash, and descriptor hash. |
CONTRACT_REGISTRY_ENTRY_NOT_APPROVED | A matching entry exists, but its status is not in allowedStatuses. |
CONTRACT_REGISTRY_ENTRY_ALREADY_EXISTS | A registration attempted to reuse an existing registry id or the same package/version/code/manifest tuple. |
Register A Package
The package helper can generate a registry payload during publishing:
npm run contracts:as-sdk:payloads -- --package "contract-packages/report-store-0.1.0" --contract-id "contract-report-store" --owner-user-id "user-admin" --organization-id "org-noos" --registry-id "pkg-report-store-0.1.0" --approval-metadata-json '{"approvedFor":"tutorial"}'Submit the generated payload as a chain-admin transaction:
npm run noos -- tx build-and-submit --type REGISTER_CONTRACT_PACKAGE --payload-file "contract-packages/report-store-0.1.0/payloads/register-contract-package.json" --signer-public-key "<ADMIN_PUBLIC_KEY_PEM>" --signer-private-key-path "<ADMIN_PRIVATE_KEY_PATH>" --yesThis submits transaction REGISTER_CONTRACT_PACKAGE.
Only actors with chain:admin can register registry entries. Registration fails if the id already exists, or if another entry already has the same package name, package version, code hash, and manifest hash tuple.
Manual Payload
If you are not using the package helper, create the payload directly:
{
"id": "pkg-report-store-0.1.0",
"packageName": "report-store",
"packageVersion": "0.1.0",
"codeHash": "<sha256-of-wasm>",
"manifestHash": "<canonical-manifest-sha256>",
"descriptorHash": "<sha256-of-package-descriptor>",
"runtime": "wasm-assemblyscript-v1",
"status": "approved",
"auditMetadata": {
"reviewId": "SEC-1234",
"reviewedAt": "2026-06-05T00:00:00.000Z"
},
"approvalMetadata": {
"changeControlId": "CHG-1234",
"environment": "production"
}
}Then submit it:
npm run noos -- tx build-and-submit --type REGISTER_CONTRACT_PACKAGE --payload-file "register-contract-package.json" --signer-public-key "<ADMIN_PUBLIC_KEY_PEM>" --signer-private-key-path "<ADMIN_PRIVATE_KEY_PATH>" --yesThis submits transaction REGISTER_CONTRACT_PACKAGE.
Before submitting a manual payload, recompute all hashes from the package files. Do not copy hash values from an untrusted release note.
Suspend Or Retire A Package
Use transaction UPDATE_CONTRACT_PACKAGE_STATUS when a package should stop being accepted for new production use.
Suspend a package while review is pending:
{
"id": "pkg-report-store-0.1.0",
"status": "suspended",
"approvalMetadata": {
"reason": "audit-expired",
"ticket": "SEC-2345"
}
}Retire a package after replacement:
{
"id": "pkg-report-store-0.1.0",
"status": "retired",
"approvalMetadata": {
"reason": "replaced-by-0.2.0"
}
}Restore approval after review:
{
"id": "pkg-report-store-0.1.0",
"status": "approved",
"auditMetadata": {
"reviewId": "SEC-3456",
"result": "accepted"
},
"approvalMetadata": {
"reason": "review-complete"
}
}Submit any of those payloads with:
npm run noos -- tx build-and-submit --type UPDATE_CONTRACT_PACKAGE_STATUS --payload-file "update-contract-package-status.json" --signer-public-key "<ADMIN_PUBLIC_KEY_PEM>" --signer-private-key-path "<ADMIN_PRIVATE_KEY_PATH>" --yesThis submits transaction UPDATE_CONTRACT_PACKAGE_STATUS.
Status updates preserve the package identity and hashes. They only change status, audit metadata, approval metadata, approver fields, transaction hash, and update height.
Relationship To Releases
Release workflow records tie a registry package to a target contract id, optional source contract id, rollout status, migration, audit metadata, approval metadata, and rollback trail.
Before a production release advances, check:
- the registry entry exists;
- the registry status is allowed by policy;
- package name and version match the release;
- code hash, manifest hash, and descriptor hash match the signed package;
- audit and approval metadata satisfy the release gate;
- the target contract uses the expected code and manifest;
- suspended or retired packages are not promoted.
The registry is the package approval layer. Release workflow is the deployment control layer.
Review Checklist
Use this checklist with the deeper Package Provenance review checklist.
| Check | What to verify | Why it matters |
|---|---|---|
| Provenance accepted | The package can produce accepted provenance under the active provenance policy. | Required registry mode needs package identity from provenance. |
| Registry id | The id is stable and scoped correctly for the network or environment. | Prevents confusing production and test approvals. |
| Package identity | Name and version match the signed descriptor and release plan. | Prevents approving the wrong package line. |
| Code hash | Registry codeHash matches the packaged WASM and instantiate payload. | Prevents bytecode substitution. |
| Manifest hash | Registry manifestHash matches the canonical reviewed manifest. | Prevents authorization, bucket, ABI, or migration drift. |
| Descriptor hash | Registry descriptorHash matches accepted provenance. | Ensures the registered package is the signed package. |
| Runtime | Runtime is supported and matches descriptor and manifest. | Prevents runtime compatibility surprises. |
| Status | Status is approved for new production use. | Suspended or retired packages should not be instantiated. |
| Audit metadata | Review id, reviewer, date, scope, and result are recorded when required. | Incident response needs meaningful evidence. |
| Approval metadata | Change id, environment, release scope, and approver intent are recorded. | Operators need to know why this package was approved. |
| Release alignment | Registry entry matches the target release and rollback plan. | Prevents release records from pointing at stale packages. |