Holger — PLAN (the driver)
The big-stroke driver for holger: where it's going and what to build first. Detail lives in the design docs (linked below); this stays at altitude. Features are recorded here as direction, implemented later.
Constellation context (the embedded-holger / nornir-release arc, benches, release gate) is tracked from the outside in
workspace_nordisk/PLAN.md §O. This doc is holger's own driver.
RESUME — session 2026-06-25 (read here first)
All changes are UNCOMMITTED on branch feat/plugin-read-api (holger + znippy), building against the local [patch.crates-io] znippy; znippy-zoomies also has uncommitted C1 changes once that agent lands. Nothing published or merged.
Done + verified this session
-
Read handlers fixed end-to-end via the new znippy typed-view plugin contract: npm (R2), gem (R1), conda (R4) — real plugins parse
package.json/metadata.gz/info/index.jsonfor authoritative coords;*View/as_*()inznippy-common; holger backends resolve via the view; npm base-URL configurable; gem → real RubyGems compact-index; conda → realrepodata.json. (.condazip+zstd format deferred, documented, not faked.) Foundation rust/maven/python already landed. All view round-trips + backend tests green. -
Write path: W1 (OIDC pooled
reqwest::Client+ TTL token cache, blake3 key)- W2 v1 (RBAC global gate —
Role+roles/default_rolein RON, fail-closed, back-compat off-until-configured). 5 auth tests green; reviewer confirmed no fail-open path.
- W2 v1 (RBAC global gate —
-
Security review (read-only) of all uncommitted work → fixed H1/H2 (JSON injection in npm packument + conda repodata → built via
serde_json) and M1 (gem compact-index token sanitize); verified green. C1 (decompression-bomb OOM at ingest) fix IN FLIGHT (background agent: capped decompressors inznippy-zoomieslgz/lbzip2 + plugin caps → bomb degrades to filename fallback). -
Test infra: CPU-scaled multicore sanity matrix cell (
holger_matrix.rs, records mt/st read speedup inmetric; 16c → 4.64×); confirmed heavy/non-heavy benchers (HOLGER_BENCH_SCALE) + addedScale::sane(). -
Hygiene: fixed stale
server_lib::→holger_server_lib::inserver/lib/tests/*(was breakingcargo test --workspace). -
Side quest:
SkidbladnirreusableMachineController(KVM + container behind features, lean embedded client stays hypervisor-free) + content-addressedImageCachewith znippy-backed image sets —Skidbladnir/.nornir/machine-control-design.md, green (54 lean / 71 all-features).
Caveats / to-do-when-back
integration_znippy_servehangs (stalledcargo test --workspace>1h40m; killed). Root cause (grounded):server/repository/znippy-rust/tests/integration_znippy_serve.rsis documented "run with--ignored", but the#[test]s at ~451/483/1152 are not#[ignore]-marked, so the default workspace run executes them; they pack real packages (crates.io / Maven Central network fetch, lists ~575/607) and poll for the server viathread::sleeploops (269/702/729/946/969) with no timeout → offline or a missed bind spins forever. Fix: (1) add#[ignore = "heavy: real packages + serve; --ignored pass"]to those tests (matches the file header + the matrix heavy-pass convention); (2) bound the poll loops with max-attempts→error; (3) gate the network fetch behind an offline SKIP (mirrorbench-scenarios/src/nexus.rs::is_skip) so it skips cleanly offline. Then re-runcargo test --workspaceclean (the release-gate pre-flight).- A clean full-workspace pre-flight (with a timeout / excluding daemon tests) should run before the release gate.
Next (priority order — NOT started, per "don't start more")
- #8 Batched release (IRREVERSIBLE — needs explicit go): publish znippy crates → drop holger
[patch.crates-io]→ bump deps → cleancargo test --workspace→ merge both branches. Also commit the uncommitted work first. - #9 W2 v2 per-repo ACL — plumb
ron_write_rolesintoFastRoutes/HolgerGrpc. - #10 static/dynamic profile —
BackendProvidertrait + crate split; airgap = egress isolation (provable fromcargo tree). - #11 offline OIDC — JWT signature verify vs offline JWKS (airgap auth path).
- #12 container conformance — real package-manager client ⇄ real holger; mannequin = mocked world (light pass in-process).
- znippy perf — batch
get_many+ ordered bulk decompress (design noted).
Design docs (for eval): auth-rbac-design.md, static-dynamic-profile-design.md, end-to-end-conformance-testing.md, znippy/.nornir/perf-batch-and-ordered-decompress.md.
The spine — two binaries, not one with a switch
- static holger — for high-security installations / driftmiljön. Serves from sealed znippy archives, nothing else. The executable is stripped: the dynamic machinery isn't compiled in, so there's no surface to attack, audit, or misconfigure. Minimal binary, minimal trust.
- Holger — the full server (developer/build side). Carries everything the static one deliberately lacks. This is the default.
Decision: crate split (hard boundary) + features for granularity. The crate boundary is the floor — "the dynamic code isn't in this binary" is provable from the dependency tree, not from trusting #[cfg]. Features then tune each side.
traits— shared by both.- core/serve lib — read + serve from sealed znippy (pulls the read-only znippy backend crates, which already stand alone).
- dynamic lib — writable backends, proxy, import, promotion. Dynamic-only; the writable
file-*backends live here. - two binary crates —
static holger= traits + serve;Holger= traits + serve + dynamic.
Crates protect the strip, features tune it.
- The static binary depends on core/serve with
default-features = false+ a minimal allowlist → it carries almost nothing. - Features do granularity within a side, never the static/dynamic split itself.
- Why the crate floor matters: Cargo features are additive and unify — dynamic code hidden behind a feature in a shared crate could unify on in a workspace build and leak into the static binary. The crate boundary makes the strip guaranteed; features alone can leak.
The dynamic driver — reach feature level to X, crucial-first
Goal: reach feature level to established artifact servers (X), crucial-first. Not full parity — the useful features first. Bloat (e.g. Groovy scripting) is out; genuinely-needed niche behaviour can be reimplemented to talk to Holger.
Tier 1 — baseline feature level
-
Import (→ znippy) — ingest existing artifact stores into znippy archives.
- Nexus — dump import works today (keep current / refresh).
- Artifactory — add import via znippy.
- plus bulk ingest direct from a running server.
-
Proxy / remote repos — pull-through caching from upstreams, per-upstream creds.
-
Hosted writable repos — ingest for the core formats (Maven, npm, PyPI, Cargo, Docker/OCI, NuGet, Go).
-
Virtual / group repos — one URL fronting many hosted+remote, ordered resolve. Clients point at a single endpoint.
-
Auth + per-repo RBAC — who reads/writes which repo.
Tier 2 — operability 6. Search / browse — find an artifact. 7. Retention / cleanup — bound the store. 8. Audit — who did what. 9. Promotion — already designed (promotion-design.md); lands later.
Throughline: import (1) → one front door (2,3,4) → lock it down (5) → run it (6–9).
UI
- Node graph =
egui-snarl. The config graph (Repository / Exposed / Storage nodes) is drawn with theegui-snarlnode editor. - Node shows RON. UI node ↔ RON node is 1:1. Selecting a node renders an egui component that shows that node's RON — its source-of-truth config, inline.
Design docs (the detail)
promotion-design.md— promotion: two-axis (stage + environment delivery), cleansing, the content-addressed signed release unit.artifactory-parity-design.md— the full feature-level gap list + CAS/policy roadmap (P0/P1/P2).design.md— current holger architecture (the pluggable backend system).auth-rbac-design.md— auth & RBAC: W1 OIDC perf (pooled client + token cache), W2 role model in RON (policy is declarative config, not a mutable store; redb is for future lineage/audit). Offline-OIDC (airgap) JWT verify noted as net-new.static-dynamic-profile-design.md— realises §spine:BackendProvidertrait + crate split; airgap = egress isolation (provable fromcargo tree), not disconnection; auth split by egress (mTLS / offline-OIDC = static, online-OIDC = dynamic).end-to-end-conformance-testing.md— real package-manager client ⇄ real holger in containers; mannequin = mocked world (in-process light pass); containers = conformance/perf (heavy gated);cargo treeegress gate.WISHLIST.md— open robustness/format items.