Ir al contenido

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.

*.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 manifest
sbom.cbor # CBOR inventory of every payload stored in the archive
schemas/<name>@<ver>/... # optional node schema
components/<name>@<ver>/component.wasm
components/<name>@<ver>/manifest.cbor (optional)
assets/... # mapped root files plus other auxiliary assets
signatures/pack.sig # JSON signature envelope covering the manifest + SBOM
signatures/chain.pem # signing certificate chain

Production .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.

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/cbormanifest.cbor
  • application/json – JSON payloads and schemas
  • application/yaml – flow sources
  • application/wasm – WASI components
  • application/octet-stream – arbitrary assets

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:

  1. The canonical manifest (manifest.cbor).
  2. The SBOM document (sbom.json).
  3. Every SBOM entry, concatenating path + "\n" + blake3 in 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.

Supported kind values include:

  • application
  • source-provider
  • scanner
  • signing
  • attestation
  • policy-engine
  • oci-provider
  • billing-provider
  • search-provider
  • recommendation-provider
  • distribution-bundle (offline bundle GT pack)

rollout-strategy remains reserved for future phases and must not be used.

Use kind: distribution-bundle with a distribution section:

kind: distribution-bundle
distribution:
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.wasm

tenant is validated only as a JSON object; downstream tooling interprets it as a serialized TenantCtx.

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.

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.

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_url
  • public_path must start with /v1/web/.
  • public_path supports only literal path segments plus {tenant} and {team}.
  • Wildcards, regex-like segments, arbitrary placeholders, query strings, and fragments are rejected.
  • source_root must be a directory-backed logical path under assets/.
  • index_file and spa_fallback, when present, are relative to source_root.
  • Exported URL names must be unique across the whole pack.
  • scope.team=true is invalid unless scope.tenant=true.

Supported cache.strategy values in v1:

  • none
  • public-max-age

When strategy: public-max-age, max_age_seconds is required. For none, max_age_seconds must be omitted.

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.