CellScript Wiki
Tutorial 12: Registry Artifacts End to End
Tutorial 12: Registry Artifacts End to End
Status: current tutorial for publishing and inspecting CellScript and non-CellScript artifacts in the public Registry.
The Registry is not limited to dependency packages. It distinguishes source libraries, profile libraries, CKB runtime verifiers, deployable contracts, reproducible binaries, and copy-only templates. This tutorial uses the native CellScript path first, then the generic artifact path.
1. Authorise the first publish
Start from the package or artifact directory, not from an empty browser form:
cellc publish --authorisecellc creates the delegated P-256 key, stores it as pending in the local OS
keychain, opens a 15-minute exact-coordinate Registry session, waits for wallet
approval, and then resumes the original publish. The private key never enters
the browser. The Registry atomically registers the public key, claims or reviews
the namespace, completes the session, and records the audit trail. Use
--no-open to print the browser URL for a remote or terminal-only environment.
The browser token is fragment-only, survives a same-tab refresh, and is removed on completion or expiry. Completed or review-pending sessions remain readable to the polling CLI for 24 hours so an approval committed near the deadline can be recovered. A local polling timeout preserves the pending key unless the Registry confirms cancellation or pending-session expiry.
The production site has no network selector and accepts mainnet evidence only.
Pudge testing uses https://testnet.registry.cellscript.dev/registry, with a
different API origin, database, object store, signing identity, wallet state,
and testnet-only evidence. Start that flow explicitly with:
cellc publish --authorise --api-url https://api.testnet.registry.cellscript.devSandbox records disappear from discovery after 72 hours and their source bytes are purged after a 24-hour grace period; this does not erase Pudge chain history. The explicit capability-submit and namespace-claim commands remain available for CI, external-wallet signing, and recovery.
2. Publish a CellScript source library
Add the namespace to Cell.toml:
[package]
name = "math"
version = "1.0.0"
namespace = "acme"Verify and publish:
cellc package verify --json
cellc publish --dry-run
cellc publish --authorise # first publish
cellc publish # later publishes with an active delegated keyUse --artifact-kind profile_library when the package is a named CellScript
profile library. Both kinds use compiler-backed verification and remain valid
Cell.toml dependencies.
3. Publish a deployable CKB contract
Create Artifact.toml:
schema = "cellscript-registry-artifact"
namespace = "acme"
name = "vault-lock"
release = "1.0.0"
kind = "deployable_contract"
language = "rust"
bundle = "vault-lock.bundle.json"
description = "Vault lock Script"Create a closed profile contract first. Its ABI hash is the CKB Blake2b-256 of the immutable ABI object:
{
"schema": "cellscript-registry-profile-contract-v1",
"artifact_kind": "deployable_contract",
"profile": "ckb_executable",
"build": {
"target": "riscv64imac-unknown-none-elf",
"toolchain": "rustc 1.97.1",
"profile": "release",
"source_revision": "<immutable revision>",
"reproducible": false
},
"security": { "status": "review_required" },
"ckb": {
"vm_version": "2",
"script_role": "lock",
"hash_type": "data1",
"dep_type": "code",
"abi_hash": "<ABI object CKB Blake2b-256>"
}
}Canonicalize it recursively by key and put that JSON string in the immutable bundle. Each payload is base64-encoded bytes, not a path:
{
"schema": "cellscript-registry-bundle",
"namespace": "acme",
"name": "vault-lock",
"release": "1.0.0",
"profile": "ckb_executable",
"manifest_json": "<canonical cellscript-registry-profile-contract-v1 JSON>",
"objects": [
{ "role": "source", "content_base64": "..." },
{ "role": "executable", "content_base64": "..." },
{ "role": "abi", "content_base64": "..." }
]
}Validate before sending anything:
cellc publish --artifact-manifest Artifact.toml --dry-runThe CLI checks the coordinate, release, kind/language pair, bundle profile, required object roles, size limit, and computed hashes. Publish with:
cellc publish --artifact-manifest Artifact.tomlThe release initially reports:
verification_status = pending
deployment_status = undeployed
availability_status = activeAfter the independent verifier binds the source, executable, ABI, and profile
contract hashes, verification becomes hash_bound. That is an integrity claim,
not a claim about Script semantics, security review, or deployment.
4. Prove a reproducible build
Skip this step for the non-reproducible example above. If the signed profile
sets build.reproducible = true, or the kind is reproducible_binary, the
release remains evidence_required until independent builders reproduce the
same executable.
Each builder writes a bounded report:
{
"schema": "cellscript-reproduction-report-v2",
"builder_id": "builder-a",
"trust_domain": "independent-org-a",
"builder_public_key": "p256-spki:<base64-der>",
"environment": "<exact environment from the signed profile>",
"source_hash": "<CKB Blake2b-256>",
"build_recipe_hash": "<CKB Blake2b-256>",
"artifact_hash": "<CKB Blake2b-256>",
"build_log_hash": "<CKB Blake2b-256>",
"generated_at": "2026-08-02T00:00:00Z",
"signature": {
"algorithm": "p256-sha256",
"signature": "<base64url-fixed-signature>"
}
}Generate a signed report on each independent builder:
cellc auth reproducer create \
--builder-id builder-a \
--trust-domain independent-org-a \
--json > reports/builder-a-enrollment.json
cellc artifact reproduction-report acme/vault-lock@1.0.0 \
--artifact target/vault-lock \
--build-log reports/builder-a.log \
--builder-id builder-a \
--trust-domain independent-org-a \
--builder-key-id cap_<sha256-prefix> \
--builder-public-key 'p256-spki:<base64url-der>' \
--output reports/builder-a.jsonEach builder sends only the generated public policy_builder record to the
Registry operator. The private key stays in that builder's OS keychain. A CI
builder on Unix may pass --private-key-output <new-file> during enrollment,
import the mode-0600 file's PKCS#8 base64 value into its own secret manager as
CELLSCRIPT_REPRODUCER_PRIVATE_KEY_PKCS8_B64, and must not share that file.
Validate and combine at least two signed reports with distinct builder IDs, public keys, and trust domains:
cellc artifact reproduction-evidence acme/vault-lock@1.0.0 \
--report reports/builder-a.json \
--report reports/builder-b.json \
--output reproduced-build-promotion.jsonThe command verifies each P-256 report signature and fetches and verifies the
signed release, predecessor build evidence, source, recipe, artifact,
environment, and report identities. It does not execute the publisher's recipe.
A Registry operator reviews and submits the generated reproduced_build
promotion payload. The API also requires every builder to match its configured
policy, enforces a minimum number of trust domains, and records that policy's
canonical SHA-256 and threshold in the accepted evidence. Only then does
verification become verified; a reproducible executable cannot be recorded
as deployed before this transition.
5. Record a deployment on the Registry's fixed network
The deployment request is a signed
cellscript-registry-deployment / record_deployment payload sent to:
POST /v1/artifacts/acme/vault-lock/releases/1.0.0/deploymentsIt includes the published artifact_hash, equal data_hash, code_hash,
hash_type, dep_type, and the environment's OutPoint. The API requires a
separately granted deployment: capability for the same coordinate and prior
verified-build evidence; a publish: scope alone is insufficient.
The API first verifies the configured RPC chain identity. It calls
get_live_cell to prove that the OutPoint remains live and reads
get_transaction.tx_status to prove the creation transaction is committed and
obtain the block hash used for confirmation counting. It rejects a dead or
missing Cell, an uncommitted creation transaction, insufficient confirmation
depth, a data-hash mismatch, a Type Script hash mismatch, a network mismatch, or an
OutPoint that is not bound to the published executable. A successful request
appends deployment evidence and changes only deployment_status to
chain_verified.
For a DepGroup OutPoint, the API decodes the live Cell data as the canonical
Molecule OutPointVec and finds the matching live code member. It does not hash
the DepGroup container as though it were the executable.
6. Publish and resolve an LS-IDL Lock Script interface
For a Lock Script that follows LS-IDL 0.1, start with the original idl.json
bytes. Do not pretty-print or reserialise them after computing the commitment:
cellc artifact ls-idl validate --idl idl.json
cellc artifact ls-idl bind \
--idl idl.json \
--executable target/release/vault-lock \
--output target/release/vault-lock.ls-idl
cellc artifact ls-idl bundle \
--idl idl.json \
--executable target/release/vault-lock.ls-idl \
--source src/lib.rs \
--namespace acme \
--name vault-lock \
--release 1.0.0 \
--language rust \
--hash-type data1 \
--dep-type code \
--toolchain rust-1.97.1 \
--source-revision <40-hex-git-commit> \
--output artifact.bundle.json \
--artifact-manifest-output Artifact.toml
cellc publish --artifact-manifest Artifact.toml --dry-run --jsonAfter publishing and recording chain-verified deployment evidence, resolve the same bytes through either the CLI or canonical API:
cellc artifact ls-idl fetch \
--code-hash 0x<64-hex> \
--hash-type data1 \
--network mainnet \
--output idl.json
curl --fail \
'https://api.registry.cellscript.dev/v1/ckb/scripts/0x<64-hex>/interfaces/ls-idl?network=mainnet&hash_type=data1' \
--output idl.jsonThe compatibility route /idl/:code_hash returns the same original bytes.
The Registry proves the document schema, raw-byte digest, executable suffix,
and deployment identity. It does not prove that the Lock Script correctly
implements the interface, and it is not a security audit. See the
LS-IDL tutorial for the complete
cellc workflow and the
LS-IDL Registry profile for the
closed schema and trust boundary.
7. Inspect and consume the artifact
Open the artifact detail page or query the API:
curl --fail 'https://api.registry.cellscript.dev/v1/artifacts/acme/vault-lock'
curl --fail 'https://api.registry.cellscript.dev/v1/artifacts/acme/vault-lock/releases/1.0.0/evidence'Check these independently:
- artifact kind, profile, language, and consumption mode;
- source, executable, ABI, or recipe hashes;
- verification, deployment, and availability states;
- evidence producer and evidence hash;
- mainnet OutPoint, code hash, data hash, hash type, and dep type.
Do not use cellc install for this executable. cellc install accepts only
cellscript_source artifacts whose consumption mode is dependency.
Consume it explicitly:
cellc artifact fetch acme/vault-lock@1.0.0 --output vault-lock.bundle.json
cellc artifact verify --bundle vault-lock.bundle.json --receipt vault-lock.bundle.json.receipt.json
cellc artifact pin acme/vault-lock@1.0.0 --output Artifacts.lock --accept-hash-bound
cellc artifact reproduction-evidence acme/vault-lock@1.0.0 --report builder-a.json --report builder-b.json --output reproduced-build-promotion.json
cellc artifact record-deployment acme/vault-lock@1.0.0 --network mainnet --code-hash <hash> --hash-type data1 --dep-type code --tx-hash <tx_hash> --index 0 --capability-key-id <key_id>
cellc artifact cell-dep acme/vault-lock@1.0.0 --output CellDep.json --accept-hash-bound --rpc-url https://mainnet.ckb.dev/rpc
cellc artifact set-availability acme/vault-lock@1.0.0 --status yanked --reason "security advisory" --capability-key-id <key_id>
cellc artifact commitment acme/vault-lock@1.0.0 --output RegistryCommitment.jsoncell-dep fails until mainnet deployment evidence has been verified, then
rechecks that the deployment (and resolved DepGroup code member) is still live
at consumption time. Deployment mode must equal the immutable profile
contract. The commitment file contains canonical CSREGv1 Cell data;
current commitment still requires the API to read a sufficiently confirmed
live mainnet Cell and match its configured Type/Lock identities and both live
code CellDeps. When those Scripts and CellDeps are configured, the file
also contains a mainnet-only transaction intent. A compatible wallet completes
capacity, inputs, change, fee, witnesses, signatures, and broadcast.
Scheduled maintenance discovers exact Registry Type Script matches through the
CKB indexer. A sufficiently confirmed live matching commitment promotes the
current release to on_chain_committed; spending that Cell returns it to deployed; and spending
or replacing the deployment Cell returns it to verified_build. Accepted
evidence remains available for audit.
The transaction-intent and scanner code is implemented, but production does not claim a chain commitment until operators deploy and configure the canonical mainnet Registry Type Script, commitment custody Lock, and both code CellDeps.
For the isolated Pudge flow, use:
cellc publish --api-url https://api.testnet.registry.cellscript.dev
cellc artifact record-deployment acme/vault-lock@1.0.0 \
--network testnet \
--api-url https://api.testnet.registry.cellscript.dev \
--code-hash <hash> --hash-type data1 --dep-type code \
--tx-hash <testnet_tx_hash> --index 0 --capability-key-id <key_id>cell-dep reads the accepted evidence network and defaults to the matching
official RPC; an explicit --rpc-url still has to report the same chain.
8. Other artifact kinds
runtime_verifier:ckb_executablebundle with source, executable, and ABI; consumption mode istcb.- A generic
ckb_executablewith onlysource,executable, andabiremainshash_bound. A CellScript release may opt into independent structural admission by adding the completemetadata,lowering_record, andsource_maprole set. Supplying only part of that set fails closed. The least-privilege artifact worker records checker version, policy, and report hash asstructurally_verifiedevidence; it does not load the compiler and does not claim source equivalence or deployment. - A
ckb_executablethat is built reproducibly may additionally includebuild_recipe, setbuild.reproducible = true, and bind the recipe, environment, command, and expected executable hash inreproduction. reproducible_binary:reproducible_buildbundle with source, executable, andbuild_recipe; the Registry reportsevidence_requireduntil build evidence is sufficient.template:copy_materialbundle containing acellscript-template-file-map-v1source object; usecellc artifact copy. It rejects traversal, duplicates, hash drift, and overwrites.
An artifact declaring security.status = "audited" must also carry an
immutable audit_report bundle object whose CKB Blake2b-256 hash exactly
matches security.audit_report_hash. This authenticates the referenced report;
it does not make the Registry the auditor.
9. Naming rules
Namespace and artifact names are 1–64 characters. Use lowercase letters and
digits; _ and - may appear only between characters. A one-character name is
valid. The UI and API enforce the same rule.
10. Registry scope and repository validation
The Registry names code, build recipes, TCB inputs, deployment facts, and compact commitments. It does not operate application business Cells. Those Cells remain governed by their own Lock/Type Scripts, schemas, and replacement transactions; publishing a Script is not equivalent to indexing every state Cell that uses it.
./scripts/cellscript_gate.sh devFor the complete model and failure rules, see `docs/CELLSCRIPT_REGISTRY_PHASE1.md`.