Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/Skidbladnir

.nornir/archive-guide.md

archive — guide

Class: guide · audience: a techie packing or reading bundles. The what is in archive-design.md; the why in archive-reasoning.md.

Pick an engine

use skidbladnir::archive::{Archive, TarZstd};
let eng = TarZstd::new();          // always available, always offline

For the REAL znippy-core engine (seal/read/verify/unpack via ../znippy, so the bundle is the one canonical .znippy — znippy CLI / DuckDB readable), build with --features znippy and swap the constructor — the trait seam means nothing else changes:

# #[cfg(feature = "znippy")]
let eng = skidbladnir::archive::ZnippyArchive::new();

Pack a staging tree

// staging_root holds your files under their relative paths (see pack-guide.md)
let manifest = eng.pack(&staging_root, "20260704", &bundle_path)?;   // Archive::pack
assert!(manifest.verify_root());                                     // self-check
// a sidecar <bundle_path>.manifest.json is written beside the bundle

manifest.entries is one EntryDigest { path, sha256, len } per file; manifest.root_sha256 is the hash over all of them. This manifest is what the far side verifies.

List and read without extracting everything

for path in eng.list(&bundle_path)? { println!("{path}"); }
let bytes = eng.read_entry(&bundle_path, "bin/app")?;   // znippy: get_file random-access; tar: temp-extract

Verify a received bundle

let manifest = skidbladnir::archive::load_manifest(&bundle_path)?;
let bad = eng.verify_entries(&bundle_path, &manifest)?;   // Vec<String> of bad paths
assert!(bad.is_empty(), "tampered or incomplete: {bad:?}");

Prefer the fetch wrapper for the full receipt gate (manifest root + optional out-of-band SHA + per-entry) — see move-guide.md.

Ship only what changed (znippy delta)

With --features znippy, pack a patch against the previous manifest and apply it on the far side:

# #[cfg(feature = "znippy")] {
let patch = eng.delta(&old_manifest, &new_staging, "20260705")?;   // ships only changed blobs
println!("shipped {} bytes, reused {} entries", patch.shipped_bytes(), patch.reused());
let new_manifest = eng.apply(&old_bundle, &patch, &new_bundle)?;   // re-seals a real znippy bundle; same content root as a fresh pack
# }

On the default TarZstd engine delta/apply bail with a clear "use the znippy feature" message (archive.rs:143) — they are not silently faked.

Gotchas