znippy format-version pin — guide
Class:
guide· Function:znippy-format-pin. Design:znippy-format-pin-design.md.
What you will see
An archive written by a newer znippy than your holger reads is refused, and holger tells you so in one line:
holger refuses znippy archive /srv/holger/drift.znippy: it records format version 4,
which this build does not read (supports up to v3) — re-pack the archive with a
matching znippy, or upgrade holger
Where it shows up:
| when | what happens |
at boot, static archive (ron_archive_path) |
that one repo is disabled; every other repo starts and serves. The line above is the startup error for it. |
at request time, writable repo (/sparring, /cache primary) |
the request gets 503 and the line above as the body. Other repos are unaffected. |
in-process (get_file, HolgerObject::fetch) |
Err carrying the line above — no longer the misleading No reader configured. |
An archive that records no version, or one at/below the pin, behaves exactly as it always did. The gate only ever adds a refusal.
What to do about it
- Re-pack with a matching znippy (preferred, and the only option in an airgap):
znippy compresson the agent side with the znippy your holger was built against. - Upgrade holger to a build whose pin covers that format.
To ask before you deploy, without booting a server:
traits::ensure_supported_format(std::path::Path::new("drift.znippy"))?; // verdict
traits::recorded_format_version(&path); // Option<String>
Checking your pin
traits::MAX_SUPPORTED_ZNIPPY_FORMAT // highest on-disk format this build parses
The test the_gate_admits_the_current_format_and_stays_out_of_the_way (server/repository/znippy-rust/tests/format_version_gate.rs) fails the moment the linked znippy starts writing a version above the pin — that is the signal a bump is due, together with a reader that handles the new layout.
Wiring it into another backend
The gate lives in traits because every znippy-* backend already depends on it. To adopt it in a backend that opens archives:
// once, at open — a refusal disables just this repo
traits::ensure_supported_format(&archive_path)?;
let archive = ZnippyArchive::open(&archive_path)?;
// per request, for a repo that re-opens its archive (memoised on (len, mtime))
struct MyRepo { format_gate: traits::FormatGate, /* … */ }
if let Err(e) = self.format_gate.check(path) {
return Ok((503, vec![("Content-Type".into(), "text/plain".into())], e.to_string().into_bytes()));
}
Today znippy-rust is wired. The other znippy-* backends open their archive once, at construction, and inherit the boot-time containment (instantiate_backends disables a repo whose backend fails); adding ensure_supported_format to each is a one-line change and is the tracked follow-up.
Tests
cargo test -p holger-traits znippy_format
cargo test -p holger-rust-znippy-repository --test format_version_gate
cargo test -p holger-server-lib --test graceful_backend_init