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

nordisk/holger

.nornir/serve-guide.md

Serving & writing a UI client — guide

Class: guide · Function: serve. Architecture: serve-design.md. Two how-tos: (A) drive the two doors from a client, (B) build a UI over gRPC.

A · Hit the two doors

Native HTTP — point the stock tool at the gateway, unmodified:

# the sparse index advertises the public download URL (file-rust)
curl -s http://localhost:8081/rust-prod/index/config.json
# → {"dl":"https://holger.example.com/rust-prod/crates","api":null}
# per-crate index is text/plain NDJSON with real SHA-256 cksums
curl -si http://localhost:8081/rust-prod/index/se/rd/serde | head
# health
curl http://localhost:8081/healthz          # → ok

gRPC — the holger-native surface (holger.v1). Regenerate stubs after editing the proto (never at build time, never needs protoc):

cargo xtask gen-proto      # rewrites server/lib/src/generated/holger.v1.rs, idempotent

B · Write a UI client over gRPC

Source pointers: proto/holger.proto (contract), server/lib/src/grpc.rs (service impl), server/lib/src/object.rs (RemoteHolger, the reference tonic client), server/lib/src/auth.rs (auth surface). A UI should use gRPC, not the native-HTTP door (that door exists for stock package managers, not for you to reimplement).

The canonical pattern is nornir's own viz (nornir/src/viz/remote.rs): an egui app that loads everything over a tonic channel, one blocking call per click, a bearer token stamped by an interceptor. holger's UI is the same shape.

Which RPC backs which view

view RPC notes
browse / list RepositoryService::ListArtifacts name_filter substring; page_token cursor; rows are ArtifactEntry
open / download FetchArtifact whole blob; NOT_FOUND if absent
download w/ progress StreamArtifact 64 KB ArtifactChunks → drive a progress bar
push PutArtifact PERMISSION_DENIED on a read-only repo or a failed RBAC check

Connect + authenticate

Open a tonic channel to :50051, add a request interceptor that stamps the bearer token (OIDC) — mirror RemoteHolger and the nornir viz interceptor. For mTLS, present the client cert configured against holger's client_ca (the chain is verified once at the TLS handshake, and against ron_tls.crl when the endpoint names one: a revoked certificate fails the handshake; see auth-guide). Then each view is one RPC call as above.

The operator UI (package + bin holger-server-ui)

server/ui is an egui app built from facett components + theme, connecting over gRPC. Build with --features gui. It is driven headlessly by a real robot-UI test (server/ui/tests/robot_ui_app.rs, egui_kittest, feeding the nornir test matrix) — see testing-guide. Don't hard-code colours; pull from the facett theme so every pane reads as one product.