Pack Format
{/* AUTO-GENERATED by scripts/sync-reference-schemas.mjs - do not edit by hand. */}
Source document: ../greentic-pack/docs/pack-format.md
This document describes the on-disk representation for .gtpack archives
produced by greentic-pack.
Archive Layout
Sección titulada «Archive Layout»*.gtpack files are deterministic ZIP archives. Entries are written in lexical
order with DOS timestamps pinned to 1980-01-01T00:00:00Z and permissions
normalised to 0644. The root contains the following directories:
manifest.cbor # canonical CBOR manifestsbom.cbor # CBOR inventory of every payload stored in the archiveschemas/<name>@<ver>/... # optional node schemacomponents/<name>@<ver>/component.wasmcomponents/<name>@<ver>/manifest.cbor (optional)assets/... # mapped root files plus other auxiliary assetssignatures/pack.sig # JSON signature envelope covering the manifest + SBOMsignatures/chain.pem # signing certificate chainProduction .gtpack archives include only the canonical CBOR manifest, its SBOM,
runtime artifacts (WASM + component manifests), asset material, and the signature
bundle. Flow definitions and pack sources live inside manifest.cbor; the
individual .ygtc/JSON files are generated only when greentic-pack build --dev
is requested (or when greentic-pack doctor inspects a source directory).
Any non-reserved file at the pack root is remapped to assets/<filename> inside
the archive, while complete directories (e.g. schemas/, templates/) are
included as-is. The contents of an existing assets/ directory are bundled
verbatim and take precedence: if a root file would conflict with assets/<name>,
the archive keeps the assets version and emits a warning instead of overwriting.
Static route mounts are declared separately from asset packaging. Packs that
need tenant-facing hosted assets should keep the payload under assets/... and
declare the mount metadata through the greentic.static-routes.v1 extension in
the pack manifest.
Only regular files are allowed—directories, symlinks, and special entries are rejected by the reader before any manifest parsing occurs.
Hashing & SBOM
Sección titulada «Hashing & SBOM»Every payload file (excluding signatures/*) is recorded in sbom.cbor as a
SbomEntry with the relative path, byte length, media type, and BLAKE3 digest.
During verification the reader recomputes all hashes and also ensures that every
file present in the archive is listed in the SBOM. This SBOM is also part of the
signature input.
The CycloneDX file tracked as dist/sbom.cdx.json is derived from this same
inventory. When you build a .gtpack via packc --gtpack-out, the CycloneDX
artifact and the archive’s own sbom.cbor are produced from the same flows and
templates even though their formatting differs.
Common media types:
application/cbor–manifest.cborapplication/json– JSON payloads and schemasapplication/yaml– flow sourcesapplication/wasm– WASI componentsapplication/octet-stream– arbitrary assets
Signing
Sección titulada «Signing»signatures/pack.sig is a JSON envelope containing the signing algorithm,
decoded signature (URL-safe Base64), digest, timestamp, and optional key
fingerprint. The digest covers:
- The canonical manifest (
manifest.cbor). - The SBOM document (
sbom.json). - Every SBOM entry, concatenating
path + "\n" + blake3in lexical order.
signatures/chain.pem carries the certificate chain. Dev builds generate an
ephemeral Ed25519 key and a single self-signed certificate with
CN=greentic-dev-local. Production builds should bundle the full trust chain.
Pack kinds
Sección titulada «Pack kinds»Supported kind values include:
applicationsource-providerscannersigningattestationpolicy-engineoci-providerbilling-providersearch-providerrecommendation-providerdistribution-bundle(offline bundle GT pack)
rollout-strategy remains reserved for future phases and must not be used.
Distribution bundles
Sección titulada «Distribution bundles»Use kind: distribution-bundle with a distribution section:
kind: distribution-bundledistribution: bundle_id: bundle-123 # optional; defaults to pack id if omitted tenant: {} # opaque JSON map; conventionally serialized TenantCtx environment_ref: env-prod desired_state_version: v1 components: - component_id: app.component version: 1.0.0 digest: sha256:deadbeef artifact_path: artifacts/app.component.wasm kind: software artifact_type: binary/linux-x86_64 tags: [runner-dependency] platform: linux-x86_64 entrypoint: install.sh platform_components: - component_id: greentic-runner version: 1.2.3 digest: sha256:cafebabe artifact_path: artifacts/runner.wasmtenant is validated only as a JSON object; downstream tooling interprets it as a serialized TenantCtx.
Component descriptors and software installs
Sección titulada «Component descriptors and software installs»Components may carry an optional kind (e.g. software), optional artifact_type hint, tags, platform, and entrypoint. artifact_path is a generic path inside the .gtpack; the pack format does not assume WASM. Downstream tooling decides how to execute or install.
Verification Semantics
Sección titulada «Verification Semantics»open_pack(path, policy) reads the archive, enforces size limits, rejects
path traversal (“zip slip”), and only accepts regular files. The SBOM is
validated before any manifest processing. Signature handling depends on the
requested SigningPolicy:
DevOk– accepts the self-signed dev certificate, warning when the chain contains more than one entry.Strict– rejects dev/self-signed chains and requires a non-dev certificate.
The function returns the decoded PackManifest together with a
VerifyReport { signature_ok, sbom_ok, warnings } so callers can surface
warnings while still treating the pack as verified.
Static Routes Extension
Sección titulada «Static Routes Extension»Use extensions.greentic.static-routes.v1 when a pack needs runtime to mount
packaged files as public static surfaces.
The extension does not change how files are bundled. Assets remain ordinary
files under assets/...; the extension only declares mount metadata.
extensions: greentic.static-routes.v1: kind: greentic.static-routes.v1 version: 1.0.0 inline: version: 1 routes: - id: webchat-gui public_path: /v1/web/webchat/{tenant} source_root: assets/webchat-gui scope: tenant: true team: false index_file: index.html spa_fallback: index.html cache: strategy: public-max-age max_age_seconds: 3600 exports: base_url: webchat_gui_base_url entry_url: webchat_gui_entry_urlV1 rules
Sección titulada «V1 rules»public_pathmust start with/v1/web/.public_pathsupports only literal path segments plus{tenant}and{team}.- Wildcards, regex-like segments, arbitrary placeholders, query strings, and fragments are rejected.
source_rootmust be a directory-backed logical path underassets/.index_fileandspa_fallback, when present, are relative tosource_root.- Exported URL names must be unique across the whole pack.
scope.team=trueis invalid unlessscope.tenant=true.
Cache policy
Sección titulada «Cache policy»Supported cache.strategy values in v1:
nonepublic-max-age
When strategy: public-max-age, max_age_seconds is required. For none,
max_age_seconds must be omitted.
Deterministic Builds
Sección titulada «Deterministic Builds»PackBuilder always emits deterministic archives:
- Entries sorted lexically.
- Stable DOS timestamps and permissions.
- Stored compression mode (no deflate variance).
- Media types recorded for every SBOM entry.
The examples/build_demo.rs example and the CI workflow both build the same
pack twice and ensure the resulting archives are byte-identical, guaranteeing
the determinism contract.