holger-rust-repository 0.2.0

Holger guards your artifacts at rest. May Allfather Odin watch over every bit.
Documentation

Holger

Holger guards your artifacts at rest.

-->NOTE Holger projekt just started , come back later <--

Immutable Rust-based artifact airgaper. Holger ingests language-specific package trees and serves them over standardized APIs, just like Artifactory or Nexus โ€” but with an airgapped, append-only backend called artifact, based on Znippy archives.

Overview

When airgapping environments, your company saves offline packages using native language tools. These packages are exported and organized under the following structure:

/airgap/
  rust/     <- cargo vendor
  python/   <- pip download
  java/     <- mvn dependency:go-offline
  go/       <- TBD

These folders are archived into a .znippy file by the Znippy CLI. The resulting .znippy file is immutable and can be verified using Blake3 checksums.

The Holger service reads this .znippy archive and exposes one virtual API endpoint per language. Internally, the .znippy file is parsed into one Arrow-based table per language, collectively called an .artifact file. Holger uses this file to respond to requests from tools like Cargo, pip, Maven and Go.

Exampe toml config for small deploy.

# NOTE **TOML canโ€™t represent Holgerโ€™s graph topology. RON can.**
## TOML is dead here. Long live RON.

[[exposed_endpoints]]
name = "prod"
url_prefix = "https://10.101.1.9:8443"
cert = "holger-core/tests/cert.pem"
key = "holger-core/tests/key.pem"

[[storage_endpoints]]
name = "artifact-prod"
type = "znippy"
path = "/var/lib/holger/rust-prod/"

[[repositories]]
name = "rust-prod"
type = "rust"
out = { storage_backend = "artifact-prod", exposed_endpoint = "prod" }

Fan art

curent state source code

graph TD

subgraph Core
    HolgerInstance["HolgerInstance"]
end

subgraph Endpoints
    ExposedEndpointInstance["ExposedEndpointInstance"]
end

subgraph Storage
    StorageEndpointInstance["StorageEndpointInstance"]
end

subgraph Repositories
    RepositoryInstance["RepositoryInstance"]
end

%% --- Wiring HolgerInstance ---
HolgerInstance --> ExposedEndpointInstance
HolgerInstance --> StorageEndpointInstance
HolgerInstance --> RepositoryInstance

%% --- Repository Connections ---
RepositoryInstance -->|reads from| StorageEndpointInstance
RepositoryInstance -->|uses| ExposedEndpointInstance

%% --- Endpoint Mappings ---
ExposedEndpointInstance -->|maps to| RepositoryInstance

Holger serving imutable historized archives

All .artifact files are immutable. However, Holger can(will be) optionally be configured to allow live ingest of artifacts not found in the current .artifact. This is primarily useful in DEV environments.

History Source Update Capability Use Case
V1 Initial .artifact import Immutable Bootstrap, base snapshot
V2 .artifact + live ingest Yes (in-memory + RocksDB) DEV: allow dynamic additions
V3 Promoted .artifact only Immutable PROD: strict airgapped enforcement
  • V2 allows development-time fetches from upstream sources (e.g. crates.io, PyPI) and caches them.
  • V3 is the result of promoting selected artifacts from V2 into a new .artifact file.
  • Live proxy mode can be disabled completely in strict environments.

Architecture

Newest on top , older if you scroll down.

flowchart LR
    %% ===== CONFIG LAYER =====
    CConfig["Holger Config (TOML/JSON)"]
    CRepos["repositories[]"]
    CExposed["exposed_endpoints[]"]
    CStorage["storage_endpoints[]"]

    CConfig --> CRepos
    CConfig --> CExposed
    CConfig --> CStorage

    %% ===== RUNTIME INSTANCES =====
    subgraph RuntimeInstances
        direction LR

        subgraph RepoInst["Repository Instances"]
            RRepo["RepositoryInstance"]
            RRepoBackend["RepositoryBackend"]
            IOIn["IOInstance (in)"]
            IOOut["IOInstance (out)"]
        end

        subgraph ExposedInst["Exposed Endpoints"]
            RExposed["ExposedEndpointInstance"]
            RExposedBackend["ExposedEndpointBackend"]
        end

        subgraph StorageInst["Storage Endpoints"]
            RStorage["StorageEndpointInstance"]
        end
    end

    %% ===== LINKS FROM CONFIG TO RUNTIME =====
    CRepos -->|from_config| RRepo
    CExposed --> RExposed
    CStorage --> RStorage

    %% ===== RUNTIME INTERNAL RELATIONSHIPS =====
    RRepo -->|"backend: Option<Arc<dyn RepositoryBackend>>"| RRepoBackend
    RExposed -->|"backend: Option<Arc<dyn ExposedEndpointBackend>>"| RExposedBackend

    %% IOInstance wiring
    RRepo --> IOIn
    RRepo --> IOOut
    IOIn --> RStorage
    IOIn --> RExposed
    IOOut --> RStorage
    IOOut --> RExposed

    %% ExposedEndpoint routing to RepositoryBackend
    RExposedBackend -->|"route_request_by_subURL"| RRepoBackend
flowchart LR

%% Step 1: Airgap dump
subgraph Offline_Airgap_Dump
    RUST["rust/ (cargo vendor)"]
    PYTHON["python/ (pip download)"]
    JAVA["java/ (mvn go-offline)"]
    GO["golang/ (TBD)"]
end

RUST --> ZNIPPY["๐Ÿ“ฆ Znippy Archive"]
PYTHON --> ZNIPPY
JAVA --> ZNIPPY
GO --> ZNIPPY

%% Step 2: Holger Ingestion
subgraph Holger_Processing
    INPUTAPI["Holger INPUT api/"] --> HOLGER["๐Ÿ›ก Holger Ingest & Promote Service"]
    ZNIPPY --> HOLGER
    HOLGER --> artifact_V1["๐Ÿ“š .artifact v1"]
    HOLGER --> artifact_V2["๐Ÿ“š .artifact v2"]
    HOLGER --> artifact_V3["๐Ÿ“š .artifact v3"]
end

%% Step 3: Holger Serving via APIs
subgraph Holger DEV _API_Endpoints
    CARGO_dev["Cargo Git+HTTP"]
    PIP_dev["PyPI Simple API"]
    MAVEN_dev["Maven Repo API"]
    GOPROXY_dev["Golang Proxy Mode"]
end

subgraph HolgerPROD _API_Endpoints
    CARGO_prod["Cargo Git+HTTP"]
    PIP_prod["PyPI Simple API"]
    MAVEN_prod["Maven Repo API"]
    GOPROXY_prod["Golang Proxy Mode"]
end

artifact_V2 --> CARGO_dev
artifact_V2 --> PIP_dev
artifact_V2 --> MAVEN_dev
artifact_V2 --> GOPROXY_dev

artifact_V3 --> CARGO_prod
artifact_V3 --> PIP_prod
artifact_V3 --> MAVEN_prod
artifact_V3 --> GOPROXY_prod

Status

  • โœ… Znippy archive ingestion
  • โœ… Arrow-based indexing
  • โœ… Immutable .artifact output
  • โœ… API server
  • ๐Ÿšฝ Blake3 verification in place

Mindmapping ..


flowchart TD

%% Konfiguration
subgraph Config
    CFG[holger.yaml]
end

%% Repos
subgraph Repositories
    Hosted1[Hosted Repo\nname: java-test\nmode: .artifact + live\nformat: Java]
    Hosted2[Hosted Repo\nname: rust-prod\nmode: .artifact only\nformat: Rust]
    Proxy1[Proxy Repo\nname: maven-central\nURL: mirror]
    Agg1[Aggregated Repo\nname: all-java\nincludes: java-test and maven-central]
end

%% Komponenter
subgraph HolgerCore
    CLI[CLI and REST API]
    Promote[Ingest and Promote Service]
    Access[Artifact Access API]
    Merge[Znippy Merger\nmerging and dependency resolution]
end

%% Metadata
subgraph ArtifactLayer
    Artifact[Artifact\nUUIDv7 and checksums\nplus type metadata]
    DepGraph[Dependency Graph\nUUID-based DAG]
end

%% Flรถden
CLI --> Promote
CLI --> Access
Promote -->|uses| Repositories
Access -->|uses| Repositories
Repositories --> Artifact
Repositories --> DepGraph
Merge --> Promote
Artifact --> Merge
DepGraph --> Promote
CFG --> Repositories