Skip to main content
Version: 0.1.0-alpha.4 (alpha)

Package identity and artifact format

This is the format foundation delivered by #140. It defines bounded models, codecs and validation. The packaging workflow adds deterministic build/inspection and component/WIT checks. The registry adapter adds scoped authenticated transfers. Publisher signature verification binds exact packages to approved keys and current trust state. Build provenance adds independent builder policy; SBOM inspection binds inventories to package content. Trusted catalog admission and durable rollout complete the delivery path.

Identity and compatibility​

IdentityBytes or object identified
ReleaseDigestExact executable component bytes.
PackageDigestExact OCI package manifest bytes, including their configuration/layer descriptors.
ArtifactBlobDigestExact configuration, layer or other content bytes.
Implementation versionPackage's declared semantic version; it is not a content identity.
WIT versionContract package version, independent of the implementation version.
Revision/generationExisting deployment policy and publication identities; see routing.

New digest types require lowercase SHA-256 syntax. They cannot be implicitly constructed from ReleaseDigest. Hashing a parsed-and-reserialized remote manifest would identify different bytes: retain and hash its exact input. Whitespace or ordering changes may therefore create distinct valid package digests. Canonical publishing is deterministic but does not relabel received content.

Historical receipts retain their original identities. The verified package admission path persists the association between package and component identity, enforces existing metadata immutability, and derives trust from verified evidence. An old local record is not evidence of a signed package. Deduplicating bytes never grants another tenant authority to discover, deploy or inspect them.

Package envelope​

The envelope uses schemaVersion: 2 and mediaType: application/vnd.oci.image.manifest.v1+json. Its required fields are schemaVersion, mediaType, artifactType, config, layers and annotations. Unknown structural fields are rejected by the LSF execution profile. This is a narrow package consumer, not a claim that generic OCI registries reject unknown artifact types.

KindartifactTypeRequired content
capsuleapplication/vnd.latent.capsule.v1One component, capsule manifest, typed contracts and WIT lock graph; optional assets.
browser-assetsapplication/vnd.latent.browser-assets.v1Asset layers only.
ssr-packageapplication/vnd.latent.ssr-package.v1One opaque renderer plus optional assets.

The configuration descriptor has exactly mediaType, digest and size, with media type application/vnd.latent.package.config.v1+json. A layer descriptor adds annotations containing exactly org.opencontainers.image.title (logical path) and dev.latent.layer.role. No external descriptor URL or inline data is accepted by this profile. No archive extraction or automatic URL fetch occurs.

Configuration and layers​

Configuration fields are formatVersion: 1, kind, name, version, entrypoint, layers and annotations. A capsule also requires componentDigest; other kinds forbid it. Each configuration layer contains exactly path, role, mediaType, digest and size.

The configuration's layer list and envelope's layer list must correspond exactly in path, order, role, media type, digest and length. Paths are strictly sorted by ASCII byte order. The capsule's component digest equals its component layer digest. Its entrypoint names that component. Browser and SSR entrypoints name an asset or renderer respectively. The configuration annotations and capsule manifest carry package configuration metadata; these are not deployment secret values or an authority to override operator policy.

RoleMedia type
componentapplication/wasm
capsule-manifestapplication/vnd.latent.capsule.manifest.v1+json
contractsapplication/vnd.latent.contracts.v1+json
wit-lockapplication/vnd.latent.wit-lock.v1+json
assetBounded base MIME type, without parameters.
rendererapplication/wasm or text/javascript

Format validation is not a proof that opaque Wasm exports match the supplied contracts, that an SSR runtime is available, or that a publisher is trusted. Those checks belong to packaging, compatibility and admission. Asset and SSR packages cannot pass the capsule-kind check merely by containing Wasm bytes.

WIT source lock graph​

The wit-lock layer is a closed JSON document with required formatVersion: 1, world, contractsDigest and packages fields. contractsDigest names the exact typed-contract metadata layer bytes. Every package entry requires id, sourcePath, digest and dependencies.

id is a pinned namespace:package@version; world is namespace:package/world@version. Identifiers begin with a lowercase ASCII letter, end with an alphanumeric character, and otherwise contain lowercase letters, digits or hyphens. Each identifier segment and version is at most 128 bytes; each complete package/world identity is at most 512 bytes. Versions use SemVer. Package entries are strictly sorted by ID; each dependency list is strictly sorted and unique. All referenced dependencies and the world's package must exist, and cycles are rejected. Package and per-package dependency counts are bounded by the layer-count ceiling.

Each sourcePath names a distinct asset layer with media type text/plain. Its digest names the exact UTF-8 WIT source bytes, with no implicit newline or source normalization. validate_wit_lock checks those layer associations and the contracts digest. Raw source content must also pass the normal byte length/hash verification. Packaging subsequently parses WIT, verifies declared package and dependency identities, and checks agreement with the compiled component and typed contracts. A self-consistent lock graph alone is not that semantic proof.

Evidence association​

Detached evidence is another OCI manifest with a required subject descriptor containing the package manifest's media type, exact package digest and length. It uses the OCI empty configuration: media type application/vnd.oci.empty.v1+json, the SHA-256 of the two ASCII bytes {}, and size 2. Exactly one evidence layer has title and role annotations; its role is evidence.

EvidenceArtifact typeLayer media type
Signatureapplication/vnd.latent.signature.v1application/vnd.latent.signature.payload.v1+json
Provenanceapplication/vnd.latent.provenance.v1application/vnd.latent.provenance.payload.v1+json
SBOMapplication/vnd.latent.sbom.v1application/vnd.latent.sbom.payload.v1+json

These envelope types define subject associations. The publisher signature profile defines the implemented signature payload and verification policy. The build provenance profile separately defines authenticated builder assertions and exact source constraints. The SBOM profile defines CycloneDX 1.6 content at the reserved package/sbom.cdx.json asset and requires detached SBOM payloads to equal those embedded bytes exactly. The inventory omits the final package digest to avoid a self-reference cycle; the detached subject supplies it after assembly. A referrer with a matching subject alone is not authenticated. Required evidence must pass independent subject, integrity and trust checks before admission. Evidence cannot be made part of the same manifest it signs; that would create a digest cycle.

Bounds and portable names​

The codec defaults are also its hard ceilings. A caller may lower them.

ResourceCeiling
JSON document256 KiB
JSON nesting16
JSON nodes16,384
JSON string4,096 UTF-8 bytes
Package layers256
Annotations per map32
Individual layer64 MiB
Aggregate layer content256 MiB, using checked arithmetic
Logical path240 ASCII bytes; 64 per segment
Package name/version128 bytes each
MIME type128 ASCII bytes
Annotation key128 ASCII bytes

Names use lowercase ASCII alphanumeric characters with interior ., _ or -. Versions use SemVer. Paths allow only ASCII letters, digits, ., _, - and /, with no absolute path, empty/./.. segment, trailing dot, Windows reserved basename, case-insensitive collision or file/directory prefix collision. Backslashes, colons, percent encoding, query strings and fragments are rejected. MIME tokens use lowercase ASCII letters, digits, ., _, + and -, with an alphanumeric first character in both type and subtype. Annotation keys use ASCII letters, digits, ., _, - and /; keys cannot be empty. Annotation values have the string byte ceiling and cannot contain control characters.

The decoder rejects duplicate keys, unknown fields, excessive nesting/counts and malformed integer tokens before accepting a typed value. Wire integers are nonnegative integer tokens representable as u64; fractional/exponent spellings do not acquire an integer field's authority through rounding. JSON Schema alone cannot express all byte, lexical, cross-layer and graph constraints; the Rust codec enforces those additional requirements.

Deterministic encoding​

LSF publishing emits compact UTF-8 JSON without a trailing newline, using fixed model field order, sorted annotation keys and strictly path-sorted layers. Optional capsule identity is omitted for other kinds. Numeric fields emit decimal integers. JSON strings use the codec's JSON escaping rules. This is the versioned LSF encoding profile, not a claim of RFC 8785/JCS conformance.

Golden examples and adversarial fixtures exercise the schemas and codec. The package graph validator checks exact configuration/descriptor associations; content verification additionally compares each available blob's exact length and SHA-256. No digest, successful parse or well-formed descriptor alone grants publisher trust or creates execution resources.

See ADR-0019, the OCI manifest specification and content descriptor specification.

Focused validation​

With the pinned toolchain and Python development dependencies installed:

cargo test -p latent-core digest --locked
cargo test -p latent-core --doc --locked
cargo test -p latent-artifacts --test package_format --test package_adversarial --test package_golden --locked
cargo test -p latent-artifacts --lib package::wit_lock --locked
cargo test -p latent-oci --locked
python -m unittest discover -s tools/tests -p test_package_format.py

These portable format checks do not select the Linux catalog durability suite, instantiate guests, contact a registry or run a load campaign. Normal Linux CI also checks the existing workspace, SDKs and runtime invariants before merge.

Immutable browser asset delivery​

The immutable browser asset HTTP profile defines exact publication URLs, current admission checks, GET/HEAD and conditional behavior, shared storage/cache ownership, and the explicitly unsupported range and compression features.