sign
Sign a built .pkg with your Organization's key, without the key or the artifact leaving where they are.
npx @elizon/cli sign <artifact.pkg> --yes [--target=<name>] [--out=<file>.pkg] [--re-sign] [--json]Signs an artifact that build produced, using your
Organization's signing key. A Package must be signed before anyone can install it.
Before you start
- A connected device for the Organization whose key should sign.
- A role with the
package.installpermission (Owner, Admin and Editor have it). Signing acts on behalf of your Organization, so read-only roles can't.
What happens
Re-check the artifact, locally
Every file in the .pkg is hashed again and compared with its digest manifest. If anything changed
since build, sign stops with PKG_DIGEST_MISMATCH naming the file, before any network call.
That way a signature can never vouch for contents it doesn't describe.
Send only the digest manifest
The CLI sends .elizon/digests.json (a list of SHA-256 hashes) to your Organization. The .pkg
itself stays on your machine.
Your Organization signs
Your Organization signs those bytes with its ed25519 key and returns the signature plus its public key. The private key stays encrypted in your Organization's vault and is never returned to anyone. The first time an Organization signs, its key pair is created automatically.
Verify, then write
The CLI adds the signature to the archive as .elizon/signature.json without moving or rewriting any
other entry, verifies the result offline, and only then writes the file. If anything fails (an
expired device, a missing permission, a signature that doesn't verify), the .pkg is left exactly
as it was.
✓ /home/you/support-bot/my-org-support-bot-0.1.0.pkg
signed by acme (https://acme.elizon.example)
organization: 0f0b1c2d-…
key: ed25519:4f2c9a…
digests.json: sha256:41ec06ffbf…
.elizon/signature.json added — every other entry is unchanged.
Self-signed by "Acme Ltd" (key ed25519:4f2c9a…). The name is the signer's own claim; no registry has counter-signed this Package.Options
| Option | Effect |
|---|---|
<artifact.pkg> | The artifact to sign. Exactly one. |
--yes | Required. Signing acts on a real Organization. |
--target=<name> | Which connected Organization signs. Default: your default target. |
--out=<file>.pkg | Write the signed artifact here and leave the input unsigned, e.g. to keep the unsigned build in CI. |
--re-sign | Replace an existing signature. Without it, signing twice fails with PKG_ALREADY_SIGNED. |
What a signature means
Every Package is self-signed: the signature proves the file hasn't changed since this Organization signed it. The name shown is the signer's own claim, and no registry vouches for it. The person installing decides whose key to trust. See Signing and verification.
Re-signing
Replacing a signature looks exactly like tampering to anyone who already has the old file. Use
--re-sign only when you'll redistribute the new file to everyone.
Errors
| Code | Meaning and fix |
|---|---|
CLI_WRITE_NOT_CONFIRMED | --yes is missing. |
PKG_DIGEST_MISMATCH | A file changed after build. Build again, then sign the new artifact. |
PKG_ALREADY_SIGNED | Already signed. Sign the unsigned output of build, or pass --re-sign deliberately. |
CLI_TARGET_NOT_FOUND | No connected target by that name. Check target ls, or run target add. |
CLI_TARGET_TOKEN_REJECTED | The device token expired or was revoked. Run target add again. |
CLI_TARGET_FORBIDDEN | Your role can't sign. Reconnecting won't help; ask an Owner or Admin to change your role. |
CLI_TARGET_UNREACHABLE | The Organization's address can't be reached. Check the host and your network. |
CLI_TARGET_ERROR | The gateway answered an HTTP error status, which the message names. |