What a pack is
An OpenWOP pack is a signed tarball containing:
- A
pack.jsonmanifest declaring the pack name, version, and the types it exports. - One or more node implementations (
runtime.languageisjavascript,python,go,wasm,wasm-component, orremote— an MCP server the host calls; see Node-pack runtimes). - Optional agent manifests (per RFC 0003).
- A detached Ed25519 signature over the RFC 8785 canonical-JSON bytes of the
pack.jsoninside the tarball (the v2ed25519-canonical-jsonscheme).
Hosts consume packs at install time, verify the signature against the publisher's public key, and register the declared types in their node catalog. The host's pack-consumer reference implementation is at examples/hosts/postgres/src/pack-consumer.ts in openwop/openwop-examples. It shows the install-time security check: lockfile parse, SRI integrity, version-drift detection and Ed25519 signature verification.
Read these first
- Node packs — pack format, manifest schema, dependency resolution, lockfile semantics, signing recipe.
- Workflow chain packs — composing reusable multi-step workflow templates (RFC 0013).
- Node-pack runtimes — the runtime languages a host may execute, the WASM ABI, and the MCP registry record for
remotepacks. - Host services — the advertised
host.*service surfaces a node pack invokes throughctx. - Registry operations — submission, deprecation, yank, key rotation. The registry tree and signing rules are in Packs.
agent-manifest.schema.json— agent pack manifest shape (RFC 0003).
Namespace tiers
Packs are partitioned into three tiers. The tier is part of the pack identifier; there's no implicit promotion.
| Tier | Publishing rule | Signing root | Example |
|---|---|---|---|
core.* | OpenWOP-maintained; canonical baseline | openwop-team-1 or openwop-registry-root (both permitted for core.openwop.*) | core.openwop.http |
vendor.* | Named vendor; the vendor's own Ed25519 key, listed in the registry's signingKeys[] with permittedNamespaces scoped to vendor.<org>.* | vendor-held keypair | vendor.myndhyve.canvas |
community.* | Open publishing via PR; the publisher's own Ed25519 key, listed in the registry's signingKeys[] with permittedNamespaces scoped to the publisher's community.<publisher>.* names | per-publisher Ed25519 keypair | community.openwop-team.demo |
Host-private deployments can additionally use private.* — these never enter the public registry.
Sign your tarball
v2 has one signing scheme (per Packs §"Signing"): signing on the version manifest is { keyId, scheme }, and scheme MUST be ed25519-canonical-json. The recipe is:
- Build a deterministic tarball containing your
pack.json. - Compute the SRI integrity of the tarball.
- Sign the RFC 8785 (JCS) canonical bytes of that
pack.jsonwith your Ed25519 private key — a detached 64-byte signature. - Submit the
.tgz+ the.sig+ a version manifest referencing both, with the SRI integrity matching the tarball.
A signature over the raw tarball bytes is not a v2 signature; a pack signed that way must be re-signed, not relabeled. A verifier checks the signature against the issuing registry's key for keyId and the pack name against that key's permittedNamespaces.
A reference workflow lives at scripts/build-pack-tarball.mjs in openwop/openwop-registry — you can mine it for the canonical command sequence.
Publish to the canonical registry
The reference registry at packs.openwop.dev has no write API by design. Publishing is via PR against openwop/openwop-registry:
- Fork the repo.
- Add your pack tarball + signature + manifest under the appropriate namespace tier.
- Add a row to the registry index via the canonical generator script.
- Open a PR with the conventional commit prefix
feat(registry):.
The registry rebuilds on merge. Packs are served under registry/v2/packs/<name>/-/<version>.{json,sbom.json,sig,tgz}. Clients resolve every registry path through the endpoints in .well-known/openwop-registry.json instead of building one.
Publish to a private registry
You can stand up your own OpenWOP registry by serving the discovery doc + the pack URLs over HTTPS. The discovery document is .well-known/openwop-registry.json, defined at Packs §"The registry tree". Hosts that point at your registry will consume your packs identically to the canonical one.
Use cases: tenant-scoped private packs, air-gapped deployments, enterprise compliance ("our packs never leave our network").
Common pitfalls
- Don't reuse a signing key across publishers. Each
community.<publisher>.*pack should use a publisher-scoped Ed25519 keypair. - Pin your dependencies. Pack-to-pack dependencies are resolved via lockfile; install-time integrity checks fail closed on version drift.
- Honor SR-1. If your nodes touch secrets, follow the secret-redaction invariant — never put raw secrets in node outputs or event payloads.
- Bump majors honestly. A pack version bump that changes node input/output shapes is a breaking change; downstream workflows must be able to pin to the prior major.