nordisk/holger
holger-cli/src/generated/holger.v1.rs
// @generated by `cargo xtask gen-proto` (protox + tonic-build, no protoc).
// DO NOT EDIT BY HAND. Regenerate after changing proto/holger.proto.
// This file is @generated by prost-build.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ArtifactId {
/// e.g. groupId for Maven, empty for Rust
#[prost(string, tag = "1")]
pub namespace: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub name: ::prost::alloc::string::String,
#[prost(string, tag = "3")]
pub version: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct FetchArtifactRequest {
#[prost(string, tag = "1")]
pub repository: ::prost::alloc::string::String,
#[prost(message, optional, tag = "2")]
pub id: ::core::option::Option<ArtifactId>,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct FetchArtifactResponse {
#[prost(bytes = "vec", tag = "1")]
pub data: ::prost::alloc::vec::Vec<u8>,
#[prost(string, tag = "2")]
pub content_type: ::prost::alloc::string::String,
#[prost(int64, tag = "3")]
pub size_bytes: i64,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ArtifactChunk {
#[prost(bytes = "vec", tag = "1")]
pub data: ::prost::alloc::vec::Vec<u8>,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ListArtifactsRequest {
#[prost(string, tag = "1")]
pub repository: ::prost::alloc::string::String,
/// optional substring filter
#[prost(string, tag = "2")]
pub name_filter: ::prost::alloc::string::String,
#[prost(int32, tag = "3")]
pub limit: i32,
#[prost(string, tag = "4")]
pub page_token: ::prost::alloc::string::String,
}
/// One row of a repository listing.
///
/// ── Fields 4, 5 and 6 are `optional`, and that word is load-bearing ────────────
///
/// A proto3 scalar has no field presence: a peer that does not send `sha256`
/// and a peer that sends `sha256 = ""` are indistinguishable on the wire, and a
/// `published_unix_ms` of 0 arrives looking exactly like a real answer of
/// 1970-01-01T00:00:00Z. Both of those would be a FABRICATED value dressed as a
/// measurement — an empty digest compares equal to another empty digest, and a
/// zero timestamp sorts as the oldest thing in the repository.
///
/// The `optional` keyword restores explicit presence (proto3 field presence;
/// prost renders these as `Option<i64>` / `Option<String>`), so "this publisher
/// does not know" is a distinct state on the wire and not a value at all.
///
/// Wire compatibility, both directions:
///
/// * an OLD server answering a NEW client sends neither field; the client
/// reads `None` = unknown, which is the truth about an old server.
/// * a NEW server answering an OLD client sends two fields the old client
/// does not know; proto3 drops unknown fields, and the old client sees
/// exactly the listing it saw before.
/// Neither peer has to be upgraded first, and nothing here is an invented value.
///
/// Belt and braces on top of presence: a receiver still treats a
/// `published_unix_ms` that is not strictly positive, and a `sha256` that is not
/// 64 hex characters, as unknown — so even a hand-rolled client that emits the
/// proto3 zero values cannot claim 1970 or an empty hash. See
/// `holger_traits::normalize_published_unix_ms` / `normalize_sha256`.
///
/// This is the same reasoning as `StartMigrationRequest.skip_digest_verification`
/// next door, which is INVERTED on the wire so that the proto3 zero value is the
/// safe one. Here the safe state is "unknown", and presence says it outright
/// rather than by inversion.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ArtifactEntry {
#[prost(message, optional, tag = "1")]
pub id: ::core::option::Option<ArtifactId>,
#[prost(int64, tag = "2")]
pub size_bytes: i64,
#[prost(string, tag = "3")]
pub content_type: ::prost::alloc::string::String,
/// When these bytes were published, Unix milliseconds UTC.
/// ABSENT = the serving backend does not know. Never guessed, never 0.
#[prost(int64, optional, tag = "4")]
pub published_unix_ms: ::core::option::Option<i64>,
/// Lowercase-hex SHA-256 of the artifact bytes, 64 chars, no `sha256:` prefix.
/// ABSENT = the serving backend does not know, and in particular does NOT mean
/// the bytes are trusted — the same rule `RemoteAsset.sha256` states. A
/// backend that would have to read the artifact to answer leaves it absent
/// rather than turning a listing into a full read of the repository.
#[prost(string, optional, tag = "5")]
pub sha256: ::core::option::Option<::prost::alloc::string::String>,
/// An OPAQUE CHANGE TOKEN for these bytes, scoped to this server+repository.
///
/// Equal ⇒ unchanged HERE. Different ⇒ changed HERE. It is not a content
/// digest and it is not comparable with one; nor is it comparable with a
/// token from any other source, because two sources holding byte-identical
/// artifacts legitimately publish different tokens (holger's binds the
/// archive-relative path, exactly as znippy's own provenance digest does).
/// A consumer stamps its own source scope onto the value before it stores or
/// compares it — see `holger_traits::scope_change_token`.
///
/// This is the ONE provenance question a znippy-backed repository can answer
/// cheaply: the archive index already carries a BLAKE3 per chunk, so a
/// per-entry fold of them reads no artifact byte. 15 of 17 backends are
/// znippy-backed, and without this every one of them answered `None` to both
/// fields above, landed in the mirror's `unproven` bucket on every tick, and
/// re-fetched its whole repository every 300 s under the default policy.
///
/// ABSENT = the serving backend does not know. Never guessed, never "".
#[prost(string, optional, tag = "6")]
pub change_token: ::core::option::Option<::prost::alloc::string::String>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ListArtifactsResponse {
#[prost(message, repeated, tag = "1")]
pub artifacts: ::prost::alloc::vec::Vec<ArtifactEntry>,
#[prost(string, tag = "2")]
pub next_page_token: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct PutArtifactRequest {
#[prost(string, tag = "1")]
pub repository: ::prost::alloc::string::String,
#[prost(message, optional, tag = "2")]
pub id: ::core::option::Option<ArtifactId>,
#[prost(bytes = "vec", tag = "3")]
pub data: ::prost::alloc::vec::Vec<u8>,
/// ASYNC SHAPE -- see `PromoteArtifactRequest.async_job`. Unset/false writes
/// the bytes into the backend on this RPC, as always. Set, the FINALIZE half
/// (the backend write, which for a znippy repo is an index re-seal and for a
/// proxy an outbound round-trip) becomes a job: the body is staged and the
/// answer is a job id. The INGEST GATES still run here, before admission --
/// making an upload asynchronous must not make it ungated.
#[prost(bool, tag = "4")]
pub async_job: bool,
}
/// One piece of a `PutArtifactStream` upload. `repository`, `id` and
/// `async_job` are read from the FIRST message only; `data` from every one.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct PutArtifactChunk {
#[prost(string, tag = "1")]
pub repository: ::prost::alloc::string::String,
#[prost(message, optional, tag = "2")]
pub id: ::core::option::Option<ArtifactId>,
#[prost(bytes = "vec", tag = "3")]
pub data: ::prost::alloc::vec::Vec<u8>,
#[prost(bool, tag = "4")]
pub async_job: bool,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct PutArtifactResponse {
#[prost(bool, tag = "1")]
pub success: bool,
#[prost(string, tag = "2")]
pub message: ::prost::alloc::string::String,
/// Set ONLY when the request asked for the async shape. Empty otherwise.
#[prost(string, tag = "3")]
pub job_id: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ListArchiveFilesRequest {
#[prost(string, tag = "1")]
pub repository: ::prost::alloc::string::String,
/// optional path prefix filter
#[prost(string, tag = "2")]
pub prefix: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ListArchiveFilesResponse {
#[prost(string, repeated, tag = "1")]
pub paths: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
#[prost(int64, tag = "2")]
pub total_files: i64,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ArchiveInfoRequest {
#[prost(string, tag = "1")]
pub repository: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ArchiveInfoResponse {
#[prost(int64, tag = "1")]
pub file_count: i64,
#[prost(int64, tag = "2")]
pub total_uncompressed_bytes: i64,
#[prost(string, tag = "3")]
pub archive_path: ::prost::alloc::string::String,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
pub struct HealthRequest {}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct HealthResponse {
/// "ok"
#[prost(string, tag = "1")]
pub status: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub version: ::prost::alloc::string::String,
#[prost(int64, tag = "3")]
pub uptime_seconds: i64,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ListRepositoriesRequest {}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct RepositoryInfo {
#[prost(string, tag = "1")]
pub name: ::prost::alloc::string::String,
/// "rust", "maven3"
#[prost(string, tag = "2")]
pub repo_type: ::prost::alloc::string::String,
#[prost(bool, tag = "3")]
pub writable: bool,
#[prost(bool, tag = "4")]
pub has_archive: bool,
/// Whether `RepositoryService.ListArtifacts` on this repository is a REAL
/// enumeration (`RepositoryBackendTrait::supports_listing`). A counter that
/// ignores this reads a full repository as empty; a consumer that meters by
/// artifact count MUST refuse, by name, while this is false.
#[prost(bool, tag = "5")]
pub supports_listing: bool,
/// A GROUP repository is a read-only VIEW over `members`: it owns no storage,
/// and its `ArchiveInfo` is the SUM of its members'. A fleet total that adds a
/// group to its members counts those bytes twice — skip every `is_group`.
#[prost(bool, tag = "6")]
pub is_group: bool,
/// The member repository names of a group, in resolution order. Empty for a
/// repository that owns its own storage.
#[prost(string, repeated, tag = "7")]
pub members: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// A SYSTEM repository of this estate (floored at Admin, e.g. the sealed
/// `monetize-backup`): the estate's own, its name taken, never a tenant a
/// buyer pays for. Set by `ListRepositories` only; false elsewhere.
#[prost(bool, tag = "8")]
pub system: bool,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ListRepositoriesResponse {
#[prost(message, repeated, tag = "1")]
pub repositories: ::prost::alloc::vec::Vec<RepositoryInfo>,
}
/// Confer the TWIN role on this box. See AdminService.BecomeTwin.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct BecomeTwinRequest {
/// The primary this box will follow, as an address a client would use
/// ("grpc.holger.rs:50051"). MANDATORY: a twin that names no primary could
/// neither refuse a write by name nor follow anything.
#[prost(string, tag = "1")]
pub primary: ::prost::alloc::string::String,
/// Seconds between follow cycles. 0 = the server's default.
#[prost(uint64, tag = "2")]
pub poll_seconds: u64,
/// The MEASUREMENT that decided this election, in the caller's own words
/// ("2 cores / 1 GB / 20 GB hdd vs 2 / 4 / 20 maxiops"). Recorded verbatim:
/// this record is read by an operator on the worst day, and a number with no
/// units is not a reason.
#[prost(string, tag = "3")]
pub reason: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct BecomeTwinReply {
/// Unix seconds the election was recorded at.
#[prost(uint64, tag = "1")]
pub elected_at: u64,
/// The authenticated identity that elected it — the server's own reading of
/// the credential, not anything the caller said about itself.
#[prost(string, tag = "2")]
pub elected_by: ::prost::alloc::string::String,
/// True: the LOOPBACK BIND of the public doors waits for the next start,
/// because doors are bound at wiring time and a running server does not
/// rebind them underneath its clients. The role itself is live — see
/// `applied_live`.
#[prost(bool, tag = "3")]
pub restart_required: bool,
/// True when every door refuses writes by name from this reply on and the
/// follow has started, without a restart (stinky 14 §P3).
#[prost(bool, tag = "4")]
pub applied_live: bool,
}
/// Which credential slot of THIS box a pairing step is about: "twin" (the
/// twin following its primary; the default when empty) or "recharge" (a fresh
/// main reading its twin).
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct TwinCsrRequest {
#[prost(string, tag = "1")]
pub purpose: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct TwinCsrReply {
/// PKCS#10, PEM. Its key was minted on this box and never leaves it; asked
/// again, the same request.
#[prost(string, tag = "1")]
pub csr_pem: ::prost::alloc::string::String,
/// The CN it carries — the principal the source must issue for.
#[prost(string, tag = "2")]
pub principal: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct IssueTwinCertificateRequest {
/// `holger-twin` or `holger-recharge`; the request's own CN must be this.
#[prost(string, tag = "1")]
pub principal: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub csr_pem: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct IssueTwinCertificateReply {
/// The client leaf: CN = principal, clientAuth only, 365 days.
#[prost(string, tag = "1")]
pub cert_pem: ::prost::alloc::string::String,
/// This box's replication issuer — what the reader pins.
#[prost(string, tag = "2")]
pub issuer_pem: ::prost::alloc::string::String,
/// The replication door's port and the addresses it answers on, in order.
#[prost(uint32, tag = "3")]
pub port: u32,
#[prost(string, repeated, tag = "4")]
pub hosts: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// notAfter, Unix seconds.
#[prost(int64, tag = "5")]
pub not_after: i64,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct InstallTwinCertificateRequest {
#[prost(string, tag = "1")]
pub purpose: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub cert_pem: ::prost::alloc::string::String,
#[prost(string, tag = "3")]
pub issuer_pem: ::prost::alloc::string::String,
#[prost(uint32, tag = "4")]
pub port: u32,
#[prost(string, repeated, tag = "5")]
pub hosts: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// RE-POINT (purpose "twin" only): the primary this twin followed is DEAD and
/// a fresh main was recharged from it — a main with an issuer of its own (an
/// issuer is never replicated). Every install check but the pin runs; the new
/// issuer is pinned and the twin's role record names `primary` from now on.
/// Admin and explicit: never a courier's retry.
#[prost(bool, tag = "6")]
pub repoint: bool,
#[prost(string, tag = "7")]
pub primary: ::prost::alloc::string::String,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
pub struct FencePrimaryRequest {
/// The epoch the order names (0 = a local fence).
#[prost(uint64, tag = "1")]
pub epoch: u64,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct FencePrimaryReply {
/// The box is fenced now: every door refuses writes.
#[prost(bool, tag = "1")]
pub fenced: bool,
/// The epoch it is fenced at.
#[prost(uint64, tag = "2")]
pub epoch: u64,
/// The write refusal its doors answer from now on.
#[prost(string, tag = "3")]
pub refusal: ::prost::alloc::string::String,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
pub struct RechargeStatusRequest {}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct RechargeStatusReply {
/// "fresh" (holds nothing of its own — a recharge may start), "restoring" (a
/// recharge began and is not whole — it resumes), "recharged" (done, once),
/// "holding" (state of its own: a re-image makes it fresh).
#[prost(string, tag = "1")]
pub state: ::prost::alloc::string::String,
#[prost(bool, tag = "2")]
pub fresh: bool,
#[prost(bool, tag = "3")]
pub restoring: bool,
#[prost(bool, tag = "4")]
pub recharged: bool,
/// False while the box refuses to serve (holger-twin-15).
#[prost(bool, tag = "5")]
pub serving: bool,
/// What makes the box not fresh, by path; empty when fresh.
#[prost(string, tag = "6")]
pub held: ::prost::alloc::string::String,
/// The source a pending recharge waits for, when one is declared.
#[prost(string, tag = "7")]
pub awaiting_from: ::prost::alloc::string::String,
/// This box's control plane as a client dials it (its gRPC door; an
/// unspecified bind is named by its replication door's first address) — what
/// a twin re-pointed at it names as its primary.
#[prost(string, tag = "8")]
pub control: ::prost::alloc::string::String,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
pub struct TwinStatusRequest {}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct TwinStatusReply {
/// "twin" or "primary".
#[prost(string, tag = "1")]
pub role: ::prost::alloc::string::String,
/// The primary it follows (a twin).
#[prost(string, tag = "2")]
pub primary: ::prost::alloc::string::String,
/// What it holds: estate files, and artifacts over every repository.
#[prost(uint64, tag = "3")]
pub estate_files: u64,
#[prost(uint64, tag = "4")]
pub artifacts: u64,
/// True when its last follow cycle that REACHED its primary was whole — a dead
/// primary makes every later cycle fail to connect, and that is not a loss.
#[prost(bool, tag = "5")]
pub complete: bool,
/// Why not complete, in words; empty when complete.
#[prost(string, tag = "6")]
pub why: ::prost::alloc::string::String,
/// Unix seconds of the last whole cycle; 0 = never.
#[prost(int64, tag = "7")]
pub last_whole_unix: i64,
/// How it last followed ("mtls <door>" / "plain <endpoint>").
#[prost(string, tag = "8")]
pub follow: ::prost::alloc::string::String,
/// ★ What it last HEARD of its primary — the fence gate's evidence (A7 row 4,
/// Gunnar R-13 fence before recharge): Unix ms of the last follow cycle that
/// reached it (0 = never), how long ago that was on the TWIN's clock, what the
/// primary listed then (estate files; 0 = an empty primary), and the twin's
/// word: "following", "unreachable" (its last cycle did not reach it) or "idle".
#[prost(int64, tag = "9")]
pub primary_answer_unix_ms: i64,
#[prost(uint64, tag = "10")]
pub primary_answer_ago_ms: u64,
#[prost(uint64, tag = "11")]
pub primary_head: u64,
#[prost(string, tag = "12")]
pub follow_state: ::prost::alloc::string::String,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
pub struct InstallTwinCertificateReply {
#[prost(int64, tag = "1")]
pub days_left: i64,
/// True when this replaced a certificate from the SAME issuer.
#[prost(bool, tag = "2")]
pub renewal: bool,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
pub struct RechargeRequest {}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct RechargeReply {
/// The estate line, one line per repository, and what failed (empty = whole;
/// the `holger-recharged` marker is written only then).
#[prost(string, tag = "1")]
pub estate: ::prost::alloc::string::String,
#[prost(string, repeated, tag = "2")]
pub artifacts: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
#[prost(string, repeated, tag = "3")]
pub failed: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct FlowSvgRequest {
/// The zoom, as `GET /-/flow.svg?open=` names it (HOL-FLOW-SMART): the machines to unfold,
/// comma-separated, by id (`estate:main`) or short name (`main`, `twin`, a downstream's
/// name). Empty is level 1 (the Overview: the machines and the upstream sources); some is
/// level 2 (the Flow: those machines unfolded in place, with their part of the RON); `all`
/// is level 3, the full RON.
#[prost(string, tag = "1")]
pub open: ::prost::alloc::string::String,
}
/// The whole drawing, `image/svg+xml`, UTF-8, self-contained (no script, no external
/// reference), and the model it was drawn from, JSON.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct FlowSvgReply {
#[prost(string, tag = "1")]
pub svg: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub graph_json: ::prost::alloc::string::String,
/// Where the drawing is clickable (HOL-FLOW-SMART): each machine that unfolds or folds,
/// and the full-RON link. A console showing the drawing as an image (which follows no
/// link inside it) lays a plain link over each; it computes nothing.
#[prost(message, repeated, tag = "3")]
pub links: ::prost::alloc::vec::Vec<FlowLink>,
}
/// One clickable place of the flow drawing, as the share (0..1) of the drawing's width and
/// height it covers, and the relative link it follows (`flow?open=main`).
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct FlowLink {
#[prost(string, tag = "1")]
pub href: ::prost::alloc::string::String,
/// What following it does: `unfold main`, `fold twin`, `show the full RON`.
#[prost(string, tag = "2")]
pub label: ::prost::alloc::string::String,
#[prost(double, tag = "3")]
pub left: f64,
#[prost(double, tag = "4")]
pub top: f64,
#[prost(double, tag = "5")]
pub width: f64,
#[prost(double, tag = "6")]
pub height: f64,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
pub struct CapacityRequest {}
/// One measurement of the filesystem under `path` (the data root).
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct CapacityReply {
/// The filesystem size: f_blocks * f_frsize.
#[prost(uint64, tag = "1")]
pub total_bytes: u64,
/// SERVABLE: what an unprivileged writer (holger) may still put there —
/// f_bavail * f_frsize, i.e. without the root reserve. Not f_bfree.
#[prost(uint64, tag = "2")]
pub available_bytes: u64,
/// The sum of `ArchiveInfo.total_uncompressed_bytes` over every repository
/// that owns storage. Groups are excluded (their info is a sum of members).
#[prost(uint64, tag = "3")]
pub used_by_holger_bytes: u64,
/// The data root the measurement was taken over.
#[prost(string, tag = "4")]
pub path: ::prost::alloc::string::String,
/// ── the GROWTH VERDICT (2026-09-27, additive) ──
/// Can this data set ever hold more than it does, and by whose hand — edda
/// appliance-grow's ladder over MEASURED facts (the journal on the box, this
/// build's engine, the kernel's PCI hot-plug, PID 1). Reported on every
/// answer: "yes, and this is the last capacity" is a different sale. An OLD
/// holger leaves it 0 (unspecified), which a reader must take as unknown.
#[prost(enumeration = "SetGrowth", tag = "5")]
pub growth: i32,
/// The clause that says it, in words (an attached disk that is billed and
/// invisible is said in those words).
#[prost(string, tag = "6")]
pub growth_reason: ::prost::alloc::string::String,
/// What `path` sits on: `4×75G raid0 xfs`; empty when it is not a mount of its own.
#[prost(string, tag = "7")]
pub data_set: ::prost::alloc::string::String,
/// The running kernel has PCI hot-plug (a runtime growth needs it).
#[prost(bool, tag = "8")]
pub hotplug: bool,
/// ── the rest of the ELECTION's measurement (stinky SB #37, additive) ──
/// The installer elects the weakest box the twin on cores, then RAM, then data
/// room (nordisk-pairing `elect::weakest`); a capacity that answered the disk
/// alone could not say which box that is. An OLD holger leaves both 0.
/// CPUs this process may run on (available_parallelism).
#[prost(uint32, tag = "9")]
pub cpu_cores: u32,
/// MemTotal of /proc/meminfo, bytes.
#[prost(uint64, tag = "10")]
pub ram_bytes: u64,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ServerProfileRequest {}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct PromoteArtifactRequest {
/// source, mutable DEV repository
#[prost(string, tag = "1")]
pub from_repo: ::prost::alloc::string::String,
/// target, immutable PROD repository
#[prost(string, tag = "2")]
pub to_repo: ::prost::alloc::string::String,
#[prost(message, optional, tag = "3")]
pub artifact: ::core::option::Option<ArtifactId>,
/// ASYNC SHAPE (2026-09-21, stinky 01 §1.3), purely ADDITIVE: unset/false is
/// the original synchronous promotion, byte for byte -- the seal runs on this
/// RPC and the response carries `content_address`. Set true and the server
/// ADMITS the promotion to its durable job queue and answers at once with
/// `job_id`; the seal happens on the queue's gatling pool and is read back
/// through `JobService.GetJob`. A server built WITHOUT the `jobs` feature
/// refuses a true here BY NAME rather than silently promoting inline.
#[prost(bool, tag = "4")]
pub async_job: bool,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct PromoteArtifactResponse {
#[prost(bool, tag = "1")]
pub success: bool,
#[prost(string, tag = "2")]
pub message: ::prost::alloc::string::String,
/// blake3 hex of the promoted bytes
#[prost(string, tag = "3")]
pub content_address: ::prost::alloc::string::String,
/// identity that performed the promotion
#[prost(string, tag = "4")]
pub promoted_by: ::prost::alloc::string::String,
/// Set ONLY when the request asked for the async shape: the admitted job's id.
/// Empty on every synchronous promotion, so an old client sees no change.
#[prost(string, tag = "5")]
pub job_id: ::prost::alloc::string::String,
}
/// One evidence slot: kind is scan | malware | license | provenance | approval |
/// other; verdict is pass | warn | fail. A caller never supplies `approval`:
/// the server mints it from the authenticated approver (holger-duty-7).
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct IntakeEvidence {
#[prost(string, tag = "1")]
pub kind: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub source: ::prost::alloc::string::String,
#[prost(string, tag = "3")]
pub verdict: ::prost::alloc::string::String,
#[prost(string, tag = "4")]
pub reference: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AdvanceArtifactRequest {
#[prost(message, optional, tag = "1")]
pub artifact: ::core::option::Option<ArtifactId>,
#[prost(enumeration = "IntakeVerb", tag = "2")]
pub verb: i32,
/// Optional: the state ADVANCE is meant to reach (refused unless it is the next one).
#[prost(string, tag = "3")]
pub to_state: ::prost::alloc::string::String,
#[prost(string, tag = "4")]
pub reason: ::prost::alloc::string::String,
#[prost(message, repeated, tag = "5")]
pub evidence: ::prost::alloc::vec::Vec<IntakeEvidence>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AdvanceArtifactResponse {
#[prost(string, tag = "1")]
pub from_state: ::prost::alloc::string::String,
/// The state after the call. Equal to from_state when an approval vote was
/// recorded short of the quorum.
#[prost(string, tag = "2")]
pub state: ::prost::alloc::string::String,
/// Distinct approvals now recorded for the APPROVED hop, and how many it needs.
#[prost(uint32, tag = "3")]
pub approvals: u32,
#[prost(uint32, tag = "4")]
pub approvals_required: u32,
/// The evidence the transition carried (the approval slots on APPROVED).
#[prost(message, repeated, tag = "5")]
pub evidence: ::prost::alloc::vec::Vec<IntakeEvidence>,
#[prost(string, tag = "6")]
pub message: ::prost::alloc::string::String,
#[prost(string, tag = "7")]
pub sha256: ::prost::alloc::string::String,
/// The authenticated principal the server acted for.
#[prost(string, tag = "8")]
pub actor: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct GetArtifactStateRequest {
#[prost(message, optional, tag = "1")]
pub artifact: ::core::option::Option<ArtifactId>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct IntakeTransition {
#[prost(string, tag = "1")]
pub from_state: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub to_state: ::prost::alloc::string::String,
#[prost(string, tag = "3")]
pub actor: ::prost::alloc::string::String,
#[prost(int64, tag = "4")]
pub at: i64,
#[prost(message, repeated, tag = "5")]
pub evidence: ::prost::alloc::vec::Vec<IntakeEvidence>,
#[prost(string, tag = "6")]
pub policy: ::prost::alloc::string::String,
#[prost(string, tag = "7")]
pub reason: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetArtifactStateResponse {
#[prost(string, tag = "1")]
pub state: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub sha256: ::prost::alloc::string::String,
/// The principal that ingested the artifact; it never approves it.
#[prost(string, tag = "3")]
pub importer: ::prost::alloc::string::String,
#[prost(uint32, tag = "4")]
pub approvals: u32,
#[prost(uint32, tag = "5")]
pub approvals_required: u32,
#[prost(message, repeated, tag = "6")]
pub history: ::prost::alloc::vec::Vec<IntakeTransition>,
/// Approval votes recorded short of the quorum.
#[prost(message, repeated, tag = "7")]
pub pending_approvals: ::prost::alloc::vec::Vec<IntakeEvidence>,
/// The source the artifact came from (tier 1 `sources:`); empty on a chain
/// declared with the old `promotion:` spelling.
#[prost(string, tag = "8")]
pub source: ::prost::alloc::string::String,
/// The artifact's effective policy (the floor plus its source's gates), as JSON:
/// each rule with who set it (`floor`, `steps.gates`, `source '<name>'`).
#[prost(string, tag = "9")]
pub effective_policy: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ListIntakeArtifactsRequest {
/// The queue whose rows to return: incoming | quarantined |
/// awaiting-approval | blocked | available. Empty returns the counts only.
#[prost(string, tag = "1")]
pub queue: ::prost::alloc::string::String,
/// At most this many rows (0 = the server's default, 200).
#[prost(uint32, tag = "2")]
pub limit: u32,
}
/// One queue of the security dashboard, as the server groups the states.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct IntakeQueue {
/// The stable name: incoming | quarantined | awaiting-approval | blocked | available.
#[prost(string, tag = "1")]
pub name: ::prost::alloc::string::String,
/// The words an operator reads: "Awaiting approval".
#[prost(string, tag = "2")]
pub title: ::prost::alloc::string::String,
/// The intake states the queue holds, by name.
#[prost(string, repeated, tag = "3")]
pub states: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// The artifacts in the queue that the caller may read.
#[prost(uint64, tag = "4")]
pub count: u64,
}
/// One intake artifact where it stands now.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct IntakeArtifactRow {
#[prost(message, optional, tag = "1")]
pub artifact: ::core::option::Option<ArtifactId>,
#[prost(string, tag = "2")]
pub state: ::prost::alloc::string::String,
#[prost(string, tag = "3")]
pub sha256: ::prost::alloc::string::String,
/// The intake repository it stands in.
#[prost(string, tag = "4")]
pub repository: ::prost::alloc::string::String,
/// The principal of the last transition, and when (Unix seconds).
#[prost(string, tag = "5")]
pub actor: ::prost::alloc::string::String,
#[prost(int64, tag = "6")]
pub at: i64,
/// The state a QUARANTINED artifact was held at.
#[prost(string, tag = "7")]
pub held_from: ::prost::alloc::string::String,
#[prost(string, tag = "8")]
pub importer: ::prost::alloc::string::String,
/// Approval votes recorded short of the quorum, and the quorum.
#[prost(uint32, tag = "9")]
pub approvals: u32,
#[prost(uint32, tag = "10")]
pub approvals_required: u32,
/// The policy's words and the reason of the last transition.
#[prost(string, tag = "11")]
pub policy: ::prost::alloc::string::String,
#[prost(string, tag = "12")]
pub reason: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ListIntakeArtifactsResponse {
#[prost(message, repeated, tag = "1")]
pub queues: ::prost::alloc::vec::Vec<IntakeQueue>,
/// The rows of the queue asked for.
#[prost(message, repeated, tag = "2")]
pub artifacts: ::prost::alloc::vec::Vec<IntakeArtifactRow>,
/// True when the queue held more rows than `limit`.
#[prost(bool, tag = "3")]
pub truncated: bool,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct GetArtifactEvidenceRequest {
#[prost(message, optional, tag = "1")]
pub artifact: ::core::option::Option<ArtifactId>,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct EvidenceHash {
/// sha256 | blake3.
#[prost(string, tag = "1")]
pub alg: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub hex: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct EvidenceFinding {
#[prost(string, tag = "1")]
pub id: ::prost::alloc::string::String,
/// info | low | medium | high | critical.
#[prost(string, tag = "2")]
pub severity: ::prost::alloc::string::String,
#[prost(string, tag = "3")]
pub summary: ::prost::alloc::string::String,
}
/// One scanner's evidence about the artifact.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct EvidenceRecord {
#[prost(string, tag = "1")]
pub scanner_id: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub scanner_version: ::prost::alloc::string::String,
/// inspection | malware | vulnerability | license | secrets | provenance | sbom.
#[prost(string, tag = "3")]
pub kind: ::prost::alloc::string::String,
/// pass | warn | block | error.
#[prost(string, tag = "4")]
pub verdict: ::prost::alloc::string::String,
#[prost(message, repeated, tag = "5")]
pub findings: ::prost::alloc::vec::Vec<EvidenceFinding>,
#[prost(message, repeated, tag = "6")]
pub inputs: ::prost::alloc::vec::Vec<EvidenceHash>,
#[prost(string, tag = "7")]
pub detail: ::prost::alloc::string::String,
/// The operator requires this kind; an error from it blocks.
#[prost(bool, tag = "8")]
pub required: bool,
/// No scanner is installed in this slot.
#[prost(bool, tag = "9")]
pub not_configured: bool,
/// A document the scanner produced (the CycloneDX SBOM), as JSON. Empty when none.
#[prost(string, tag = "10")]
pub document_json: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetArtifactEvidenceResponse {
/// The intake state and the sha256 recorded at ingest.
#[prost(string, tag = "1")]
pub state: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub sha256: ::prost::alloc::string::String,
/// False when no scan has recorded evidence for these bytes yet.
#[prost(bool, tag = "3")]
pub scanned: bool,
#[prost(string, tag = "4")]
pub file_name: ::prost::alloc::string::String,
#[prost(string, tag = "5")]
pub ecosystem: ::prost::alloc::string::String,
#[prost(uint64, tag = "6")]
pub size: u64,
/// The hashes of the bytes the scanners saw.
#[prost(message, repeated, tag = "7")]
pub hashes: ::prost::alloc::vec::Vec<EvidenceHash>,
/// The fold over every record: pass | warn | block | error.
#[prost(string, tag = "8")]
pub verdict: ::prost::alloc::string::String,
/// One sentence per reason the verdict is not pass.
#[prost(string, repeated, tag = "9")]
pub reasons: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
#[prost(message, repeated, tag = "10")]
pub records: ::prost::alloc::vec::Vec<EvidenceRecord>,
/// When the scan ran, Unix seconds.
#[prost(int64, tag = "11")]
pub scanned_at: i64,
/// The policy's words on the last transition.
#[prost(string, tag = "12")]
pub policy: ::prost::alloc::string::String,
/// W5: every stored record about these bytes, oldest scan first, each with the
/// envelope that signs it.
#[prost(message, repeated, tag = "13")]
pub stored: ::prost::alloc::vec::Vec<ArtifactEvidenceRecord>,
/// The attestation signer's certificate (DER) the envelopes verify against.
#[prost(bytes = "vec", tag = "14")]
pub signer_cert: ::prost::alloc::vec::Vec<u8>,
/// `/-/intake/sbom?sha256=<hex>` when the newest record carries an SBOM.
#[prost(string, tag = "15")]
pub sbom_link: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ListDependencySetsRequest {
/// Only the sets in this status (resolving | held | refused | awaiting-approval |
/// approved | available); empty: every set the caller may read.
#[prost(string, tag = "1")]
pub status: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ListDependencySetsResponse {
/// Newest first.
#[prost(message, repeated, tag = "1")]
pub sets: ::prost::alloc::vec::Vec<DependencySet>,
/// How many distinct approvers each member needs.
#[prost(uint32, tag = "2")]
pub approvals_required: u32,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct GetDependencySetRequest {
#[prost(string, tag = "1")]
pub id: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct JudgeDependencySetRequest {
#[prost(string, tag = "1")]
pub id: ::prost::alloc::string::String,
/// Why: kept with every vote; a refusal names it on every blocked member (required).
#[prost(string, tag = "2")]
pub reason: ::prost::alloc::string::String,
/// The `revision` of the set as the caller was shown it (SEC-REVIEW D4, required): a vote
/// naming none, or another than the set has now, is refused (FAILED_PRECONDITION,
/// holger-depset-4) and nothing is cast.
#[prost(string, tag = "3")]
pub revision: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct JudgeDependencySetResponse {
#[prost(string, tag = "1")]
pub id: ::prost::alloc::string::String,
/// Where the set stands after the call.
#[prost(string, tag = "2")]
pub status: ::prost::alloc::string::String,
/// The members this call voted on (approve) or blocked (refuse).
#[prost(uint32, tag = "3")]
pub moved: u32,
#[prost(string, tag = "4")]
pub message: ::prost::alloc::string::String,
#[prost(message, optional, tag = "5")]
pub set: ::core::option::Option<DependencySet>,
}
/// A member or a coordinate, and why it refuses or holds a set.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct DependencySetReason {
#[prost(string, tag = "1")]
pub name: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub why: ::prost::alloc::string::String,
}
/// One member of a set, as an approver is shown it.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct DependencySetMember {
/// The chain coordinate (`pypi/dep-1.0-py3-none-any.whl`).
#[prost(string, tag = "1")]
pub name: ::prost::alloc::string::String,
/// requested | parent | bom | descriptor | dependency.
#[prost(string, tag = "2")]
pub role: ::prost::alloc::string::String,
/// What needed it.
#[prost(string, tag = "3")]
pub via: ::prost::alloc::string::String,
/// The intake state (POLICY_CHECKED …), or not-in-chain.
#[prost(string, tag = "4")]
pub state: ::prost::alloc::string::String,
#[prost(string, tag = "5")]
pub sha256: ::prost::alloc::string::String,
/// The votes cast on its current bytes, and by whom.
#[prost(uint32, tag = "6")]
pub approvals: u32,
#[prost(string, repeated, tag = "7")]
pub approvers: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// Why it is refused or held, when it is.
#[prost(string, tag = "8")]
pub reason: ::prost::alloc::string::String,
/// Advisories recorded as a warning.
#[prost(string, repeated, tag = "9")]
pub warnings: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
}
/// One dependency set: what a pull brought in, judged as one.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct DependencySet {
#[prost(string, tag = "1")]
pub id: ::prost::alloc::string::String,
/// The pull-through source.
#[prost(string, tag = "2")]
pub source: ::prost::alloc::string::String,
/// maven | npm | crates | python.
#[prost(string, tag = "3")]
pub ecosystem: ::prost::alloc::string::String,
/// What was asked for, in the ecosystem's words (`app==1.0`).
#[prost(string, tag = "4")]
pub root: ::prost::alloc::string::String,
/// When the pull ran, Unix seconds.
#[prost(int64, tag = "5")]
pub at: i64,
/// resolving | held | refused | awaiting-approval | approved | available.
#[prost(string, tag = "6")]
pub status: ::prost::alloc::string::String,
/// The words for the status.
#[prost(string, tag = "7")]
pub summary: ::prost::alloc::string::String,
#[prost(message, repeated, tag = "8")]
pub members: ::prost::alloc::vec::Vec<DependencySetMember>,
/// The members that refuse the set.
#[prost(message, repeated, tag = "9")]
pub blockers: ::prost::alloc::vec::Vec<DependencySetReason>,
/// What holds the set.
#[prost(message, repeated, tag = "10")]
pub holds: ::prost::alloc::vec::Vec<DependencySetReason>,
#[prost(uint32, tag = "11")]
pub approvals_required: u32,
/// The approvers who voted on every member still waiting.
#[prost(string, repeated, tag = "12")]
pub approvers: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// Members waiting at POLICY_CHECKED, and members AVAILABLE.
#[prost(uint32, tag = "13")]
pub awaiting: u32,
#[prost(uint32, tag = "14")]
pub available: u32,
#[prost(string, repeated, tag = "15")]
pub notes: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// What a vote names (SEC-REVIEW D4): a hash over the members and their sha256 as shown.
#[prost(string, tag = "16")]
pub revision: ::prost::alloc::string::String,
}
/// One stored scan-evidence record (W5).
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ArtifactEvidenceRecord {
/// The blake3 of the record's bytes: its name in the evidence store.
#[prost(string, tag = "1")]
pub id: ::prost::alloc::string::String,
/// When the scan ran, Unix seconds.
#[prost(int64, tag = "2")]
pub scanned_at: i64,
/// The fold over every scanner: pass | warn | block | error.
#[prost(string, tag = "3")]
pub verdict: ::prost::alloc::string::String,
#[prost(string, repeated, tag = "4")]
pub reasons: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// The record itself (holger.scan-evidence/v1 JSON), byte-identical to the store.
#[prost(bytes = "vec", tag = "5")]
pub evidence_json: ::prost::alloc::vec::Vec<u8>,
/// The DSSE envelope (in-toto, predicate <https://holger.rs/attestation/scan-evidence/v1>)
/// that verifies to this record; empty when the record is not signed.
#[prost(bytes = "vec", tag = "6")]
pub envelope: ::prost::alloc::vec::Vec<u8>,
/// Empty when a scan now would agree; otherwise why it is stale (a newer
/// scanner version or intel database sequence).
#[prost(string, tag = "7")]
pub stale: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct GetArtifactTrailRequest {
/// Lowercase-hex SHA-256 of the artifact's bytes (a `sha256:` prefix is allowed).
#[prost(string, tag = "1")]
pub sha256: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ArtifactTrailEntry {
/// The record's sequence number and chain hash in the audit log.
#[prost(uint64, tag = "1")]
pub seq: u64,
#[prost(string, tag = "2")]
pub hash: ::prost::alloc::string::String,
#[prost(int64, tag = "3")]
pub ts_nanos: i64,
/// imported | hash_verified | scanned | policy_passed | policy_denied |
/// approved | sealed | exported | airgap_imported
#[prost(string, tag = "4")]
pub kind: ::prost::alloc::string::String,
#[prost(string, tag = "5")]
pub ident: ::prost::alloc::string::String,
#[prost(string, tag = "6")]
pub repo: ::prost::alloc::string::String,
#[prost(string, tag = "7")]
pub artifact: ::prost::alloc::string::String,
#[prost(uint32, tag = "8")]
pub status: u32,
#[prost(string, tag = "9")]
pub detail: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetArtifactTrailResponse {
#[prost(string, tag = "1")]
pub sha256: ::prost::alloc::string::String,
#[prost(message, repeated, tag = "2")]
pub entries: ::prost::alloc::vec::Vec<ArtifactTrailEntry>,
/// Whether the whole audit chain verified when the trail was read.
#[prost(bool, tag = "3")]
pub chain_intact: bool,
#[prost(string, tag = "4")]
pub chain_summary: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct QueryDownloadsRequest {
/// Who downloaded (the authenticated principal; `anonymous` for open reads).
/// Empty = anybody.
#[prost(string, tag = "1")]
pub ident: ::prost::alloc::string::String,
/// The repository. Empty = every repository.
#[prost(string, tag = "2")]
pub repo: ::prost::alloc::string::String,
/// From (inclusive) and to (exclusive), nanoseconds since the Unix epoch.
/// Zero = open.
#[prost(int64, tag = "3")]
pub since_nanos: i64,
#[prost(int64, tag = "4")]
pub until_nanos: i64,
/// At most this many rows, the NEWEST that match. Zero = 1000; capped at 10000.
#[prost(uint64, tag = "5")]
pub limit: u64,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct DownloadRow {
#[prost(uint64, tag = "1")]
pub seq: u64,
#[prost(string, tag = "2")]
pub hash: ::prost::alloc::string::String,
#[prost(int64, tag = "3")]
pub ts_nanos: i64,
#[prost(string, tag = "4")]
pub ident: ::prost::alloc::string::String,
#[prost(string, tag = "5")]
pub repo: ::prost::alloc::string::String,
#[prost(string, tag = "6")]
pub artifact: ::prost::alloc::string::String,
#[prost(string, tag = "7")]
pub source_ip: ::prost::alloc::string::String,
#[prost(uint32, tag = "8")]
pub status: u32,
#[prost(uint64, tag = "9")]
pub bytes: u64,
#[prost(string, tag = "10")]
pub sha256: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct QueryDownloadsResponse {
#[prost(message, repeated, tag = "1")]
pub rows: ::prost::alloc::vec::Vec<DownloadRow>,
/// How many rows matched in all, and whether the limit left some out.
#[prost(uint64, tag = "2")]
pub matched: u64,
#[prost(bool, tag = "3")]
pub truncated: bool,
}
/// Which records: every field optional, set fields AND together.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AuditFilter {
/// The actor (authenticated principal; "anonymous" for open reads).
#[prost(string, tag = "1")]
pub ident: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub repo: ::prost::alloc::string::String,
/// A PREFIX of the artifact: "acme/" a namespace, "acme/widget@" every version.
#[prost(string, tag = "3")]
pub artifact_prefix: ::prost::alloc::string::String,
/// download | upload | delete | list | promote | entitlement | purge | scan |
/// token | other. Any other word is refused.
#[prost(string, tag = "4")]
pub action: ::prost::alloc::string::String,
/// The client address; without a port it matches every port of the address.
#[prost(string, tag = "5")]
pub source_ip: ::prost::alloc::string::String,
/// The exact status. 0 = any.
#[prost(uint32, tag = "6")]
pub status: u32,
/// From (inclusive) and to (exclusive), nanoseconds since the Unix epoch. 0 = open.
#[prost(int64, tag = "7")]
pub since_nanos: i64,
#[prost(int64, tag = "8")]
pub until_nanos: i64,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AuditRecordRow {
#[prost(uint64, tag = "1")]
pub seq: u64,
#[prost(string, tag = "2")]
pub hash: ::prost::alloc::string::String,
#[prost(int64, tag = "3")]
pub ts_nanos: i64,
#[prost(string, tag = "4")]
pub ident: ::prost::alloc::string::String,
#[prost(string, tag = "5")]
pub action: ::prost::alloc::string::String,
#[prost(string, tag = "6")]
pub repo: ::prost::alloc::string::String,
#[prost(string, tag = "7")]
pub artifact: ::prost::alloc::string::String,
#[prost(string, tag = "8")]
pub source_ip: ::prost::alloc::string::String,
#[prost(uint32, tag = "9")]
pub status: u32,
#[prost(uint64, tag = "10")]
pub bytes: u64,
#[prost(string, tag = "11")]
pub detail: ::prost::alloc::string::String,
#[prost(string, tag = "12")]
pub sha256: ::prost::alloc::string::String,
#[prost(string, tag = "13")]
pub trail: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AuditQueryRequest {
#[prost(message, optional, tag = "1")]
pub filter: ::core::option::Option<AuditFilter>,
/// Matching records to skip; pass back next_offset.
#[prost(uint64, tag = "2")]
pub offset: u64,
/// Page size. 0 = 100; capped at 1000 (limit_applied says what was used).
#[prost(uint32, tag = "3")]
pub limit: u32,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AuditQueryResponse {
/// The page, oldest first.
#[prost(message, repeated, tag = "1")]
pub records: ::prost::alloc::vec::Vec<AuditRecordRow>,
/// Every match before paging: the number to show.
#[prost(uint64, tag = "2")]
pub matched: u64,
#[prost(uint64, tag = "3")]
pub next_offset: u64,
/// Matches exist beyond this page.
#[prost(bool, tag = "4")]
pub more: bool,
#[prost(uint64, tag = "5")]
pub scanned: u64,
#[prost(uint32, tag = "6")]
pub limit_applied: u32,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AuditAggregateRequest {
#[prost(message, optional, tag = "1")]
pub filter: ::core::option::Option<AuditFilter>,
/// repo | action | day | ident | client | status. Empty = repo, action, day.
#[prost(string, repeated, tag = "2")]
pub group_by: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// Only 2xx statuses (what was served, not what was refused).
#[prost(bool, tag = "3")]
pub ok_only: bool,
/// At most this many groups (the first in key order). 0 = 10000.
#[prost(uint32, tag = "4")]
pub max_groups: u32,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AuditAggregateRow {
/// The keys not grouped on are empty (status 0).
#[prost(string, tag = "1")]
pub repo: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub action: ::prost::alloc::string::String,
/// YYYY-MM-DD, UTC.
#[prost(string, tag = "3")]
pub day: ::prost::alloc::string::String,
#[prost(string, tag = "4")]
pub ident: ::prost::alloc::string::String,
/// The client address without its port. An address is not an identity.
#[prost(string, tag = "5")]
pub client: ::prost::alloc::string::String,
#[prost(uint32, tag = "6")]
pub status: u32,
#[prost(uint64, tag = "7")]
pub count: u64,
#[prost(uint64, tag = "8")]
pub bytes: u64,
#[prost(int64, tag = "9")]
pub first_ts_nanos: i64,
#[prost(int64, tag = "10")]
pub last_ts_nanos: i64,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AuditAggregateResponse {
#[prost(string, repeated, tag = "1")]
pub group_by: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
#[prost(message, repeated, tag = "2")]
pub rows: ::prost::alloc::vec::Vec<AuditAggregateRow>,
#[prost(bool, tag = "3")]
pub groups_truncated: bool,
#[prost(uint64, tag = "4")]
pub rows_counted: u64,
#[prost(uint64, tag = "5")]
pub scanned: u64,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AuditExportRequest {
#[prost(message, optional, tag = "1")]
pub filter: ::core::option::Option<AuditFilter>,
/// Only rows with seq >= since_seq (the next page: next_seq of the last reply).
#[prost(uint64, tag = "2")]
pub since_seq: u64,
/// At most this many rows, the oldest that match. 0 = 50000; capped at 50000.
#[prost(uint32, tag = "3")]
pub limit: u32,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AuditExportResponse {
/// One Arrow IPC file.
#[prost(bytes = "vec", tag = "1")]
pub arrow_ipc: ::prost::alloc::vec::Vec<u8>,
#[prost(uint64, tag = "2")]
pub rows: u64,
#[prost(bool, tag = "3")]
pub truncated: bool,
#[prost(uint64, tag = "4")]
pub next_seq: u64,
/// "holger.audit.index/v1" and the schema, `name:type` per column.
#[prost(string, tag = "5")]
pub layout: ::prost::alloc::string::String,
#[prost(string, tag = "6")]
pub schema: ::prost::alloc::string::String,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
pub struct VerifyAuditChainRequest {}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct VerifyAuditChainResponse {
#[prost(bool, tag = "1")]
pub intact: bool,
#[prost(uint64, tag = "2")]
pub records: u64,
#[prost(uint64, tag = "3")]
pub checkpoints: u64,
#[prost(uint64, tag = "4")]
pub signatures_verified: u64,
#[prost(uint64, tag = "5")]
pub signatures_unchecked: u64,
#[prost(uint64, tag = "6")]
pub unsigned_checkpoints: u64,
/// The hash of the last line that verified.
#[prost(string, tag = "7")]
pub head: ::prost::alloc::string::String,
/// The first break: 1-based line, its seq, and why. Zero / empty when intact.
#[prost(uint64, tag = "8")]
pub break_line: u64,
#[prost(uint64, tag = "9")]
pub break_seq: u64,
#[prost(string, tag = "10")]
pub break_reason: ::prost::alloc::string::String,
#[prost(string, tag = "11")]
pub summary: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SearchRequest {
/// Case-insensitive substring match on the artifact NAME (Maven artifactId,
/// crate name, …). Empty = any name.
#[prost(string, tag = "1")]
pub name: ::prost::alloc::string::String,
/// Case-insensitive substring match on the NAMESPACE (Maven groupId, npm
/// scope). Empty = any / no namespace constraint.
#[prost(string, tag = "2")]
pub namespace: ::prost::alloc::string::String,
/// Exact match on the artifact VERSION. Empty = any version.
#[prost(string, tag = "3")]
pub version: ::prost::alloc::string::String,
/// Lowercase-hex sha256 of the artifact CONTENT (exact, case-insensitive).
/// Setting this forces the server to hash candidate artifacts' bytes, so it is
/// the one expensive axis — leave empty unless you are searching by digest.
#[prost(string, tag = "4")]
pub checksum: ::prost::alloc::string::String,
/// Case-insensitive substring match on a RAW archive file path. Produces path
/// hits (see `paths`), independent of the artifact axes above.
#[prost(string, tag = "5")]
pub path: ::prost::alloc::string::String,
/// Restrict the search to these repository names. Empty = every configured repo.
#[prost(string, repeated, tag = "6")]
pub repositories: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// Cap the number of hits returned (per hit kind). 0 ⇒ a server default.
#[prost(int32, tag = "7")]
pub limit: i32,
/// Custom-PROPERTY filters (AND-composed with each other and the axes above). An
/// artifact matches only if it carries every listed property. Empty = no
/// property constraint. Requires the server to have a property store configured;
/// with none, a property filter matches nothing (fail-closed).
#[prost(message, repeated, tag = "8")]
pub properties: ::prost::alloc::vec::Vec<PropertyMatch>,
}
/// One custom-property filter: the artifact must carry `key`, and — when `value`
/// is non-empty — that exact value among the key's values (empty `value` = "the
/// key is present, any value").
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct PropertyMatch {
#[prost(string, tag = "1")]
pub key: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub value: ::prost::alloc::string::String,
}
/// One artifact matched by name / coordinate / checksum, tagged with the repo it
/// was found in.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ArtifactHit {
#[prost(string, tag = "1")]
pub repository: ::prost::alloc::string::String,
#[prost(message, optional, tag = "2")]
pub id: ::core::option::Option<ArtifactId>,
#[prost(int64, tag = "3")]
pub size_bytes: i64,
#[prost(string, tag = "4")]
pub content_type: ::prost::alloc::string::String,
/// sha256 hex of the content — set ONLY when a checksum query forced a hash
/// (empty otherwise, to keep the common name/coordinate search cheap).
#[prost(string, tag = "5")]
pub checksum: ::prost::alloc::string::String,
}
/// One raw archive path matched by the `path` axis, tagged with its repo.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct PathHit {
#[prost(string, tag = "1")]
pub repository: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub path: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SearchResponse {
#[prost(message, repeated, tag = "1")]
pub artifacts: ::prost::alloc::vec::Vec<ArtifactHit>,
#[prost(message, repeated, tag = "2")]
pub paths: ::prost::alloc::vec::Vec<PathHit>,
/// True when the result set hit the `limit` cap and more hits exist.
#[prost(bool, tag = "3")]
pub truncated: bool,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AttachSbomRequest {
/// The repository the artifact lives in.
#[prost(string, tag = "1")]
pub repository: ::prost::alloc::string::String,
/// The artifact coordinate the SBOM describes (namespace/name/version).
#[prost(message, optional, tag = "2")]
pub artifact: ::core::option::Option<ArtifactId>,
/// The SBOM document bytes to host (a CycloneDX 1.5 JSON document). Served back
/// byte-identical by FetchSbom / the HTTP door.
#[prost(bytes = "vec", tag = "3")]
pub document: ::prost::alloc::vec::Vec<u8>,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AttachSbomResponse {
#[prost(bool, tag = "1")]
pub success: bool,
#[prost(string, tag = "2")]
pub message: ::prost::alloc::string::String,
/// blake3 hex of the attached document (the SBOM's content address).
#[prost(string, tag = "3")]
pub content_address: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct FetchSbomRequest {
#[prost(string, tag = "1")]
pub repository: ::prost::alloc::string::String,
#[prost(message, optional, tag = "2")]
pub artifact: ::core::option::Option<ArtifactId>,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct FetchSbomResponse {
/// The hosted SBOM document bytes (byte-identical to what was attached).
#[prost(bytes = "vec", tag = "1")]
pub document: ::prost::alloc::vec::Vec<u8>,
#[prost(int64, tag = "2")]
pub size_bytes: i64,
/// blake3 hex of the document (its content address).
#[prost(string, tag = "3")]
pub content_address: ::prost::alloc::string::String,
}
/// One property: a key with its ordered set of values (the map's entry form on
/// the wire, since proto has no first-class ordered multimap here).
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct PropertyEntry {
#[prost(string, tag = "1")]
pub key: ::prost::alloc::string::String,
#[prost(string, repeated, tag = "2")]
pub values: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct SetPropertyRequest {
#[prost(string, tag = "1")]
pub repository: ::prost::alloc::string::String,
#[prost(message, optional, tag = "2")]
pub artifact: ::core::option::Option<ArtifactId>,
/// The property key to set (or, with empty `values`, remove).
#[prost(string, tag = "3")]
pub key: ::prost::alloc::string::String,
/// The key's values (deduped, order preserved). EMPTY ⇒ remove the key.
#[prost(string, repeated, tag = "4")]
pub values: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SetPropertyResponse {
#[prost(bool, tag = "1")]
pub success: bool,
#[prost(string, tag = "2")]
pub message: ::prost::alloc::string::String,
/// The coordinate's full property map AFTER the set/remove.
#[prost(message, repeated, tag = "3")]
pub properties: ::prost::alloc::vec::Vec<PropertyEntry>,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct GetPropertiesRequest {
#[prost(string, tag = "1")]
pub repository: ::prost::alloc::string::String,
#[prost(message, optional, tag = "2")]
pub artifact: ::core::option::Option<ArtifactId>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetPropertiesResponse {
/// The coordinate's full property map (empty when none attached).
#[prost(message, repeated, tag = "1")]
pub properties: ::prost::alloc::vec::Vec<PropertyEntry>,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ReplicateRequest {
/// Source repository — read-only here (only listed + fetched, never mutated).
#[prost(string, tag = "1")]
pub from_repo: ::prost::alloc::string::String,
/// Destination repository — where artifacts land. MUST be writable.
#[prost(string, tag = "2")]
pub to_repo: ::prost::alloc::string::String,
/// false (default) = dry-run PREVIEW (report what would copy, write nothing);
/// true = actually copy the missing artifacts into the destination.
#[prost(bool, tag = "3")]
pub execute: bool,
/// Cap the number of source artifacts examined; 0 = unlimited.
#[prost(int32, tag = "4")]
pub limit: i32,
/// ASYNC SHAPE -- see `PromoteArtifactRequest.async_job`. True admits it to the
/// job queue and answers with `job_id`. An EXECUTING replication on a server
/// with a job queue is queued even when this is unset; a dry run, or a server
/// without a queue, runs on this RPC and the caller waits.
#[prost(bool, tag = "5")]
pub async_job: bool,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ReplicateResponse {
/// Total source artifacts examined.
#[prost(int64, tag = "1")]
pub examined: i64,
/// Artifacts actually written into the destination (0 on a dry run).
#[prost(int64, tag = "2")]
pub copied: i64,
/// Artifacts already present in the destination by content id (skipped).
#[prost(int64, tag = "3")]
pub skipped: i64,
/// Artifacts a dry run WOULD copy (0 on an executing run).
#[prost(int64, tag = "4")]
pub would_copy: i64,
/// Artifacts that could not be replicated (source unreadable / dest read-only).
#[prost(int64, tag = "5")]
pub failed: i64,
/// Sum of bytes copied (0 on a dry run).
#[prost(int64, tag = "6")]
pub copied_bytes: i64,
/// True when the `limit` cap was hit and more source artifacts remained.
#[prost(bool, tag = "7")]
pub truncated: bool,
/// True when nothing failed — the replication is fully accounted for.
#[prost(bool, tag = "8")]
pub complete: bool,
#[prost(string, tag = "9")]
pub message: ::prost::alloc::string::String,
/// Set ONLY when the request asked for the async shape: the admitted job's id.
/// Every count above is 0 in that case -- nothing has run yet, and reporting a
/// zero as a result would be a lie. Read the outcome with `JobService.GetJob`.
#[prost(string, tag = "10")]
pub job_id: ::prost::alloc::string::String,
}
/// Where a migration reads FROM, credentials included.
///
/// ⚠ The credential is a PARAMETER and lives in memory for the life of the job
/// alone. It is never written to disk, never echoed back by any RPC here, and
/// never audited. A one-shot move does not need a stored secret, and a stored
/// secret is a standing capability against someone else's registry that outlives
/// the reason it was given. Persisting one is a separate decision with its own
/// holder (`nornir-vault`), and it is not made here.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct MigrationSource {
#[prost(enumeration = "migration_source::Kind", tag = "1")]
pub kind: i32,
/// Nexus: the base URL. Artifactory: the URL up to (not including)
/// `/artifactory`.
#[prost(string, tag = "2")]
pub base_url: ::prost::alloc::string::String,
/// Basic-auth credential. In memory only — see the warning above.
#[prost(string, tag = "3")]
pub username: ::prost::alloc::string::String,
#[prost(string, tag = "4")]
pub password: ::prost::alloc::string::String,
/// Migrate only this ONE source repository. Empty = the whole registry.
#[prost(string, tag = "5")]
pub repository: ::prost::alloc::string::String,
}
/// Nested message and enum types in `MigrationSource`.
pub mod migration_source {
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
PartialOrd,
Ord,
::prost::Enumeration
)]
#[repr(i32)]
pub enum Kind {
MigrationSourceUnspecified = 0,
Nexus = 1,
Artifactory = 2,
}
impl Kind {
/// String value of the enum field names used in the ProtoBuf definition.
///
/// The values are not transformed in any way and thus are considered stable
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
pub fn as_str_name(&self) -> &'static str {
match self {
Self::MigrationSourceUnspecified => "MIGRATION_SOURCE_UNSPECIFIED",
Self::Nexus => "NEXUS",
Self::Artifactory => "ARTIFACTORY",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
match value {
"MIGRATION_SOURCE_UNSPECIFIED" => Some(Self::MigrationSourceUnspecified),
"NEXUS" => Some(Self::Nexus),
"ARTIFACTORY" => Some(Self::Artifactory),
_ => None,
}
}
}
}
/// One source repository and what taking it would mean for holger.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct MigrationRepoPlan {
#[prost(string, tag = "1")]
pub source_repo: ::prost::alloc::string::String,
/// The format string the SOURCE used, verbatim (`maven2`, `pypi`, `generic`).
#[prost(string, tag = "2")]
pub source_format: ::prost::alloc::string::String,
#[prost(string, tag = "3")]
pub target_repo: ::prost::alloc::string::String,
/// holger's `ron_repo_type` for the mapped format (`maven3`, `pip`, `raw`).
/// Empty when holger has no format for what the source said.
#[prost(string, tag = "4")]
pub target_format: ::prost::alloc::string::String,
/// `existing` | `create` | `collision` | `unmapped_format`.
#[prost(string, tag = "5")]
pub disposition: ::prost::alloc::string::String,
/// Why this repository refuses, when it does. Empty otherwise.
#[prost(string, tag = "6")]
pub refusal_reason: ::prost::alloc::string::String,
/// Assets the source LISTED. No artifact content was read to count them.
#[prost(int64, tag = "7")]
pub assets: i64,
/// Sum of the sizes the source's listing advertised. 0 where it advertised
/// none — which is "not stated", not "empty".
#[prost(int64, tag = "8")]
pub bytes: i64,
/// The RON declaration an operator must add to the wired config, and restart,
/// BEFORE this repository can be filled. Non-empty only for `create`.
///
/// ⚠ holger cannot create a repository while it is running: the route table is
/// built from the config at boot and is immutable for the process lifetime. So
/// a `create` row is not a thing the migration will do — it is a thing a person
/// must do first. Rendered by `traits::migrate::ron_declaration`, the same
/// function the run-time refusal quotes, so the console and the terminal hand
/// over one text and not two.
#[prost(string, tag = "9")]
pub declaration: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct DiscoverMigrationRequest {
#[prost(message, optional, tag = "1")]
pub source: ::core::option::Option<MigrationSource>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct DiscoverMigrationResponse {
#[prost(message, repeated, tag = "1")]
pub repos: ::prost::alloc::vec::Vec<MigrationRepoPlan>,
#[prost(int64, tag = "2")]
pub total_assets: i64,
#[prost(int64, tag = "3")]
pub total_bytes: i64,
/// True when nothing refuses — this plan would actually run.
#[prost(bool, tag = "4")]
pub would_run: bool,
/// One line per refusing repository. Non-empty iff `would_run` is false.
#[prost(string, repeated, tag = "5")]
pub refusals: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// The same human preview the CLI's `--dry-run` prints, rendered ONCE in
/// `traits::migrate` so the UI and the terminal cannot describe the same plan
/// in two different ways.
#[prost(string, tag = "6")]
pub report: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct StartMigrationRequest {
#[prost(message, optional, tag = "1")]
pub source: ::core::option::Option<MigrationSource>,
/// In-flight asset transfers. 0 = the engine default.
#[prost(int32, tag = "2")]
pub concurrency: i32,
/// ⚠ Inverted ON PURPOSE. proto3 has no field presence for a bool, so a
/// `verify_digests` a caller forgot to set would arrive as false and silently
/// turn the check off. The safe state has to be the zero value: leave this
/// alone and every asset the source published a sha256 for is verified before
/// it is stored.
#[prost(bool, tag = "3")]
pub skip_digest_verification: bool,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StartMigrationResponse {
/// Follow it with `Watch`, stop it with `Cancel`.
#[prost(string, tag = "1")]
pub job_id: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub message: ::prost::alloc::string::String,
/// Echo of the plan the job started with, so a caller that skipped `Discover`
/// still learns which repositories it is creating.
#[prost(message, repeated, tag = "3")]
pub repos: ::prost::alloc::vec::Vec<MigrationRepoPlan>,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct WatchMigrationRequest {
#[prost(string, tag = "1")]
pub job_id: ::prost::alloc::string::String,
}
/// One progress row. A watcher that joins late receives the latest row for each
/// repository first, then follows live — so a UI that reconnects is not blind.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct MigrationProgressEvent {
#[prost(string, tag = "1")]
pub job_id: ::prost::alloc::string::String,
/// The holger repository this row is about.
#[prost(string, tag = "2")]
pub repo: ::prost::alloc::string::String,
/// Assets written into this repository so far.
#[prost(int64, tag = "3")]
pub done: i64,
/// Assets that could not be moved.
#[prost(int64, tag = "4")]
pub failed: i64,
/// Assets the destination already held — the idempotence count.
#[prost(int64, tag = "5")]
pub skipped: i64,
/// Assets the source listed for this repository: the denominator.
#[prost(int64, tag = "6")]
pub total: i64,
#[prost(int64, tag = "7")]
pub bytes: i64,
/// Last row for this repository.
#[prost(bool, tag = "8")]
pub repo_finished: bool,
/// Last row for the whole job. The stream ends after it.
#[prost(bool, tag = "9")]
pub job_finished: bool,
/// Only meaningful when `job_finished`: nothing failed and it was not cut
/// short. A migration that "succeeded" with failures is one an operator would
/// wrongly believe is done.
#[prost(bool, tag = "10")]
pub complete: bool,
#[prost(bool, tag = "11")]
pub cancelled: bool,
#[prost(string, tag = "12")]
pub message: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct CancelMigrationRequest {
#[prost(string, tag = "1")]
pub job_id: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct CancelMigrationResponse {
/// True when the job was running and is now winding down. False when it had
/// already finished — which is not an error, just an answer.
#[prost(bool, tag = "1")]
pub cancelling: bool,
#[prost(string, tag = "2")]
pub message: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct WhoAmIRequest {
/// Optional. When set, the answer also carries the caller's role ON THIS
/// repository (`repository_role`) — the per-repository ACL included, the same
/// resolution the write and admin gates apply. A console asks this instead of
/// deciding for itself what a person may do to a repository (holger-ui's
/// thin-layer move, 2026-10-04: buying room for a repository is a write on it).
#[prost(string, tag = "1")]
pub repository: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct WhoAmIResponse {
/// True when the presented credential validated against a configured method.
#[prost(bool, tag = "1")]
pub authenticated: bool,
/// The validated principal (OIDC sub / StaticToken subject / mTLS CN).
/// Empty for anonymous callers.
#[prost(string, tag = "2")]
pub subject: ::prost::alloc::string::String,
/// Which configured method validated the credential (e.g. "bearer", "oidc",
/// "mtls"). Empty for anonymous callers.
#[prost(string, tag = "3")]
pub method: ::prost::alloc::string::String,
/// The caller's effective GLOBAL role name ("denied"/"reader"/"writer"/
/// "admin"), from the RBAC map or the default role. Per-repo ACLs can grant
/// or deny beyond this — this is discoverability, not authorization.
#[prost(string, tag = "4")]
pub global_role: ::prost::alloc::string::String,
/// Whether the opt-in read gate (`require_auth_for_reads`) is active — with
/// it on, even reads need the reader floor.
#[prost(bool, tag = "5")]
pub read_gate: bool,
/// The caller's effective role on `WhoAmIRequest.repository`
/// ("denied"/"reader"/"writer"/"admin"), per-repository ACL included. Empty
/// when no repository was asked about.
#[prost(string, tag = "6")]
pub repository_role: ::prost::alloc::string::String,
/// What is open on this Holger, in plain words (HCON-5: the RON's `access`
/// block and its public repositories), read only.
#[prost(string, tag = "7")]
pub access_words: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ServerProfileResponse {
/// "static" (sealed / read-only) or "dynamic" (writable / proxy).
#[prost(string, tag = "1")]
pub profile: ::prost::alloc::string::String,
/// True when the server accepts no writes on any repository — server truth,
/// derived from the live route table (or an explicit sealed-mode override).
#[prost(bool, tag = "2")]
pub read_only: bool,
/// Human label for the UI chrome/badge (e.g. the red "silent running" strip).
#[prost(string, tag = "3")]
pub label: ::prost::alloc::string::String,
/// Number of configured repositories that accept writes (0 ⇒ read_only).
#[prost(int32, tag = "4")]
pub writable_repo_count: i32,
/// ── THE MODULE CENSUS ────────────────────────────────────────────────────
///
/// An appliance has no shell. This is the only way an operator can ask "what
/// is loaded here, and what may it do" — and the only way a test can ask it of
/// a RUNNING box rather than of a build.
///
/// A cargo feature's absence is provable in the symbol table. An uninstalled
/// module's absence is only "a file that is not there", which is weaker. These
/// three fields are where that strength is recovered.
#[prost(message, repeated, tag = "5")]
pub modules: ::prost::alloc::vec::Vec<LoadedModule>,
/// The union of every capability granted to any module on this boot. A set
/// that does not contain `principal.read`, `digest.read`, `clock.read` or
/// `audit.write` proves "and none can be" from CONFIGURATION, without looking
/// at a directory at all.
#[prost(string, repeated, tag = "6")]
pub granted_capabilities: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// The host functions actually defined on this boot's wasm linkers. A module
/// importing anything outside this set fails INSTANTIATION, because the import
/// is not defined — it is not merely refused at the call.
#[prost(string, repeated, tag = "7")]
pub linker_defines: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
}
/// One guest this boot loaded.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct LoadedModule {
/// The name the module's own manifest declares.
#[prost(string, tag = "1")]
pub name: ::prost::alloc::string::String,
/// "linked" for a guest compiled into this binary, or the module's file name
/// for one loaded from the plugin directory.
#[prost(string, tag = "2")]
pub origin: ::prost::alloc::string::String,
/// "package-handler" | "meter".
#[prost(string, tag = "3")]
pub kind: ::prost::alloc::string::String,
/// Hex blake3-256 of the module bytes, over exactly what the detached CMS
/// signature covers. EMPTY for a linked guest, which has no module bytes —
/// and empty is distinguishable from a digest, which is the point.
#[prost(string, tag = "4")]
pub digest: ::prost::alloc::string::String,
/// The verified signer this module arrived under, when a trust policy was in
/// force. Empty means no provenance was REQUIRED — never "it failed and we
/// carried on", which is a boot error.
#[prost(string, tag = "5")]
pub receipt: ::prost::alloc::string::String,
/// What the operator granted THIS module, by name.
#[prost(string, repeated, tag = "6")]
pub granted: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct MeterReading {
/// The meter's name, as monetize's holger plugin declares it: `artifacts`,
/// `archive_bytes`, `bytes_served`, `requests`, `proxy_upstream_hits`, `repos`.
#[prost(string, tag = "1")]
pub name: ::prost::alloc::string::String,
/// ⚠ MEANINGLESS unless `counted` is true. See below.
#[prost(uint64, tag = "2")]
pub value: u64,
#[prost(enumeration = "MeterScope", tag = "3")]
pub scope: i32,
/// Where the number came from: the backend name, `metrics`, or whatever
/// produced it. A reader that has to ask "who said this" has a number it
/// cannot check.
#[prost(string, tag = "4")]
pub source: ::prost::alloc::string::String,
/// **THE FALSE-ZERO GUARD.** `false` means this backend cannot answer this
/// meter at all, and `value` is not a measurement — not a zero, not a
/// default, not "empty".
///
/// Four of holger's backends (`znippy-go`, `znippy-composer`, `znippy-docker`,
/// `znippy-nuget`) never override `RepositoryBackendTrait::list` and answer the
/// trait default, an empty listing. `list(...).unwrap_or(0)` stamped with a
/// REPOSITORY scope reported a full repository as empty, and collapsed a
/// genuine backend ERROR into the same 0 — so "the disk broke" and "nothing
/// here" were one answer on the wire. A bill drawn from that is wrong in the
/// customer's favour on a healthy box and wrong in ours on a broken one.
///
/// A fold that treats `counted == false` as a zero is the bug this field
/// exists to make impossible. monetize's own fold already counts an absent
/// reading as a HOLE (`FleetTotal::tenants_without_reading`), which is the
/// behaviour this field lets it keep.
#[prost(bool, tag = "5")]
pub counted: bool,
/// Why not, by name, when `counted` is false. Empty when it is true.
#[prost(string, tag = "6")]
pub refusal_reason: ::prost::alloc::string::String,
}
/// A ceiling an order attached to one meter, echoed back so a tenant can see its
/// own. `limit` of 0 means NO CEILING -- it has never meant "may hold nothing".
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct MeterCap {
#[prost(string, tag = "1")]
pub meter: ::prost::alloc::string::String,
#[prost(uint64, tag = "2")]
pub limit: u64,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ReadUsageRequest {
#[prost(string, tag = "1")]
pub repository: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ReadUsageResponse {
#[prost(message, repeated, tag = "1")]
pub meters: ::prost::alloc::vec::Vec<MeterReading>,
/// When the reading was taken, Unix milliseconds — `monetize_product::Usage`
/// carries the same field and will not invent one.
#[prost(int64, tag = "2")]
pub measured_at_unix_ms: i64,
/// The ceilings in force for this repository, so a tenant can see its own.
/// Empty in a build with no paid state, and empty is not "zero everywhere".
#[prost(message, repeated, tag = "3")]
pub caps: ::prost::alloc::vec::Vec<MeterCap>,
}
/// One row of the queue, as a reader sees it.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct JobRow {
#[prost(string, tag = "1")]
pub job_id: ::prost::alloc::string::String,
/// `holger_promote` | `holger_replicate` | `holger_upload` | `holger_gate`.
#[prost(string, tag = "2")]
pub kind: ::prost::alloc::string::String,
/// What it acts on, human-readable (`dev->prod:name:version`).
#[prost(string, tag = "3")]
pub target: ::prost::alloc::string::String,
/// `queued` | `running` | `done` | `failed` | `interrupted`.
///
/// `interrupted` is holger's own and is the point of the whole lane: a job that
/// was running when the process died is named, with a reason, instead of being
/// left `running` for ever (stinky 01 §6.2) or laundered into `failed`, which
/// would claim it was tried and refused.
#[prost(string, tag = "4")]
pub status: ::prost::alloc::string::String,
/// The idempotency key -- two jobs with the same content id are the same work.
#[prost(string, tag = "5")]
pub content_id: ::prost::alloc::string::String,
/// Terminal result pointer: a seal's content address, a replication's counts.
#[prost(string, tag = "6")]
pub result_ref: ::prost::alloc::string::String,
/// Why it failed or was interrupted. Empty otherwise -- never a placeholder.
#[prost(string, tag = "7")]
pub reason: ::prost::alloc::string::String,
/// The authenticated principal that asked.
#[prost(string, tag = "8")]
pub requested_by: ::prost::alloc::string::String,
#[prost(int64, tag = "9")]
pub ts_start_micros: i64,
#[prost(int64, tag = "10")]
pub ts_end_micros: i64,
#[prost(int64, tag = "11")]
pub elapsed_ms: i64,
/// What it is doing in the admin view's words: a pull-through (`holger_fetch`)
/// or a mirror asset (`holger_mirror_asset`) reads `requested` -> `fetching` ->
/// `done` | `failed`; every other kind reads its status word. A `failed` stage
/// with `next_attempt_micros` set is a retry waiting (status `retry_wait`).
#[prost(string, tag = "12")]
pub stage: ::prost::alloc::string::String,
/// Attempts made so far, and the ceiling (1 for the four original kinds).
#[prost(uint32, tag = "13")]
pub attempts: u32,
#[prost(uint32, tag = "14")]
pub max_attempts: u32,
/// When a `retry_wait` job runs again (µs since the epoch); 0 = not waiting.
#[prost(int64, tag = "15")]
pub next_attempt_micros: i64,
/// Pending-list priority from the consumer's admission class: 0 Full,
/// 1 Reduced, 2 Floor, 3 Queued. Lower runs first.
#[prost(uint32, tag = "16")]
pub priority: u32,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct GetJobRequest {
#[prost(string, tag = "1")]
pub job_id: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct GetJobResponse {
/// False when the ledger holds no such job -- the row below is then empty, and
/// "not found" is not spelled as an all-zero job.
#[prost(bool, tag = "1")]
pub found: bool,
#[prost(message, optional, tag = "2")]
pub job: ::core::option::Option<JobRow>,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ListJobsRequest {
/// Filter by kind; empty = every kind.
#[prost(string, tag = "1")]
pub kind: ::prost::alloc::string::String,
/// Cap the rows returned; 0 = every row the ledger holds.
#[prost(int32, tag = "2")]
pub limit: i32,
/// Filter by state: empty = all; `waiting` (queued, or failed with a retry
/// scheduled), `running`, `failed` (terminal failed or interrupted, AND
/// retry_wait — every row with a reason), `done`.
#[prost(string, tag = "3")]
pub state: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ListJobsResponse {
#[prost(message, repeated, tag = "1")]
pub jobs: ::prost::alloc::vec::Vec<JobRow>,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AdminSnapshotRequest {
/// How many of the newest log lines to return; 0 = 200, capped at 2000.
#[prost(uint32, tag = "1")]
pub log_lines: u32,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AdminSnapshotReply {
/// When this was taken, by the estate clock (Unix ms), and by whom.
#[prost(int64, tag = "1")]
pub taken_unix_ms: i64,
#[prost(string, tag = "2")]
pub host: ::prost::alloc::string::String,
#[prost(string, tag = "3")]
pub version: ::prost::alloc::string::String,
#[prost(uint64, tag = "4")]
pub uptime_seconds: u64,
/// "primary" | "twin".
#[prost(string, tag = "5")]
pub role: ::prost::alloc::string::String,
#[prost(message, optional, tag = "6")]
pub disks: ::core::option::Option<AdminDisks>,
#[prost(message, optional, tag = "7")]
pub twin: ::core::option::Option<AdminTwin>,
#[prost(message, optional, tag = "8")]
pub growth: ::core::option::Option<AdminGrowth>,
#[prost(message, optional, tag = "9")]
pub clock: ::core::option::Option<AdminClock>,
#[prost(message, optional, tag = "10")]
pub plugins: ::core::option::Option<AdminPlugins>,
#[prost(message, optional, tag = "11")]
pub audit: ::core::option::Option<AdminAudit>,
#[prost(message, optional, tag = "12")]
pub logs: ::core::option::Option<AdminLogs>,
#[prost(message, optional, tag = "13")]
pub payments: ::core::option::Option<AdminPayments>,
/// The disk speed test over the data root (edda disk-snapshot `speed`), run
/// ONCE at start on its own thread. `measured` false = not run yet / skipped /
/// failed, with the reason: the console says N/A, never a zero.
#[prost(message, optional, tag = "14")]
pub disk_speed: ::core::option::Option<AdminDiskSpeed>,
/// Every repository (monetize's TENANT for holger): what it holds on disk,
/// whether those bytes are a CACHE (a repository with an upstream: pull-through
/// or proxy), and its paid `disk_bytes` cap (the metered build's entitlement).
#[prost(message, repeated, tag = "15")]
pub tenants: ::prost::alloc::vec::Vec<AdminTenant>,
/// The redb job queue's depth, by status.
#[prost(message, optional, tag = "16")]
pub queue: ::core::option::Option<AdminQueue>,
/// Every paired downstream as this upstream last heard from it: the rows of
/// holger.grow.v1 GrowService.Downstreams, field for field (the twins are
/// `twin.twins`, GrowService.Twins). The console's Sync view reads both.
#[prost(message, repeated, tag = "17")]
pub downstreams: ::prost::alloc::vec::Vec<AdminDownstreamRow>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AdminDiskSpeed {
#[prost(bool, tag = "1")]
pub measured: bool,
/// The directory measured (the data root).
#[prost(string, tag = "2")]
pub path: ::prost::alloc::string::String,
/// Sequential write + fsync, and the read back off the device, bytes/s.
#[prost(double, tag = "3")]
pub seq_write_bps: f64,
#[prost(double, tag = "4")]
pub seq_read_bps: f64,
/// direct (O_DIRECT) | dropped (the page cache dropped first)
#[prost(string, tag = "5")]
pub read_how: ::prost::alloc::string::String,
/// The read was faster than any disk (> 5 GB/s): the cache answered, so the
/// read figure is not a disk speed.
#[prost(bool, tag = "6")]
pub read_cached: bool,
/// 4 KiB overwrites, each fdatasync'd, per second.
#[prost(double, tag = "7")]
pub sync_4k_ops_per_s: f64,
#[prost(double, tag = "8")]
pub seconds: f64,
#[prost(int64, tag = "9")]
pub at_unix_ms: i64,
/// Why there is no figure (not run yet, skipped for free space, failed).
#[prost(string, tag = "10")]
pub why: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AdminTenant {
#[prost(string, tag = "1")]
pub repository: ::prost::alloc::string::String,
/// The repository has an upstream: what it holds is a cache.
#[prost(bool, tag = "2")]
pub cache: bool,
#[prost(string, repeated, tag = "3")]
pub upstreams: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// `disk_bytes` as the meter counts it; `used_measured` false with `used_why`
/// when it could not be counted (a group owns none, no storage yet …).
#[prost(bool, tag = "4")]
pub used_measured: bool,
#[prost(uint64, tag = "5")]
pub used_bytes: u64,
#[prost(string, tag = "6")]
pub used_why: ::prost::alloc::string::String,
/// The paid cap (quota): `has_cap` false with `cap_why` when none is known.
#[prost(bool, tag = "7")]
pub has_cap: bool,
#[prost(uint64, tag = "8")]
pub cap_bytes: u64,
#[prost(string, tag = "9")]
pub cap_why: ::prost::alloc::string::String,
/// The entitlement's state (active | grace | suspended …) when one exists.
#[prost(string, tag = "10")]
pub state: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AdminQueue {
/// False when this server carries no job queue (built or configured without it).
#[prost(bool, tag = "1")]
pub present: bool,
#[prost(string, tag = "2")]
pub why: ::prost::alloc::string::String,
/// Jobs not in a terminal state (queued, running, waiting to retry).
#[prost(uint64, tag = "3")]
pub open: u64,
/// status word → count, over the newest `scanned` jobs.
#[prost(map = "string, uint64", tag = "4")]
pub by_status: ::std::collections::HashMap<::prost::alloc::string::String, u64>,
#[prost(uint64, tag = "5")]
pub scanned: u64,
#[prost(uint32, tag = "6")]
pub workers: u32,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AdminDisks {
/// Every storage mount (pseudo filesystems left out), with holger's labels
/// on the mount each labelled path sits on: `system` (/), `data` (the data
/// root), `storage:<repo>` (a repository's archive or files).
#[prost(message, repeated, tag = "1")]
pub mounts: ::prost::alloc::vec::Vec<AdminDisk>,
#[prost(message, repeated, tag = "2")]
pub block_devices: ::prost::alloc::vec::Vec<AdminBlockDevice>,
/// A labelled path that sits on no mount, with the reason.
#[prost(message, repeated, tag = "3")]
pub unresolved: ::prost::alloc::vec::Vec<AdminUnresolved>,
/// Why the mount table or /sys/block could not be read.
#[prost(string, repeated, tag = "4")]
pub problems: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// The rule the floor figures were computed with, in words — and whether
/// holger enforces it (it does not, today: the floor is advisory).
#[prost(string, tag = "5")]
pub floor_rule: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AdminDisk {
#[prost(string, tag = "1")]
pub source: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub mount_point: ::prost::alloc::string::String,
#[prost(string, tag = "3")]
pub fstype: ::prost::alloc::string::String,
#[prost(bool, tag = "4")]
pub read_only: bool,
#[prost(string, repeated, tag = "5")]
pub labels: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
#[prost(string, repeated, tag = "6")]
pub paths: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// statvfs(3), in bytes. All 0 with `error` set when it could not be taken.
#[prost(uint64, tag = "7")]
pub total_bytes: u64,
#[prost(uint64, tag = "8")]
pub free_bytes: u64,
#[prost(uint64, tag = "9")]
pub available_bytes: u64,
#[prost(uint64, tag = "10")]
pub used_bytes: u64,
#[prost(uint64, tag = "11")]
pub reserved_bytes: u64,
#[prost(uint64, tag = "12")]
pub inodes_total: u64,
#[prost(uint64, tag = "13")]
pub inodes_free: u64,
#[prost(uint64, tag = "14")]
pub block_size: u64,
#[prost(uint64, tag = "15")]
pub floor_bytes: u64,
/// available − floor.
#[prost(uint64, tag = "16")]
pub servable_bytes: u64,
#[prost(uint32, tag = "17")]
pub used_permille: u32,
#[prost(string, tag = "18")]
pub error: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AdminPartition {
#[prost(string, tag = "1")]
pub name: ::prost::alloc::string::String,
#[prost(uint64, tag = "2")]
pub size_bytes: u64,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AdminBlockDevice {
#[prost(string, tag = "1")]
pub name: ::prost::alloc::string::String,
#[prost(uint64, tag = "2")]
pub size_bytes: u64,
#[prost(bool, tag = "3")]
pub rotational: bool,
#[prost(bool, tag = "4")]
pub removable: bool,
#[prost(bool, tag = "5")]
pub read_only: bool,
#[prost(message, repeated, tag = "6")]
pub partitions: ::prost::alloc::vec::Vec<AdminPartition>,
/// What holds it or one of its partitions (md127, dm-0).
#[prost(string, repeated, tag = "7")]
pub holders: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// What it is built from (an array's members).
#[prost(string, repeated, tag = "8")]
pub members: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
#[prost(string, tag = "9")]
pub raid_level: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AdminUnresolved {
#[prost(string, tag = "1")]
pub label: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub path: ::prost::alloc::string::String,
#[prost(string, tag = "3")]
pub why: ::prost::alloc::string::String,
/// True for a repository's storage folder (`storage:<repo>`) that does not exist yet:
/// holger creates it at the first upload, so it is no fault, and `why` says that
/// (lane HOL-UI-FIX). False for every other path that sits on no mount.
#[prost(bool, tag = "4")]
pub made_at_first_upload: bool,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AdminTwin {
/// "primary" | "twin".
#[prost(string, tag = "1")]
pub role: ::prost::alloc::string::String,
/// The primary a twin follows.
#[prost(string, tag = "2")]
pub primary: ::prost::alloc::string::String,
#[prost(bool, tag = "3")]
pub serving: bool,
#[prost(bool, tag = "4")]
pub accepts_writes: bool,
/// A box awaiting its recharge serves nothing; the source it waits for.
#[prost(string, tag = "5")]
pub awaiting_recharge_from: ::prost::alloc::string::String,
/// A twin: is it alive and whole — how it last followed, whether its last
/// cycle that reached the primary was whole, when the last whole one ended,
/// and the lag: now − that end, seconds (−1 = never whole).
#[prost(string, tag = "6")]
pub follow: ::prost::alloc::string::String,
#[prost(bool, tag = "7")]
pub complete: bool,
#[prost(string, tag = "8")]
pub why: ::prost::alloc::string::String,
#[prost(int64, tag = "9")]
pub last_whole_unix: i64,
#[prost(int64, tag = "10")]
pub lag_seconds: i64,
/// The storage invariant's verdict warning (empty when none).
#[prost(string, tag = "11")]
pub store_warning: ::prost::alloc::string::String,
/// The replication door on this box: refusals by name and admitted peers.
#[prost(uint64, tag = "12")]
pub door_refused: u64,
#[prost(string, tag = "13")]
pub door_last_refusal: ::prost::alloc::string::String,
#[prost(map = "string, uint64", tag = "14")]
pub door_admitted: ::std::collections::HashMap<::prost::alloc::string::String, u64>,
/// The mTLS credentials this box holds (purpose "twin", "recharge").
#[prost(message, repeated, tag = "15")]
pub credentials: ::prost::alloc::vec::Vec<AdminTwinCredential>,
/// A primary: every enrolled twin, as its reports say.
#[prost(message, repeated, tag = "16")]
pub twins: ::prost::alloc::vec::Vec<AdminTwinRow>,
#[prost(string, tag = "17")]
pub twins_error: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AdminTwinCredential {
#[prost(string, tag = "1")]
pub purpose: ::prost::alloc::string::String,
#[prost(bool, tag = "2")]
pub installed: bool,
/// The leaf's CN, the pinned issuer's CN.
#[prost(string, tag = "3")]
pub principal: ::prost::alloc::string::String,
#[prost(string, tag = "4")]
pub issuer: ::prost::alloc::string::String,
#[prost(int64, tag = "5")]
pub not_after_unix: i64,
#[prost(int64, tag = "6")]
pub days_left: i64,
#[prost(string, repeated, tag = "7")]
pub doors: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// Why it could not be read (a half-installed credential is an error).
#[prost(string, tag = "8")]
pub error: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AdminTwinRow {
#[prost(string, tag = "1")]
pub principal: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub address: ::prost::alloc::string::String,
/// ok | behind | stalled | silent — stalled: still reporting, the applied
/// position unchanged with the head ahead for longer than TWIN_STALLED_AFTER_MS
#[prost(string, tag = "3")]
pub state: ::prost::alloc::string::String,
#[prost(int64, tag = "4")]
pub last_seen_unix_ms: i64,
#[prost(uint64, tag = "5")]
pub lag_entries: u64,
#[prost(uint64, tag = "6")]
pub disk_total_bytes: u64,
#[prost(uint64, tag = "7")]
pub disk_used_bytes: u64,
#[prost(uint32, tag = "8")]
pub fill_permille: u32,
/// The last synced point and today's pulls (holger.grow.v1 TwinRow 9, 10, 15, 16).
#[prost(uint64, tag = "9")]
pub applied_seq: u64,
#[prost(uint64, tag = "10")]
pub head_seq: u64,
#[prost(uint64, tag = "11")]
pub pulls_today: u64,
#[prost(int64, tag = "12")]
pub last_pull_unix: i64,
}
/// One paired downstream (holger.grow.v1 DownstreamRow, field for field).
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AdminDownstreamRow {
#[prost(string, tag = "1")]
pub name: ::prost::alloc::string::String,
/// `sha256:<64 hex>` of the paired client certificate.
#[prost(string, tag = "2")]
pub fingerprint: ::prost::alloc::string::String,
/// ok | behind | stalled | silent — the worst repository's; `silent` when never heard.
#[prost(string, tag = "3")]
pub state: ::prost::alloc::string::String,
#[prost(bool, tag = "4")]
pub stalled: bool,
/// The largest repository lag.
#[prost(uint64, tag = "5")]
pub lag_entries: u64,
#[prost(int64, tag = "6")]
pub last_seen_unix_ms: i64,
#[prost(uint64, tag = "7")]
pub seen_ago_ms: u64,
#[prost(uint32, tag = "8")]
pub every_secs: u32,
#[prost(message, repeated, tag = "9")]
pub repositories: ::prost::alloc::vec::Vec<AdminDownstreamRepo>,
/// Today's pulls (UTC day, since this process started) and the last one.
#[prost(uint64, tag = "10")]
pub requests_today: u64,
#[prost(uint64, tag = "11")]
pub bytes_today: u64,
#[prost(int64, tag = "12")]
pub last_pull_unix: i64,
}
/// One paired repository's sync point (holger.grow.v1 DownstreamRepoRow).
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AdminDownstreamRepo {
#[prost(string, tag = "1")]
pub repository: ::prost::alloc::string::String,
/// ok | behind | stalled | silent — TwinRow.state's words and rule.
#[prost(string, tag = "2")]
pub state: ::prost::alloc::string::String,
#[prost(uint64, tag = "3")]
pub lag_entries: u64,
#[prost(uint64, tag = "4")]
pub applied_seq: u64,
#[prost(uint64, tag = "5")]
pub head_seq: u64,
/// When the last complete cycle of this repository ended; 0 = never.
#[prost(int64, tag = "6")]
pub last_complete_unix_ms: i64,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AdminGrowMember {
#[prost(uint32, tag = "1")]
pub index: u32,
#[prost(string, tag = "2")]
pub device: ::prost::alloc::string::String,
#[prost(string, tag = "3")]
pub partition: ::prost::alloc::string::String,
#[prost(uint64, tag = "4")]
pub disk_bytes: u64,
#[prost(uint64, tag = "5")]
pub set_bytes: u64,
#[prost(uint64, tag = "6")]
pub offered_bytes: u64,
#[prost(bool, tag = "7")]
pub larger: bool,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AdminGrowth {
/// False when this process holds no growth plane (a bare service).
#[prost(bool, tag = "1")]
pub present: bool,
#[prost(string, tag = "2")]
pub phase: ::prost::alloc::string::String,
#[prost(string, tag = "3")]
pub why: ::prost::alloc::string::String,
#[prost(uint64, tag = "4")]
pub epoch: u64,
#[prost(bool, tag = "5")]
pub serving: bool,
#[prost(bool, tag = "6")]
pub engine_present: bool,
#[prost(bool, tag = "7")]
pub hotplug: bool,
#[prost(uint64, tag = "8")]
pub in_flight: u64,
#[prost(int64, tag = "9")]
pub since_unix_ms: i64,
#[prost(string, tag = "10")]
pub detail: ::prost::alloc::string::String,
#[prost(string, tag = "11")]
pub set_uuid: ::prost::alloc::string::String,
#[prost(uint64, tag = "12")]
pub total_bytes: u64,
#[prost(message, repeated, tag = "13")]
pub members: ::prost::alloc::vec::Vec<AdminGrowMember>,
#[prost(string, tag = "14")]
pub members_verdict: ::prost::alloc::string::String,
/// THE HISTORY: the boot stack's grow journal — its phase, the steps it
/// took in order, the members a partial growth left behind, where it lives.
#[prost(string, tag = "15")]
pub journal_phase: ::prost::alloc::string::String,
#[prost(string, repeated, tag = "16")]
pub journal_steps: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
#[prost(uint32, repeated, tag = "17")]
pub journal_partial_members: ::prost::alloc::vec::Vec<u32>,
#[prost(string, tag = "18")]
pub journal_detail: ::prost::alloc::string::String,
#[prost(string, tag = "19")]
pub journal_path: ::prost::alloc::string::String,
/// The capacity ladder's verdict over this machine.
#[prost(enumeration = "SetGrowth", tag = "20")]
pub capacity_growth: i32,
#[prost(string, tag = "21")]
pub capacity_growth_reason: ::prost::alloc::string::String,
#[prost(string, tag = "22")]
pub data_set: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AdminClockSource {
#[prost(string, tag = "1")]
pub source: ::prost::alloc::string::String,
#[prost(bool, tag = "2")]
pub answered: bool,
#[prost(int64, tag = "3")]
pub offset_ms: i64,
#[prost(string, tag = "4")]
pub error: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AdminClockSync {
/// timer | boot | fed | …
#[prost(string, tag = "1")]
pub trigger: ::prost::alloc::string::String,
#[prost(int64, tag = "2")]
pub at_unix_ms: i64,
/// stepped | slewed | already-right | apply-failed | no-quorum | …
#[prost(string, tag = "3")]
pub outcome: ::prost::alloc::string::String,
#[prost(bool, tag = "4")]
pub vouches: bool,
#[prost(int64, tag = "5")]
pub offset_ms: i64,
#[prost(string, tag = "6")]
pub detail: ::prost::alloc::string::String,
#[prost(message, repeated, tag = "7")]
pub sources: ::prost::alloc::vec::Vec<AdminClockSource>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AdminClock {
/// Whether a verified answer from the front stands behind holger's clock.
#[prost(bool, tag = "1")]
pub trusted: bool,
/// The correction held in-process (the machine's clock was not moved), ms.
#[prost(int64, tag = "2")]
pub owed_ms: i64,
/// The configuration in force, in words (or why it is refused).
#[prost(string, tag = "3")]
pub config: ::prost::alloc::string::String,
#[prost(int64, tag = "4")]
pub estate_unix_ms: i64,
#[prost(int64, tag = "5")]
pub system_unix_ms: i64,
/// Absent (not synced yet) when `has_last` is false.
#[prost(bool, tag = "6")]
pub has_last: bool,
#[prost(message, optional, tag = "7")]
pub last: ::core::option::Option<AdminClockSync>,
#[prost(bool, tag = "8")]
pub has_boot: bool,
#[prost(message, optional, tag = "9")]
pub boot: ::core::option::Option<AdminClockSync>,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AdminSelfRegistration {
/// False when this build or box does not register a plugin at all.
#[prost(bool, tag = "1")]
pub active: bool,
/// The last line the registration said, and whether it was taken.
#[prost(string, tag = "2")]
pub line: ::prost::alloc::string::String,
#[prost(bool, tag = "3")]
pub registered: bool,
#[prost(bool, tag = "4")]
pub warning: bool,
#[prost(int64, tag = "5")]
pub at_unix_ms: i64,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AdminEntitlement {
#[prost(string, tag = "1")]
pub repository: ::prost::alloc::string::String,
/// The fact's caps, `name=value`, as signed.
#[prost(string, repeated, tag = "2")]
pub caps: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// active | grace | suspended | … (monetize's State), when paid until (Unix
/// ms; 0 = open-ended), and where the fact came from (operator | payment:…).
#[prost(string, tag = "3")]
pub state: ::prost::alloc::string::String,
#[prost(uint64, tag = "4")]
pub paid_until_unix_ms: u64,
#[prost(string, tag = "5")]
pub source: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AdminPlugins {
/// What this boot loaded (ServerProfile's census, verbatim).
#[prost(message, repeated, tag = "1")]
pub modules: ::prost::alloc::vec::Vec<LoadedModule>,
#[prost(string, repeated, tag = "2")]
pub granted_capabilities: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
#[prost(uint32, tag = "3")]
pub meters: u32,
/// True when this is the metered build (it carries monetize's seam).
#[prost(bool, tag = "4")]
pub metered_build: bool,
/// The metered build's entitlement store: configured with monetize's key?
#[prost(bool, tag = "5")]
pub entitlements_configured: bool,
#[prost(message, repeated, tag = "6")]
pub entitlements: ::prost::alloc::vec::Vec<AdminEntitlement>,
#[prost(message, optional, tag = "7")]
pub self_registration: ::core::option::Option<AdminSelfRegistration>,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AdminAudit {
/// everything | aggregated | off
#[prost(string, tag = "1")]
pub mode: ::prost::alloc::string::String,
/// "directory <path>" | "memory" | "none".
#[prost(string, tag = "2")]
pub source: ::prost::alloc::string::String,
#[prost(uint64, tag = "3")]
pub segments: u64,
#[prost(uint64, tag = "4")]
pub total_rows: u64,
#[prost(uint64, tag = "5")]
pub total_bytes: u64,
#[prost(int64, tag = "6")]
pub first_ts_nanos: i64,
#[prost(int64, tag = "7")]
pub last_ts_nanos: i64,
#[prost(string, tag = "8")]
pub error: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AdminLogs {
/// False when this process carries no installer log (not an installer-built box).
#[prost(bool, tag = "1")]
pub present: bool,
/// The installer's log door: "install" (the installer is still at work) or
/// "log-door" (closed: the same listener serves only GET /install/log to the
/// installer's certificate).
#[prost(string, tag = "2")]
pub door: ::prost::alloc::string::String,
#[prost(bool, tag = "3")]
pub closed: bool,
#[prost(uint64, tag = "4")]
pub lines_total: u64,
#[prost(uint64, tag = "5")]
pub lines_dropped: u64,
/// The newest lines, oldest first.
#[prost(string, repeated, tag = "6")]
pub tail: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AdminPayments {
/// The Stripe webhook's last ACCEPTED delivery is kept by monetize on the
/// front, not by holger; 0 with `note` saying where it is not measured.
#[prost(int64, tag = "1")]
pub stripe_last_delivery_unix_ms: i64,
#[prost(string, tag = "2")]
pub note: ::prost::alloc::string::String,
}
/// The six units a box runs out of (`edda_admit::Cost`). Bytes except cpu_ms.
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
pub struct CostRow {
#[prost(uint64, tag = "1")]
pub cpu_ms: u64,
#[prost(uint64, tag = "2")]
pub disk_read: u64,
#[prost(uint64, tag = "3")]
pub disk_write: u64,
#[prost(uint64, tag = "4")]
pub net_in: u64,
#[prost(uint64, tag = "5")]
pub net_out: u64,
#[prost(uint64, tag = "6")]
pub upstream_fetch: u64,
}
/// One work kind's numbers for one consumer.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct WorkUsageRow {
/// `download` | `upload` | `pull_through` | `mirror_asset`.
#[prost(string, tag = "1")]
pub work: ::prost::alloc::string::String,
#[prost(uint64, tag = "2")]
pub requests: u64,
#[prost(uint64, tag = "3")]
pub refused: u64,
#[prost(message, optional, tag = "4")]
pub estimated: ::core::option::Option<CostRow>,
#[prost(message, optional, tag = "5")]
pub actual: ::core::option::Option<CostRow>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct UsageRow {
/// `principal:<sub>` | `peer:<name>` | `anon:<day>:<8 hex>`.
#[prost(string, tag = "1")]
pub consumer: ::prost::alloc::string::String,
/// Actual cost over the policy's window, and today (UTC).
#[prost(message, optional, tag = "2")]
pub window: ::core::option::Option<CostRow>,
#[prost(message, optional, tag = "3")]
pub today: ::core::option::Option<CostRow>,
#[prost(message, repeated, tag = "4")]
pub by_work: ::prost::alloc::vec::Vec<WorkUsageRow>,
/// The class the last plan gave it (`full` | `reduced` | `floor` | `queued`,
/// empty before any plan), and the plan's sentence.
#[prost(string, tag = "5")]
pub class: ::prost::alloc::string::String,
#[prost(string, tag = "6")]
pub why: ::prost::alloc::string::String,
#[prost(uint32, tag = "7")]
pub in_flight: u32,
}
/// The policy's learnt estimate for one work kind (`Admit::estimates`).
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct EstimateRow {
#[prost(string, tag = "1")]
pub kind: ::prost::alloc::string::String,
#[prost(uint64, tag = "2")]
pub samples: u64,
#[prost(uint64, tag = "3")]
pub hinted: u64,
#[prost(message, optional, tag = "4")]
pub mean: ::core::option::Option<CostRow>,
/// Cost of one GB of hinted size; absent before any hinted sample.
#[prost(message, optional, tag = "5")]
pub per_gb: ::core::option::Option<CostRow>,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct AdmitPlanRequest {
/// `principal:<sub>` | `peer:<name>` | `anonymous` (a probe token for today).
#[prost(string, tag = "1")]
pub consumer: ::prost::alloc::string::String,
/// `download` (default) | `upload` | `pull_through` | `mirror_asset`.
#[prost(string, tag = "2")]
pub work: ::prost::alloc::string::String,
/// Size hint in bytes; 0 = none.
#[prost(uint64, tag = "3")]
pub size_hint: u64,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct AdmitPlanResponse {
#[prost(string, tag = "1")]
pub consumer: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub work: ::prost::alloc::string::String,
#[prost(string, tag = "3")]
pub class: ::prost::alloc::string::String,
#[prost(message, optional, tag = "4")]
pub estimate: ::core::option::Option<CostRow>,
#[prost(string, tag = "5")]
pub why: ::prost::alloc::string::String,
/// Bytes left in the window; absent = unlimited.
#[prost(uint64, optional, tag = "6")]
pub budget_left: ::core::option::Option<u64>,
/// Concurrent requests this class gets at the door; absent = no share
/// enforced (no `admission:` block).
#[prost(uint32, optional, tag = "7")]
pub share: ::core::option::Option<u32>,
#[prost(string, tag = "8")]
pub policy: ::prost::alloc::string::String,
#[prost(message, repeated, tag = "9")]
pub estimates: ::prost::alloc::vec::Vec<EstimateRow>,
/// The consumer's usage row (absent when the book has none).
#[prost(message, optional, tag = "10")]
pub usage: ::core::option::Option<UsageRow>,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ListUsageRequest {
/// Cap the rows; 0 = all.
#[prost(int32, tag = "1")]
pub limit: i32,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ListUsageResponse {
#[prost(string, tag = "1")]
pub policy: ::prost::alloc::string::String,
#[prost(message, repeated, tag = "2")]
pub consumers: ::prost::alloc::vec::Vec<UsageRow>,
/// Requests in flight through the door right now, all consumers.
#[prost(uint32, tag = "3")]
pub in_flight_total: u32,
/// The door's ceiling and the per-class shares; absent = none enforced.
#[prost(uint32, optional, tag = "4")]
pub max_in_flight: ::core::option::Option<u32>,
#[prost(uint32, optional, tag = "5")]
pub share_full: ::core::option::Option<u32>,
#[prost(uint32, optional, tag = "6")]
pub share_reduced: ::core::option::Option<u32>,
#[prost(uint32, optional, tag = "7")]
pub share_floor: ::core::option::Option<u32>,
/// Whether proxy pull-through runs on the job queue.
#[prost(bool, tag = "8")]
pub pull_through_queue: bool,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
pub struct SecuritySummaryRequest {}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SecuritySummaryReply {
/// One line over the page, in the server's words.
#[prost(string, tag = "1")]
pub headline: ::prost::alloc::string::String,
/// The sections, in the order the page shows them (keys: chain, sources, scanners,
/// approvals, held, access, sync, events).
#[prost(message, repeated, tag = "2")]
pub sections: ::prost::alloc::vec::Vec<SecuritySection>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SecuritySection {
/// A stable key (`chain`, `scanners`, …); the console keys its markup on it, never its words.
#[prost(string, tag = "1")]
pub key: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub title: ::prost::alloc::string::String,
/// One or two sentences under the title.
#[prost(string, tag = "3")]
pub summary: ::prost::alloc::string::String,
/// What to say when there are no rows.
#[prost(string, tag = "4")]
pub empty: ::prost::alloc::string::String,
#[prost(message, repeated, tag = "5")]
pub rows: ::prost::alloc::vec::Vec<SecurityRow>,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct SecurityRow {
/// What the row is about: a step, a source, a scanner, an artifact, a repository, an event.
#[prost(string, tag = "1")]
pub name: ::prost::alloc::string::String,
/// One short word for its state (`required`, `quarantined`, `public`, …).
#[prost(string, tag = "2")]
pub state: ::prost::alloc::string::String,
/// `good` | `warn` | `bad` | `info`: how the state reads.
#[prost(string, tag = "3")]
pub tone: ::prost::alloc::string::String,
/// The rest, in plain words: why, what it checks, who, when.
#[prost(string, tag = "4")]
pub detail: ::prost::alloc::string::String,
/// The artifact the row is about, when it is one (the console links its security view).
#[prost(message, optional, tag = "5")]
pub artifact: ::core::option::Option<ArtifactId>,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
pub struct TopologyRequest {}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct TopologyReply {
/// This box first, then the others in a stable order: front, primary, twins,
/// downstreams, each by name.
#[prost(message, repeated, tag = "1")]
pub boxes: ::prost::alloc::vec::Vec<TopologyBox>,
/// This server's own clock when it answered (Unix ms).
#[prost(int64, tag = "2")]
pub server_unix_ms: i64,
/// The silence bound every `state` below was judged against, in ms.
#[prost(uint64, tag = "3")]
pub silent_after_ms: u64,
/// The estate's name from the pairing feed; empty on a holger nobody paired.
#[prost(string, tag = "4")]
pub estate: ::prost::alloc::string::String,
/// The links between the boxes: front → primary, primary → twin, primary →
/// each downstream. Each carries the state of the box it leads INTO.
#[prost(message, repeated, tag = "5")]
pub links: ::prost::alloc::vec::Vec<TopologyLink>,
/// RETIRED (Holger v2.0 H2): always empty. The server draws nothing; holger-ui
/// draws the board from `boxes` and `links`. Kept so the tag is never reused.
#[prost(string, tag = "6")]
pub svg: ::prost::alloc::string::String,
/// **Every consumer this box serves** (lane A13): named and anonymous, as the
/// door admission's book counts them. Unset = this build keeps no book.
#[prost(message, optional, tag = "7")]
pub consumers: ::core::option::Option<TopologyConsumers>,
/// **The board in one line, holger's words** (lane A13): the line drawn under
/// the title — how many upstreams and downstreams, and every consumer — for a
/// console's text alternative, rendered as it came.
#[prost(string, tag = "8")]
pub summary: ::prost::alloc::string::String,
}
/// **Who consumes this box** (lane A13, 2026-10-23), from the door admission's
/// usage book: every request asks it once, whatever the policy.
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
pub struct TopologyConsumers {
/// False when this build keeps no book: then the numbers below are not counts.
#[prost(bool, tag = "1")]
pub counted: bool,
/// Authenticated principals with a request in the window (durable: the book's
/// ledger rows survive a restart).
#[prost(uint64, tag = "2")]
pub principals: u64,
/// Paired downstream holgers with a request in the window.
#[prost(uint64, tag = "3")]
pub peers: u64,
/// Anonymous clients TODAY (UTC day): each is a per-day keyed hash that dies
/// at midnight, so there is no window for them, by design. Since this process
/// started when it started today.
#[prost(uint64, tag = "4")]
pub anonymous_today: u64,
/// The window the named counts cover, in days.
#[prost(uint32, tag = "5")]
pub window_days: u32,
}
/// **One box.** Every field is evidence this holger holds, never a guess: a box it
/// has no channel to read stays `unknown`, which is a different fact from `silent`.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct TopologyBox {
/// A short name: the pairing name (`front`, `main`, `twin`), a twin's principal,
/// a downstream's pairing name, or this box's own pairing name.
#[prost(string, tag = "1")]
pub name: ::prost::alloc::string::String,
/// `front` | `primary` | `twin` | `downstream` | `upstream` (lane A13: a
/// registry this box proxies, or a holger it mirrors).
#[prost(string, tag = "2")]
pub role: ::prost::alloc::string::String,
/// Where the evidence says it is (`host` or `host:port`); empty when unknown.
#[prost(string, tag = "3")]
pub address: ::prost::alloc::string::String,
/// `up` (it answered, or reported, within the bound) · `behind` (a twin or a
/// downstream that reports and does not catch up) · `silent` (expected, and not
/// heard within the bound, or never — and a box HELD for its recharge, which
/// serves nothing) · `unknown` (nothing here can ask it).
#[prost(string, tag = "4")]
pub state: ::prost::alloc::string::String,
/// One sentence for a human: how holger knows, and since when.
#[prost(string, tag = "5")]
pub why: ::prost::alloc::string::String,
/// True for the box that answered this call.
#[prost(bool, tag = "6")]
pub this_box: bool,
/// Wall clock of the newest evidence (Unix ms); 0 = none.
#[prost(int64, tag = "7")]
pub last_seen_unix_ms: i64,
/// `server_unix_ms - last_seen_unix_ms` at answer time; 0 when never seen.
#[prost(uint64, tag = "8")]
pub seen_ago_ms: u64,
/// The box's data volume, as measured (this box: statvfs of its data root; a
/// twin: its own, carried on its report). False = not measured, and then the
/// two numbers are 0 and must not be read.
#[prost(bool, tag = "9")]
pub disk_measured: bool,
#[prost(uint64, tag = "10")]
pub disk_total_bytes: u64,
#[prost(uint64, tag = "11")]
pub disk_used_bytes: u64,
/// Where the evidence came from: `self`, `pairing`, `report` (a twin's
/// TwinReport, or on a twin its own follow of the primary), `downstream`.
#[prost(string, repeated, tag = "12")]
pub sources: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// The WireGuard overlay address (wg0) and the utility address, from the pairing
/// feed; empty when not fed.
#[prost(string, tag = "13")]
pub overlay_address: ::prost::alloc::string::String,
#[prost(string, tag = "14")]
pub utility_address: ::prost::alloc::string::String,
/// **The state in a few words, holger's**: `answering`, `following`, `behind 120 entries`, `silent for 4 min`, `never heard`, `not asked`, `held for its recharge from twin`, `fenced`. Coarse on purpose (whole minutes once past
/// one), so the answer only changes when the state does.
#[prost(string, tag = "15")]
pub headline: ::prost::alloc::string::String,
/// A twin or a downstream: the twin's own word (TwinRow.state: ok · behind ·
/// stalled · silent, M2's `twin_state`) and its lag in log entries (M2's
/// `lag_entries`); empty / 0 for any other box.
#[prost(string, tag = "16")]
pub twin_state: ::prost::alloc::string::String,
#[prost(uint64, tag = "17")]
pub lag_entries: u64,
/// True when the box is HELD: a main awaiting its recharge from its twin (M3's
/// boot hold), or a fenced primary. Drawn dark, with the word `held`.
#[prost(bool, tag = "18")]
pub held: bool,
/// When this box's mutual-TLS credential to its peer expires (Unix s; the
/// twin's `twin` credential on a twin); 0 = none held or not readable here.
#[prost(int64, tag = "19")]
pub cert_not_after_unix: i64,
/// When the pairing itself expires (the estate's key, lane E2); 0 = not known.
///
/// **Packages fetched** (lane A13): a downstream — artifacts delivered to it,
#[prost(int64, tag = "20")]
pub pairing_not_after_unix: i64,
/// ever (durable) and today; an upstream — artifacts this box took from it
/// since this boot (`fetched_today` unused). 0 for any other box.
#[prost(uint64, tag = "21")]
pub fetched_total: u64,
#[prost(uint64, tag = "22")]
pub fetched_today: u64,
/// An upstream only: `proxy` (a repository another one names in
/// `ron_upstreams`: crates.io, PyPI, npm, a remote harbour) or `mirror` (a
/// `mirror.ron_sources` entry: another holger). Empty for any other box.
#[prost(string, tag = "23")]
pub upstream_kind: ::prost::alloc::string::String,
/// An upstream only: the local repositories it feeds.
#[prost(string, repeated, tag = "24")]
pub feeds: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// A downstream only: how it reaches this holger, `front` (the front's public
/// door) or `wireguard` (the front's downstream interface; lane HOL-WGDS).
#[prost(string, tag = "25")]
pub via: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct TopologyLink {
/// Box names, as in TopologyBox.name.
#[prost(string, tag = "1")]
pub from: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub to: ::prost::alloc::string::String,
/// `serves` (front → primary) · `follows` (primary → twin) · `pulls` (primary →
/// downstream) · `feeds` (upstream → this box, lane A13).
#[prost(string, tag = "3")]
pub kind: ::prost::alloc::string::String,
/// The state of the box the link leads into (TopologyBox.state).
#[prost(string, tag = "4")]
pub state: ::prost::alloc::string::String,
}
/// One piece of a streamed bundle. `first_import` is read from every chunk: any
/// chunk that sets it establishes an absent anti-rollback floor with this bundle.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ImportBundleChunk {
#[prost(bytes = "vec", tag = "1")]
pub data: ::prost::alloc::vec::Vec<u8>,
#[prost(bool, tag = "2")]
pub first_import: bool,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ImportIntelBundleReply {
/// `new` or `idempotent-reimport`.
#[prost(string, tag = "1")]
pub outcome: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub bundle_id: ::prost::alloc::string::String,
#[prost(uint64, tag = "3")]
pub sequence: u64,
/// YYYY-MM-DD of the advisory snapshot.
#[prost(string, tag = "4")]
pub snapshot_at: ::prost::alloc::string::String,
#[prost(uint64, tag = "5")]
pub advisories: u64,
#[prost(string, tag = "6")]
pub message: ::prost::alloc::string::String,
}
/// One artifact a bundle import landed.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ImportedArtifactRow {
#[prost(string, tag = "1")]
pub artifact: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub sha256: ::prost::alloc::string::String,
/// AVAILABLE.
#[prost(string, tag = "3")]
pub state: ::prost::alloc::string::String,
#[prost(string, tag = "4")]
pub repository: ::prost::alloc::string::String,
/// `landed` or `already-available`.
#[prost(string, tag = "5")]
pub outcome: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ImportBundleReply {
/// `new` or `idempotent-reimport`.
#[prost(string, tag = "1")]
pub outcome: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub bundle_id: ::prost::alloc::string::String,
#[prost(uint64, tag = "3")]
pub sequence: u64,
/// `airgap-export` or `update-bundle`.
#[prost(string, tag = "4")]
pub kind: ::prost::alloc::string::String,
#[prost(message, repeated, tag = "5")]
pub artifacts: ::prost::alloc::vec::Vec<ImportedArtifactRow>,
#[prost(string, tag = "6")]
pub message: ::prost::alloc::string::String,
}
/// gunnar's SetGrowth, the same numbers — monetize's `Growth` reads both.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum SetGrowth {
Unspecified = 0,
GrowthUnknown = 1,
GrowthSealed = 2,
GrowthOperatorOnly = 3,
GrowthAtRestart = 4,
GrowthAtRuntime = 5,
}
impl SetGrowth {
/// String value of the enum field names used in the ProtoBuf definition.
///
/// The values are not transformed in any way and thus are considered stable
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
pub fn as_str_name(&self) -> &'static str {
match self {
Self::Unspecified => "SET_GROWTH_UNSPECIFIED",
Self::GrowthUnknown => "GROWTH_UNKNOWN",
Self::GrowthSealed => "GROWTH_SEALED",
Self::GrowthOperatorOnly => "GROWTH_OPERATOR_ONLY",
Self::GrowthAtRestart => "GROWTH_AT_RESTART",
Self::GrowthAtRuntime => "GROWTH_AT_RUNTIME",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
match value {
"SET_GROWTH_UNSPECIFIED" => Some(Self::Unspecified),
"GROWTH_UNKNOWN" => Some(Self::GrowthUnknown),
"GROWTH_SEALED" => Some(Self::GrowthSealed),
"GROWTH_OPERATOR_ONLY" => Some(Self::GrowthOperatorOnly),
"GROWTH_AT_RESTART" => Some(Self::GrowthAtRestart),
"GROWTH_AT_RUNTIME" => Some(Self::GrowthAtRuntime),
_ => None,
}
}
}
/// What AdvanceArtifact does. ADVANCE moves to the next state on the chain (or
/// to `to_state` when set, which must be the next state).
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum IntakeVerb {
Advance = 0,
Quarantine = 1,
Release = 2,
Block = 3,
}
impl IntakeVerb {
/// String value of the enum field names used in the ProtoBuf definition.
///
/// The values are not transformed in any way and thus are considered stable
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
pub fn as_str_name(&self) -> &'static str {
match self {
Self::Advance => "INTAKE_VERB_ADVANCE",
Self::Quarantine => "INTAKE_VERB_QUARANTINE",
Self::Release => "INTAKE_VERB_RELEASE",
Self::Block => "INTAKE_VERB_BLOCK",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
match value {
"INTAKE_VERB_ADVANCE" => Some(Self::Advance),
"INTAKE_VERB_QUARANTINE" => Some(Self::Quarantine),
"INTAKE_VERB_RELEASE" => Some(Self::Release),
"INTAKE_VERB_BLOCK" => Some(Self::Block),
_ => None,
}
}
}
/// What a single reading is a measurement OF.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum MeterScope {
Unspecified = 0,
/// Measured for THIS repository alone.
Repository = 1,
/// Measured for the whole server. The same value comes back for every
/// repository, and it is not divisible between them.
Server = 2,
}
impl MeterScope {
/// String value of the enum field names used in the ProtoBuf definition.
///
/// The values are not transformed in any way and thus are considered stable
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
pub fn as_str_name(&self) -> &'static str {
match self {
Self::Unspecified => "METER_SCOPE_UNSPECIFIED",
Self::Repository => "METER_SCOPE_REPOSITORY",
Self::Server => "METER_SCOPE_SERVER",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
match value {
"METER_SCOPE_UNSPECIFIED" => Some(Self::Unspecified),
"METER_SCOPE_REPOSITORY" => Some(Self::Repository),
"METER_SCOPE_SERVER" => Some(Self::Server),
_ => None,
}
}
}
/// Generated client implementations.
pub mod repository_service_client {
#![allow(
unused_variables,
dead_code,
missing_docs,
clippy::wildcard_imports,
clippy::let_unit_value,
)]
use tonic::codegen::*;
use tonic::codegen::http::Uri;
/// Repository service — query and manage artifacts
#[derive(Debug, Clone)]
pub struct RepositoryServiceClient<T> {
inner: tonic::client::Grpc<T>,
}
impl RepositoryServiceClient<tonic::transport::Channel> {
/// Attempt to create a new client by connecting to a given endpoint.
pub async fn connect<D>(dst: D) -> Result<Self, tonic::transport::Error>
where
D: TryInto<tonic::transport::Endpoint>,
D::Error: Into<StdError>,
{
let conn = tonic::transport::Endpoint::new(dst)?.connect().await?;
Ok(Self::new(conn))
}
}
impl<T> RepositoryServiceClient<T>
where
T: tonic::client::GrpcService<tonic::body::Body>,
T::Error: Into<StdError>,
T::ResponseBody: Body<Data = Bytes> + std::marker::Send + 'static,
<T::ResponseBody as Body>::Error: Into<StdError> + std::marker::Send,
{
pub fn new(inner: T) -> Self {
let inner = tonic::client::Grpc::new(inner);
Self { inner }
}
pub fn with_origin(inner: T, origin: Uri) -> Self {
let inner = tonic::client::Grpc::with_origin(inner, origin);
Self { inner }
}
pub fn with_interceptor<F>(
inner: T,
interceptor: F,
) -> RepositoryServiceClient<InterceptedService<T, F>>
where
F: tonic::service::Interceptor,
T::ResponseBody: Default,
T: tonic::codegen::Service<
http::Request<tonic::body::Body>,
Response = http::Response<
<T as tonic::client::GrpcService<tonic::body::Body>>::ResponseBody,
>,
>,
<T as tonic::codegen::Service<
http::Request<tonic::body::Body>,
>>::Error: Into<StdError> + std::marker::Send + std::marker::Sync,
{
RepositoryServiceClient::new(InterceptedService::new(inner, interceptor))
}
/// Compress requests with the given encoding.
///
/// This requires the server to support it otherwise it might respond with an
/// error.
#[must_use]
pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self {
self.inner = self.inner.send_compressed(encoding);
self
}
/// Enable decompressing responses.
#[must_use]
pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self {
self.inner = self.inner.accept_compressed(encoding);
self
}
/// Limits the maximum size of a decoded message.
///
/// Default: `4MB`
#[must_use]
pub fn max_decoding_message_size(mut self, limit: usize) -> Self {
self.inner = self.inner.max_decoding_message_size(limit);
self
}
/// Limits the maximum size of an encoded message.
///
/// Default: `usize::MAX`
#[must_use]
pub fn max_encoding_message_size(mut self, limit: usize) -> Self {
self.inner = self.inner.max_encoding_message_size(limit);
self
}
/// Fetch a single artifact by ID
pub async fn fetch_artifact(
&mut self,
request: impl tonic::IntoRequest<super::FetchArtifactRequest>,
) -> std::result::Result<
tonic::Response<super::FetchArtifactResponse>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.RepositoryService/FetchArtifact",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("holger.v1.RepositoryService", "FetchArtifact"));
self.inner.unary(req, path, codec).await
}
/// List artifacts in a repository (with optional filter)
pub async fn list_artifacts(
&mut self,
request: impl tonic::IntoRequest<super::ListArtifactsRequest>,
) -> std::result::Result<
tonic::Response<super::ListArtifactsResponse>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.RepositoryService/ListArtifacts",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("holger.v1.RepositoryService", "ListArtifacts"));
self.inner.unary(req, path, codec).await
}
/// Upload an artifact (write-enabled repos only)
pub async fn put_artifact(
&mut self,
request: impl tonic::IntoRequest<super::PutArtifactRequest>,
) -> std::result::Result<
tonic::Response<super::PutArtifactResponse>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.RepositoryService/PutArtifact",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("holger.v1.RepositoryService", "PutArtifact"));
self.inner.unary(req, path, codec).await
}
/// Stream download for large artifacts
pub async fn stream_artifact(
&mut self,
request: impl tonic::IntoRequest<super::FetchArtifactRequest>,
) -> std::result::Result<
tonic::Response<tonic::codec::Streaming<super::ArtifactChunk>>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.RepositoryService/StreamArtifact",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(
GrpcMethod::new("holger.v1.RepositoryService", "StreamArtifact"),
);
self.inner.server_streaming(req, path, codec).await
}
/// Stream upload for large artifacts (stinky 14). The FIRST message names the
/// repository and the artifact and may carry the first bytes; every later
/// message carries bytes only. The server hands the pieces to the backend as
/// they arrive, so the body is never whole in this process unless a gate must
/// read it (the intake chain, the ingest gates) or `async_job` stages it.
pub async fn put_artifact_stream(
&mut self,
request: impl tonic::IntoStreamingRequest<Message = super::PutArtifactChunk>,
) -> std::result::Result<
tonic::Response<super::PutArtifactResponse>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.RepositoryService/PutArtifactStream",
);
let mut req = request.into_streaming_request();
req.extensions_mut()
.insert(
GrpcMethod::new("holger.v1.RepositoryService", "PutArtifactStream"),
);
self.inner.client_streaming(req, path, codec).await
}
}
}
/// Generated client implementations.
pub mod archive_service_client {
#![allow(
unused_variables,
dead_code,
missing_docs,
clippy::wildcard_imports,
clippy::let_unit_value,
)]
use tonic::codegen::*;
use tonic::codegen::http::Uri;
/// Archive service — znippy archive operations
#[derive(Debug, Clone)]
pub struct ArchiveServiceClient<T> {
inner: tonic::client::Grpc<T>,
}
impl ArchiveServiceClient<tonic::transport::Channel> {
/// Attempt to create a new client by connecting to a given endpoint.
pub async fn connect<D>(dst: D) -> Result<Self, tonic::transport::Error>
where
D: TryInto<tonic::transport::Endpoint>,
D::Error: Into<StdError>,
{
let conn = tonic::transport::Endpoint::new(dst)?.connect().await?;
Ok(Self::new(conn))
}
}
impl<T> ArchiveServiceClient<T>
where
T: tonic::client::GrpcService<tonic::body::Body>,
T::Error: Into<StdError>,
T::ResponseBody: Body<Data = Bytes> + std::marker::Send + 'static,
<T::ResponseBody as Body>::Error: Into<StdError> + std::marker::Send,
{
pub fn new(inner: T) -> Self {
let inner = tonic::client::Grpc::new(inner);
Self { inner }
}
pub fn with_origin(inner: T, origin: Uri) -> Self {
let inner = tonic::client::Grpc::with_origin(inner, origin);
Self { inner }
}
pub fn with_interceptor<F>(
inner: T,
interceptor: F,
) -> ArchiveServiceClient<InterceptedService<T, F>>
where
F: tonic::service::Interceptor,
T::ResponseBody: Default,
T: tonic::codegen::Service<
http::Request<tonic::body::Body>,
Response = http::Response<
<T as tonic::client::GrpcService<tonic::body::Body>>::ResponseBody,
>,
>,
<T as tonic::codegen::Service<
http::Request<tonic::body::Body>,
>>::Error: Into<StdError> + std::marker::Send + std::marker::Sync,
{
ArchiveServiceClient::new(InterceptedService::new(inner, interceptor))
}
/// Compress requests with the given encoding.
///
/// This requires the server to support it otherwise it might respond with an
/// error.
#[must_use]
pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self {
self.inner = self.inner.send_compressed(encoding);
self
}
/// Enable decompressing responses.
#[must_use]
pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self {
self.inner = self.inner.accept_compressed(encoding);
self
}
/// Limits the maximum size of a decoded message.
///
/// Default: `4MB`
#[must_use]
pub fn max_decoding_message_size(mut self, limit: usize) -> Self {
self.inner = self.inner.max_decoding_message_size(limit);
self
}
/// Limits the maximum size of an encoded message.
///
/// Default: `usize::MAX`
#[must_use]
pub fn max_encoding_message_size(mut self, limit: usize) -> Self {
self.inner = self.inner.max_encoding_message_size(limit);
self
}
/// List files in a znippy archive backing a repository
pub async fn list_archive_files(
&mut self,
request: impl tonic::IntoRequest<super::ListArchiveFilesRequest>,
) -> std::result::Result<
tonic::Response<super::ListArchiveFilesResponse>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.ArchiveService/ListArchiveFiles",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("holger.v1.ArchiveService", "ListArchiveFiles"));
self.inner.unary(req, path, codec).await
}
/// Get archive metadata (file count, total size, compression ratio)
pub async fn archive_info(
&mut self,
request: impl tonic::IntoRequest<super::ArchiveInfoRequest>,
) -> std::result::Result<
tonic::Response<super::ArchiveInfoResponse>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.ArchiveService/ArchiveInfo",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("holger.v1.ArchiveService", "ArchiveInfo"));
self.inner.unary(req, path, codec).await
}
}
}
/// Generated client implementations.
pub mod admin_service_client {
#![allow(
unused_variables,
dead_code,
missing_docs,
clippy::wildcard_imports,
clippy::let_unit_value,
)]
use tonic::codegen::*;
use tonic::codegen::http::Uri;
/// Health / admin
#[derive(Debug, Clone)]
pub struct AdminServiceClient<T> {
inner: tonic::client::Grpc<T>,
}
impl AdminServiceClient<tonic::transport::Channel> {
/// Attempt to create a new client by connecting to a given endpoint.
pub async fn connect<D>(dst: D) -> Result<Self, tonic::transport::Error>
where
D: TryInto<tonic::transport::Endpoint>,
D::Error: Into<StdError>,
{
let conn = tonic::transport::Endpoint::new(dst)?.connect().await?;
Ok(Self::new(conn))
}
}
impl<T> AdminServiceClient<T>
where
T: tonic::client::GrpcService<tonic::body::Body>,
T::Error: Into<StdError>,
T::ResponseBody: Body<Data = Bytes> + std::marker::Send + 'static,
<T::ResponseBody as Body>::Error: Into<StdError> + std::marker::Send,
{
pub fn new(inner: T) -> Self {
let inner = tonic::client::Grpc::new(inner);
Self { inner }
}
pub fn with_origin(inner: T, origin: Uri) -> Self {
let inner = tonic::client::Grpc::with_origin(inner, origin);
Self { inner }
}
pub fn with_interceptor<F>(
inner: T,
interceptor: F,
) -> AdminServiceClient<InterceptedService<T, F>>
where
F: tonic::service::Interceptor,
T::ResponseBody: Default,
T: tonic::codegen::Service<
http::Request<tonic::body::Body>,
Response = http::Response<
<T as tonic::client::GrpcService<tonic::body::Body>>::ResponseBody,
>,
>,
<T as tonic::codegen::Service<
http::Request<tonic::body::Body>,
>>::Error: Into<StdError> + std::marker::Send + std::marker::Sync,
{
AdminServiceClient::new(InterceptedService::new(inner, interceptor))
}
/// Compress requests with the given encoding.
///
/// This requires the server to support it otherwise it might respond with an
/// error.
#[must_use]
pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self {
self.inner = self.inner.send_compressed(encoding);
self
}
/// Enable decompressing responses.
#[must_use]
pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self {
self.inner = self.inner.accept_compressed(encoding);
self
}
/// Limits the maximum size of a decoded message.
///
/// Default: `4MB`
#[must_use]
pub fn max_decoding_message_size(mut self, limit: usize) -> Self {
self.inner = self.inner.max_decoding_message_size(limit);
self
}
/// Limits the maximum size of an encoded message.
///
/// Default: `usize::MAX`
#[must_use]
pub fn max_encoding_message_size(mut self, limit: usize) -> Self {
self.inner = self.inner.max_encoding_message_size(limit);
self
}
/// Server health check
pub async fn health(
&mut self,
request: impl tonic::IntoRequest<super::HealthRequest>,
) -> std::result::Result<tonic::Response<super::HealthResponse>, tonic::Status> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.AdminService/Health",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("holger.v1.AdminService", "Health"));
self.inner.unary(req, path, codec).await
}
/// List configured repositories
pub async fn list_repositories(
&mut self,
request: impl tonic::IntoRequest<super::ListRepositoriesRequest>,
) -> std::result::Result<
tonic::Response<super::ListRepositoriesResponse>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.AdminService/ListRepositories",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("holger.v1.AdminService", "ListRepositories"));
self.inner.unary(req, path, codec).await
}
/// Report the server's operating profile — static (sealed, read-only, "rigged
/// for silent running") vs dynamic (writable / proxy). Server-reported truth so
/// the operator UI reflects the server, not a local toggle.
pub async fn server_profile(
&mut self,
request: impl tonic::IntoRequest<super::ServerProfileRequest>,
) -> std::result::Result<
tonic::Response<super::ServerProfileResponse>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.AdminService/ServerProfile",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("holger.v1.AdminService", "ServerProfile"));
self.inner.unary(req, path, codec).await
}
/// Who does the SERVER think the caller is? Resolves the presented credential
/// (Bearer / mTLS CN) through the same validation every gated call uses and
/// reports the resulting identity + effective GLOBAL role — introspection
/// only, no secrets, and NOT an authorization decision: every operation is
/// still checked by its own gate. Anonymous callers get an answer too (the
/// default role), so a UI can explain what "not logged in" means here.
pub async fn who_am_i(
&mut self,
request: impl tonic::IntoRequest<super::WhoAmIRequest>,
) -> std::result::Result<tonic::Response<super::WhoAmIResponse>, tonic::Status> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.AdminService/WhoAmI",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("holger.v1.AdminService", "WhoAmI"));
self.inner.unary(req, path, codec).await
}
/// How much storage this holger has, may still write, and has already used —
/// one statvfs(3) over its data root plus the archive bytes of every
/// repository that OWNS storage (groups are views and are not summed). Admin
/// read: it describes the host filesystem. A holger that was handed no data
/// root refuses by name; it never answers a capacity of zero for a failure.
pub async fn capacity(
&mut self,
request: impl tonic::IntoRequest<super::CapacityRequest>,
) -> std::result::Result<tonic::Response<super::CapacityReply>, tonic::Status> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.AdminService/Capacity",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("holger.v1.AdminService", "Capacity"));
self.inner.unary(req, path, codec).await
}
/// ★★ ELECT THIS BOX A TWIN — the bootstrap door, and the ONLY way a role is
/// conferred over the wire.
///
/// Owner rulings 2026-09-21: "the weakest machine must become the twin.
/// PERIOD" and "IT must not CHANGE role later ! so its a bootstrap thing from
/// xtask". So: both machines install from ONE identical medium with NO role
/// parameter, the control plane MEASURES them (Capacity here, plus the host
/// facts it reads itself), and it tells the weaker one what it is. Exactly
/// once: a box that already holds a role record refuses by name
/// (holger-twin-4), and a box that is not FRESH refuses by name
/// (holger-twin-5) because electing a serving box would put its history
/// behind a follower's refusals.
///
/// ADMIN-gated like every other mutation here. The election is RECORDED and
/// APPLIED LIVE (stinky 14 §P3): every door refuses writes by name from the
/// reply on, and the follow starts. What waits for the next start is the
/// loopback bind of the public doors — a process does not rebind a door
/// underneath its clients.
pub async fn become_twin(
&mut self,
request: impl tonic::IntoRequest<super::BecomeTwinRequest>,
) -> std::result::Result<
tonic::Response<super::BecomeTwinReply>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.AdminService/BecomeTwin",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("holger.v1.AdminService", "BecomeTwin"));
self.inner.unary(req, path, codec).await
}
/// ★ THE TWIN OVER MUTUAL TLS — the front certifies, the primary's OWN
/// issuer signs, the twin pins it (nordisk-twin; gunnar's model). In order:
/// BecomeTwin on the twin; TwinCsr on the twin (the key is born there and
/// never crosses); IssueTwinCertificate on the primary; InstallTwinCertificate
/// on the twin. The same three with purpose "recharge" certify a fresh main to
/// read its twin's door (then Recharge on the main). ADMIN-gated; the three
/// pairing steps are asked of a twin too (they change no artifact).
pub async fn twin_csr(
&mut self,
request: impl tonic::IntoRequest<super::TwinCsrRequest>,
) -> std::result::Result<tonic::Response<super::TwinCsrReply>, tonic::Status> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.AdminService/TwinCsr",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("holger.v1.AdminService", "TwinCsr"));
self.inner.unary(req, path, codec).await
}
/// Refused by name unless this box serves a replication door (holger-twin-7)
/// and the principal is one it certifies (holger-twin-8): `holger-twin` from a
/// primary only, `holger-recharge` from any box with a door.
pub async fn issue_twin_certificate(
&mut self,
request: impl tonic::IntoRequest<super::IssueTwinCertificateRequest>,
) -> std::result::Result<
tonic::Response<super::IssueTwinCertificateReply>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.AdminService/IssueTwinCertificate",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(
GrpcMethod::new("holger.v1.AdminService", "IssueTwinCertificate"),
);
self.inner.unary(req, path, codec).await
}
/// Refused by name: another key (holger-twin-9), a CA that did not sign it
/// (holger-twin-10), a CA other than the pinned one (holger-twin-11). A
/// renewal under the SAME CA is taken.
pub async fn install_twin_certificate(
&mut self,
request: impl tonic::IntoRequest<super::InstallTwinCertificateRequest>,
) -> std::result::Result<
tonic::Response<super::InstallTwinCertificateReply>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.AdminService/InstallTwinCertificate",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(
GrpcMethod::new("holger.v1.AdminService", "InstallTwinCertificate"),
);
self.inner.unary(req, path, codec).await
}
/// A fresh main pulls the estate and every repository from the box its
/// "recharge" credential names, over that door, now. Admin; refused on a twin.
pub async fn recharge(
&mut self,
request: impl tonic::IntoRequest<super::RechargeRequest>,
) -> std::result::Result<tonic::Response<super::RechargeReply>, tonic::Status> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.AdminService/Recharge",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("holger.v1.AdminService", "Recharge"));
self.inner.unary(req, path, codec).await
}
/// ★ THE RECHARGE LANE'S TWO QUESTIONS (gunnar's Bootstrap.Status and the
/// twin's log head, in holger's words). Asked BEFORE a byte moves, admin-read
/// gated, answered by a box that serves nothing yet too.
/// On the MAIN: fresh / restoring / recharged, and what makes it not fresh.
pub async fn recharge_status(
&mut self,
request: impl tonic::IntoRequest<super::RechargeStatusRequest>,
) -> std::result::Result<
tonic::Response<super::RechargeStatusReply>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.AdminService/RechargeStatus",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("holger.v1.AdminService", "RechargeStatus"));
self.inner.unary(req, path, codec).await
}
/// On the TWIN: what it holds and whether it can give everything back.
pub async fn twin_status(
&mut self,
request: impl tonic::IntoRequest<super::TwinStatusRequest>,
) -> std::result::Result<
tonic::Response<super::TwinStatusReply>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.AdminService/TwinStatus",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("holger.v1.AdminService", "TwinStatus"));
self.inner.unary(req, path, codec).await
}
/// ★ FENCE THIS PRIMARY (Gunnar's `fence_primary` pattern): the box that runs a
/// pulled `fence_primary` (or a recharge's fence-first) asks the OLD primary to
/// refuse every write from now on, and reads the fence back from the reply.
/// ADMIN-gated by identity (not by the write gates: a fenced box answers a second
/// fence the same). Refused on a twin, which takes no writes.
pub async fn fence_primary(
&mut self,
request: impl tonic::IntoRequest<super::FencePrimaryRequest>,
) -> std::result::Result<
tonic::Response<super::FencePrimaryReply>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.AdminService/FencePrimary",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("holger.v1.AdminService", "FencePrimary"));
self.inner.unary(req, path, codec).await
}
/// ★ THE ADMIN VIEW (2026-09-28; gunnar's admin mode, holger's own code): the
/// operational snapshot an ADMINISTRATOR's console panes read — every disk and
/// volume, the twin, the growth, the clock, plugins and monetize, the audit
/// log, the installer's log door. ADMIN-READ (the Admin role under RBAC;
/// refused by name to every other role and to a caller with no valid
/// credential; open only on a server with no auth at all, like every admin
/// read). Measured on every call, never cached. See AdminSnapshotReply.
pub async fn admin_snapshot(
&mut self,
request: impl tonic::IntoRequest<super::AdminSnapshotRequest>,
) -> std::result::Result<
tonic::Response<super::AdminSnapshotReply>,
tonic::Status,
> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
format!("Service was not ready: {}", e.into()),
)
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/holger.v1.AdminService/AdminSnapshot",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("holger.v1.AdminService", "AdminSnapshot"));
self.inner.unary(req, path, codec).await
}
/// ★ THE ESTATE BOARD (lane E3, 2026-10-19; Gunnar's `Admin.Topology` pattern,
/// Holger's own code): "which boxes is this estate, as THIS holger knows them?"
/// One row per box — this box first, then every box it holds EVIDENCE of: the
/// pairing feed's front, main and twin, the twins whose reports it keeps, the
/// primary a twin follows, and the downstream holgers that pull from it. Each row
/// carries its own live state, the sentence that says how holger knows, the
/// WireGuard overlay address, and the twin's lag. The board is DATA (Holger v2.0
/// H2): the server decides every word and draws nothing; holger-ui draws the rows
/// as they came and decides nothing. ADMIN-READ, like TwinStatus: the rows name
/// addresses, never a secret. Also served as JSON, `GET /-/estate.json`, on the
/// HTTP door.
pub async fn topology(
&mut self,
request: impl tonic::IntoRequest<super::TopologyRequest>,
) -> std::result::Result<tonic::Response<super::TopologyReply>, tonic::Status> {
self.inner
.ready()
.await
.map_err(|e| {
tonic::Status::unknown(
The file goes on; the console shows all of it.