Packaging
Packaging turns your solution directory into a single immutable artifact: a canonical JSON document with a SHA-256 checksum and an Ed25519 signature. The registry accepts nothing else.
Metadata Marketplace Apps (hosting: runtime) must include entities/
and must not ship src/ or an external /qefro endpoint.
qefro app package / qefro solution build accept that shape.
SDK connections (external) require src/ and a /qefro process. See
Runtime vs SDK.
Build command
qefro app package .
# alias of: qefro solution build .
Output:
built restaurant-pro@1.0.0
checksum: 9f2c1e…
signature: 71ab04…
package: ./dist/package.json
The signed package is written to dist/package.json inside the solution
directory.
Assembly steps
- Assemble. The manifest, UI definitions, workflow definitions and connector declarations are parsed into one document. Assets are validated (images only) and attached.
- Canonicalize. The document is serialized to canonical JSON — sorted keys, compact separators. Canonicalization is the checksum contract: the same content always yields the same bytes.
- Checksum. SHA-256 of the canonical bytes becomes the package checksum.
- Sign. Ed25519 signs the message
id|version|checksum. - Emit. The package document carries:
{
"manifest": { "...": "parsed manifest" },
"components": { "workflows": [], "ui": {}, "assets": [] },
"signature": "hex…",
"signature_kid": "k1",
"publisher_id": "qefro"
}
Signing keys
The CLI loads a signing key from one of:
| Source | Setting |
|---|---|
| Environment variable | QEFRO_SIGNING_KEY_HEX — 32 bytes of hex |
| Keys file | QEFRO_KEYS_FILE pointing to a file containing REGISTRY_PRIVATE_KEY=<hex> |
The publisher identity is taken from QEFRO_PUBLISHER_ID (defaults to
the built-in publisher UUID). That id must be listed in solution-service
QEFRO_PLATFORM_ADMIN_IDS — only platform admins can publish. See
Publishing.
The signing key is the root of trust for everything you publish. Keep it out of source control, CI logs and shell history; rotate it through the platform key process, never ad hoc.
Why canonical JSON
- Deterministic checksums — two builds of identical content produce identical checksums, so the registry can detect any tampering or drift.
- Reproducible signatures —
id|version|checksumbinds the identity and content of the release; changing either invalidates the signature. - Version immutability — a published version's checksum can never change; fixes ship as new versions. See Publishing.
What does not enter the package
- Local caches, editor metadata and
dist/itself. - Anything outside the solution directory — packages are self-contained.
- Secrets of any kind; connector credentials are tenant data collected at install time. See Connectors.
Related topics
- Validation — checks run before assembly
- Publishing — submitting the signed package
- Security — the trust model signatures support