ADR 0012 — Pack content identity consumes ACES associated-artifact manifests¶
Status: Accepted
Date: 2026-07-12
Upstream decision: ACES ADR-077,
associated-artifact-manifest-v1
Context¶
A consumer can validate pack files and retain a caller-supplied digest without proving that the digest identifies the validated bytes. The first design for issue 95 attempted to close that gap with a pack-owned digest over every file in a directory. That would have created a second asset identity and checksum model beside ACES and would have treated a live-directory traversal as the portable asset model.
ACES ADR-077 now owns the missing abstraction. One closed
associated-artifact-manifest-v1 attaches an exact keyed set of non-semantic
artifact descriptors to a scenario, sealed scenario snapshot, or experiment
parent. ACES owns the descriptor/checksum/reference shapes,
associated-artifact-set/v1 canonicalization, the derived set digest, structured
diagnostics, and full parent/set/payload byte-binding validator. The associated
set is a distinct reusable-asset family; it does not change SDL semantic
identity or prove authenticity.
This repository still must select and safely materialize the bytes that comprise a scenario pack. That is a packaging responsibility, not authority to define a second canonical digest.
Decision¶
Scenario-pack content identity is the validator-derived ACES associated-artifact set digest. This repository consumes ACES’s public model and validator and defines only the following pack-owned projection:
A pack that opts into content identity declares
associated_artifact_manifestinpack.yaml. The target is a contained, pack-relative JSON file parsed through ACES’s duplicate-member-rejecting loader. The manifest carrier is not one of its own payloads.The manifest has
scope: scenario; its parent id equalspack.yaml.name, its logical id is<pack-name>-associated-artifacts, and its manifest version equals the pack version. ACES remains responsible for matching the concrete parsed scenario or scenario snapshot.Artifact locators use the pack-owned absolute URI form
aces-scenario-pack:/<percent-encoded-root-relative-path>. Artifact ids remain opaque ACES manifest-local ids; the URI is only a locator. This package resolves it beneath the opened pack root and supplies concrete byte readers to ACES. No network or ambient URI resolution occurs.The manifest must cover the exact regular-file inventory. The carrier and the exact
sdl/.aces/module-cache/resolver cache are excluded; every other file is referenced at least once and every referenced pack URI resolves to an inventoried file. Unknown files therefore fail instead of escaping identity.Scenario-pack payload descriptors use SHA-256. ACES derives the set digest over the parent plus descriptors and independently verifies every declared checksum and size from the supplied readers.
The public library separates authoring derivation from consumer verification:
derive_pack_content_manifest()recomputes payload checksums, sizes, and the ACES set digest from an immutably staged pack while preserving the authored descriptor metadata. Authoring/release tooling persists the returned model.validate_pack_content_manifest()requires the declared model, concrete SDL parent, exact inventory, set digest, sizes, checksums, and bytes to agree.pack_content_digest()returns the validated model’s set digest.verify_pack_content_digest()derives no trust from its caller-supplied value; it fully validates the pack first and then compares the expected and actual canonical digests.
Filesystem traversal and reads are anchored to opened directory descriptors and use no-follow opens. Symlinks, special files, hardlinks, non-canonical names or URIs, escaping paths, missing/extra members, unreadable data, and an inventory change during the operation fail closed with bounded errors. ACES diagnostics remain structured on the pack-domain error rather than being replaced by local checksum semantics.
No directory operation can make mutable storage atomic. Callers must acquire and immutably stage the pack, validate it and its content manifest, atomically promote the same verified bytes, and reverify before use when storage guarantees do not make that redundant. Modes, ownership, ACLs, and extended attributes are outside the associated-artifact set and must be materialized with safe fixed policy.
This adds a portable manifest/pointer and advances the scenario-pack contract
content version to 2. The package dependency remains exactly pinned while
ACES contracts are draft. ACES 0.20.0 publishes ADR-077’s model, schema
corpus, and validator; the final gate installs that published distribution
rather than relying on an upstream development worktree.
Consequences¶
Pack content and metadata have one ACES-defined identity without vendoring an ACES schema or inventing a second canonicalization profile.
Raw SDL files may be associated payloads, but associated bytes do not alter the validated scenario’s semantic digest. Parent integrity, set integrity, per-payload checksums, and authenticity remain separate claims.
A stale or caller-asserted package digest, shape-only manifest validation, or URI/path assertion cannot establish conformance. Every payload must be bound to concrete staged bytes.
Separate release/export views require separate manifests because attachment and set identity do not inherit across parents or materialized byte sets.
Public pack validation (#94) should reuse the descriptor-anchored filesystem boundary introduced here rather than reintroduce path-based safety checks.
Non-goals¶
This decision does not define SDL semantics, ACES trust admission, signatures, archive or OCI formats, acquisition, storage, entitlement, launchability, catalog persistence, or a registry. It does not fetch artifact URIs, execute pack code, invoke subprocesses, or claim snapshot isolation over a mutable directory.