3.3 KiB
ADR 0043: Content-Addressed Import Fingerprints
Status
Accepted
Context
Generated model artifacts and the project asset registry must be stable across contributors, CI, Git worktrees, and LFS checkouts. Git does not preserve source-file modification times. Persisting a checkout mtime as source identity therefore caused the editor to rewrite otherwise equivalent animation and static-mesh manifests during startup. Static-mesh manifests also used only byte length and mtime, so a same-size source edit could evade the persisted identity contract.
Formatting-only publication was a second source of noise. Re-serializing an equivalent RON document could normalize its final newline or layout even when import semantics had not changed. That made clean-checkout release evidence unreliable and obscured intentional asset edits.
Decision
shared::AssetSourceFingerprint is the persisted imported-source identity. It contains the exact
source byte length and lowercase BLAKE3 digest. Filesystem timestamps are not serialized or compared
as semantic identity; an importer may use them only as an in-memory scan hint before confirming
content.
The asset registry stores this fingerprint for every imported model, texture, and audio source. Content identity also drives unique move reconciliation, so metadata-only drift cannot replace a stable registry UUID. Ambiguous copies still receive a new identity.
Animation and static-mesh manifests use the same fingerprint. Animation schema v3 already contained
a content hash, so its schema remains v3 and legacy modified_unix_secs fields are accepted as
ignored unknown metadata. Static-mesh schema v4 replaces its length-plus-mtime record with length
plus BLAKE3. Existing schema-v3 static artifacts are regenerated once; unrelated assets are not
reimported.
Registry and generated-manifest writers parse the existing RON and compare the semantic value before publication. Equivalent documents preserve their exact existing bytes, including layout and final newlines. Changed documents publish canonical pretty RON. Registry records are ordered by normalized project path before comparison, so filesystem enumeration order cannot change their serialized sequence on a fresh checkout.
Authoritative project validation remains read-only. It validates registry, animation, and static-mesh fingerprints by length and digest, including same-size source edits. CI runs both headless validators and then asserts that tracked and untracked checkout state is unchanged.
Consequences
- A source touch or fresh checkout mtime cannot dirty the project.
- Same-size source edits invalidate the affected registry/manifests deterministically.
- Model, texture, and audio IDs survive uniquely identifiable moves by content.
- Initial migration adds fingerprints to imported registry records and upgrades static manifests to schema v4. Legacy animation files can remain byte-identical indefinitely because their timestamp field is ignored.
- Startup hashing reads imported source bytes. Future scan caches may use metadata to avoid work, but they must verify content before persisting a changed identity.
- External glTF/FBX dependency paths remain explicit manifest dependencies; extending fingerprints to a dependency graph requires a separate versioned contract.