Liking cljdoc? Tell your friends :D

hive-system.crypto.caesium

Caesium / libsodium-backed implementation of hive-system.protocols/ICrypto.

Uses parameter-object map signatures (:crypto/* keys) like the rest of the crypto layer. Loads caesium lazily via requiring-resolve so absence of native libsodium only fails at construction (->caesium-crypto).

Algorithms supported: :xchacha20-poly1305 — caesium.crypto.aead/xchacha20poly1305-ietf-{encrypt,decrypt}

Caesium / libsodium-backed implementation of `hive-system.protocols/ICrypto`.

Uses parameter-object map signatures (`:crypto/*` keys) like the rest of
the crypto layer. Loads caesium lazily via `requiring-resolve` so absence
of native libsodium only fails at construction (`->caesium-crypto`).

Algorithms supported:
  :xchacha20-poly1305  — caesium.crypto.aead/xchacha20poly1305-ietf-{encrypt,decrypt}
raw docstring

hive-system.crypto.core

Plain-fn DSL over hive-system.protocols/ICrypto. Parameter-object style: every fn takes a single map keyed under :crypto/*.

Callers depend on this ns + ICrypto, never on a concrete adapter (Tink / caesium / ...). Java interop stays inside the adapters.

Surface (key prefix :crypto/*):

(aead-seal! {:crypto/adapter c :crypto/key k :crypto/plaintext pt :crypto/aad aad}) => Result<{:crypto/ciphertext ^bytes :crypto/iv ^bytes}>

(aead-open! {:crypto/adapter c :crypto/key k :crypto/ciphertext ct :crypto/iv nonce :crypto/aad aad}) => Result<{:crypto/plaintext ^bytes}>

(hpke-seal! {:crypto/adapter c :crypto/pubkey pub :crypto/plaintext pt :crypto/aad aad}) => Result<{:crypto/ciphertext ^bytes}>

(hpke-open! {:crypto/adapter c :crypto/keypair kp :crypto/ciphertext ct :crypto/aad aad}) => Result<{:crypto/plaintext ^bytes}>

(sha256 {:crypto/adapter c :crypto/data ^bytes}) => Result<{:crypto/hash ^bytes :crypto/algorithm :sha256}>

(random-key) -> 32-byte ^bytes (XChaCha20 key) (random-nonce) -> 24-byte ^bytes (XChaCha20 nonce) (random-x25519-keypair) -> {:public 32B :private 32B}

Default :crypto/algorithm keys are filled in by each fn (caller may override via the same key in the input map).

Plain-fn DSL over `hive-system.protocols/ICrypto`. Parameter-object style:
every fn takes a single map keyed under `:crypto/*`.

Callers depend on this ns + ICrypto, never on a concrete adapter
(Tink / caesium / ...). Java interop stays inside the adapters.

Surface (key prefix `:crypto/*`):

  (aead-seal! {:crypto/adapter c :crypto/key k :crypto/plaintext pt :crypto/aad aad})
    => Result<{:crypto/ciphertext ^bytes :crypto/iv ^bytes}>

  (aead-open! {:crypto/adapter c :crypto/key k :crypto/ciphertext ct
               :crypto/iv nonce :crypto/aad aad})
    => Result<{:crypto/plaintext ^bytes}>

  (hpke-seal! {:crypto/adapter c :crypto/pubkey pub
               :crypto/plaintext pt :crypto/aad aad})
    => Result<{:crypto/ciphertext ^bytes}>

  (hpke-open! {:crypto/adapter c :crypto/keypair kp
               :crypto/ciphertext ct :crypto/aad aad})
    => Result<{:crypto/plaintext ^bytes}>

  (sha256 {:crypto/adapter c :crypto/data ^bytes})
    => Result<{:crypto/hash ^bytes :crypto/algorithm :sha256}>

  (random-key)              -> 32-byte ^bytes  (XChaCha20 key)
  (random-nonce)             -> 24-byte ^bytes  (XChaCha20 nonce)
  (random-x25519-keypair)    -> {:public 32B :private 32B}

Default `:crypto/algorithm` keys are filled in by each fn (caller may
override via the same key in the input map).
raw docstring

hive-system.crypto.kdf

Pure-Java HKDF-SHA256 (RFC 5869). Shared by ICrypto adapters so that crypto-derive-key returns byte-identical bytes regardless of which adapter resolves the call.

Composed from javax.crypto.Mac HMAC-SHA256 — no native dependency.

Pure-Java HKDF-SHA256 (RFC 5869). Shared by ICrypto adapters so that
`crypto-derive-key` returns byte-identical bytes regardless of which
adapter resolves the call.

Composed from `javax.crypto.Mac` HMAC-SHA256 — no native dependency.
raw docstring

hive-system.crypto.macros

Macro sugar for AEAD ceremonies built on hive-system.crypto.core.

Provided as an opt-in convenience layer on top of the fn DSL — required only when call sites benefit from compact nested-let composition.

Use:

(let-aead [crypto (tink/->tink-crypto) key (core/random-key) {:keys [ciphertext iv]} (core/aead-seal! crypto key pt aad)] (core/aead-open! crypto key ciphertext iv aad))

let-aead short-circuits on the first :error Result — same semantics as hive-dsl.result/let-ok — but accepts plain (non-Result) values for adapter / key construction lines.

Macro sugar for AEAD ceremonies built on `hive-system.crypto.core`.

Provided as an opt-in convenience layer on top of the fn DSL — required
only when call sites benefit from compact nested-let composition.

Use:

  (let-aead [crypto (tink/->tink-crypto)
             key (core/random-key)
             {:keys [ciphertext iv]} (core/aead-seal! crypto key pt aad)]
    (core/aead-open! crypto key ciphertext iv aad))

`let-aead` short-circuits on the first :error Result — same semantics as
`hive-dsl.result/let-ok` — but accepts plain (non-Result) values for
adapter / key construction lines.
raw docstring

hive-system.crypto.tink

Tink-backed implementation of hive-system.protocols/ICrypto.

See hive-system.protocols/ICrypto for the parameter-object contract — every op receives a single map keyed under :crypto/*.

Algorithms supported: :xchacha20-poly1305 — symmetric AEAD (subtle.XChaCha20Poly1305) :hpke-x25519 — RFC 9180 single-shot HPKE (DHKEM-X25519 + HKDF-SHA256 + ChaCha20-Poly1305) :sha256 — message digest

Tink-backed implementation of `hive-system.protocols/ICrypto`.

See `hive-system.protocols/ICrypto` for the parameter-object contract —
every op receives a single map keyed under `:crypto/*`.

Algorithms supported:
  :xchacha20-poly1305  — symmetric AEAD (subtle.XChaCha20Poly1305)
  :hpke-x25519         — RFC 9180 single-shot HPKE
                         (DHKEM-X25519 + HKDF-SHA256 + ChaCha20-Poly1305)
  :sha256              — message digest
raw docstring

hive-system.deps.core

DependencyEnsurer — composes IShell + IDistroDetector + IPackageInstaller to deliver the user-level ensure! verb.

The record itself is pure-data + dispatch; every side effect goes through one of the three injected ports. Tests exercise the policy matrix (:auto / :ask / :throw) by feeding fakes.

DependencyEnsurer — composes IShell + IDistroDetector + IPackageInstaller
to deliver the user-level `ensure!` verb.

The record itself is pure-data + dispatch; every side effect goes
through one of the three injected ports. Tests exercise the policy
matrix (`:auto` / `:ask` / `:throw`) by feeding fakes.
raw docstring

hive-system.deps.protocols

Protocols for the dependency-ensurer subsystem.

Why this exists

Tools that shell out (ssh, sshpass, pass, gpg, clojure, …) currently assume the binary is on PATH. When missing, calls explode with a confusing IOException: Cannot run program … deep in babashka.process. This namespace introduces the user-level verb "make sure I can call X" — composing narrower ports (IShell from hive-system.protocols, plus IDistroDetector and IPackageInstaller defined here) so each impl stays ISP-narrow.

ISP boundary

  • IDistroDetector — "which Linux/BSD/macOS family am I on?" One axis of variance: distro identity. Pure-ish (reads /etc/os-release, uname, etc.).
  • IPackageInstaller — "install package X via the system pkg mgr". One axis of variance: package manager (apt / dnf / pacman / brew …). All side effects.
  • IDependencyEnsurer — the user-level facade that composes the above three to deliver a single ensure! verb.

New distros plug in via new IDistroDetector impls; new package managers via new IPackageInstaller impls. IDependencyEnsurer itself stays distro/manager-agnostic.

Protocols for the dependency-ensurer subsystem.

## Why this exists

Tools that shell out (`ssh`, `sshpass`, `pass`, `gpg`, `clojure`, …)
currently assume the binary is on PATH. When missing, calls explode
with a confusing `IOException: Cannot run program …` deep in
babashka.process. This namespace introduces the user-level verb
"make sure I can call X" — composing narrower ports
(`IShell` from `hive-system.protocols`, plus `IDistroDetector` and
`IPackageInstaller` defined here) so each impl stays ISP-narrow.

## ISP boundary

- `IDistroDetector`  — "which Linux/BSD/macOS family am I on?"
  One axis of variance: distro identity. Pure-ish (reads
  `/etc/os-release`, `uname`, etc.).
- `IPackageInstaller` — "install package X via the system pkg mgr".
  One axis of variance: package manager (apt / dnf / pacman / brew …).
  All side effects.
- `IDependencyEnsurer` — the user-level facade that composes the
  above three to deliver a single `ensure!` verb.

New distros plug in via new `IDistroDetector` impls; new package
managers via new `IPackageInstaller` impls. `IDependencyEnsurer`
itself stays distro/manager-agnostic.
raw docstring

hive-system.deps.registry

Standard local-host adapters for IDistroDetector and IPackageInstaller, plus a default-ensurer factory that wires the whole thing up using the existing hive-system.shell.core/make-shell adapter.

Adapters here read /etc/os-release and shell out to apt-get / dnf / pacman / brew via the injected IShell. They never auto-install during construction; only install! runs effects, and only when explicitly invoked by IDependencyEnsurer/ensure! under an :auto or accepted :ask policy.

Tests use fake IShell + fake distro/installer impls — see test/hive_system/deps/core_test.clj.

Standard local-host adapters for IDistroDetector and IPackageInstaller,
plus a `default-ensurer` factory that wires the whole thing up using
the existing `hive-system.shell.core/make-shell` adapter.

Adapters here read `/etc/os-release` and shell out to apt-get / dnf /
pacman / brew via the injected IShell. They never auto-install during
construction; only `install!` runs effects, and only when explicitly
invoked by `IDependencyEnsurer/ensure!` under an `:auto` or accepted
`:ask` policy.

Tests use *fake* IShell + fake distro/installer impls — see
`test/hive_system/deps/core_test.clj`.
raw docstring

hive-system.events.interceptors

Reusable interceptors for system operations.

  • timing: Measures wall-clock duration, injects into effects
  • journal: Records operation to IJournal after execution
  • tool-check: Validates binary exists before shell exec
  • result-lift: Converts raw handler return into Result-typed effect

All interceptors follow the re-frame context model: {:coeffects {:event [...] :db ...} :effects {...}}

Reusable interceptors for system operations.

- timing:      Measures wall-clock duration, injects into effects
- journal:     Records operation to IJournal after execution
- tool-check:  Validates binary exists before shell exec
- result-lift: Converts raw handler return into Result-typed effect

All interceptors follow the re-frame context model:
{:coeffects {:event [...] :db ...} :effects {...}}
raw docstring

hive-system.events.system

Event-driven system operations.

Registers event handlers for shell execution, tool checking, and process lifecycle. Each handler returns a Result in the effects map, which the journal interceptor persists.

Init: (init!) ;; default — no journal (init! {:journal-fn record!}) ;; with IJournal callback

Dispatch: (dispatch [:sys/exec "ls -la"]) (dispatch [:sys/exec ["rg" "pattern" "src/"]]) (dispatch [:sys/exec-ok "make test"]) (dispatch [:sys/which "rg"]) (dispatch [:sys/require-tool :ripgrep]) (dispatch [:sys/require-tools [:ripgrep :fd :jq]])

All handlers return {:result (ok ...) or (err ...)} in effects. The timing interceptor adds :_duration-ms. The journal interceptor persists to IJournal if configured.

Event-driven system operations.

Registers event handlers for shell execution, tool checking,
and process lifecycle. Each handler returns a Result in the
effects map, which the journal interceptor persists.

Init:
  (init!)                        ;; default — no journal
  (init! {:journal-fn record!})  ;; with IJournal callback

Dispatch:
  (dispatch [:sys/exec "ls -la"])
  (dispatch [:sys/exec ["rg" "pattern" "src/"]])
  (dispatch [:sys/exec-ok "make test"])
  (dispatch [:sys/which "rg"])
  (dispatch [:sys/require-tool :ripgrep])
  (dispatch [:sys/require-tools [:ripgrep :fd :jq]])

All handlers return {:result (ok ...) or (err ...)} in effects.
The timing interceptor adds :_duration-ms.
The journal interceptor persists to IJournal if configured.
raw docstring

hive-system.fs.core

IPathQuery implementation backed by babashka.fs. All operations return hive-dsl Results for railway composition.

Convenience API (stateless, default instance): (exists? path) → Result<boolean> (directory? path) → Result<boolean> (absolute-dir? path) → Result<boolean> (resolve-first-dir [...]) → Result<string> (find-files path exts) → Result<vec<string>> (expand-path path exts) → vec<string> (rescue-wrapped)

DIP: consumers depend on IPathQuery protocol, not this impl. Swap FsPathQuery for a test double via make-path-query or protocol.

IPathQuery implementation backed by babashka.fs.
All operations return hive-dsl Results for railway composition.

Convenience API (stateless, default instance):
  (exists? path)           → Result<boolean>
  (directory? path)        → Result<boolean>
  (absolute-dir? path)     → Result<boolean>
  (resolve-first-dir [...]) → Result<string>
  (find-files path exts)   → Result<vec<string>>
  (expand-path path exts)  → vec<string> (rescue-wrapped)

DIP: consumers depend on IPathQuery protocol, not this impl.
Swap FsPathQuery for a test double via make-path-query or protocol.
raw docstring

hive-system.gpu.ollama

OllamaGpuExecutor — IGpuExecutor + IGpuStatus over the ollama HTTP API.

First concretion of hive-system.protocols.gpu. Mirrors hive-system.secrets/* placement: protocol in hive-system.protocols.*, concrete adapter in a sibling sub-namespace.

Capabilities: :embed — POST /api/embed :generate — POST /api/generate (single-shot, no streaming for now)

What we deliberately don't do here:

  • Pool / retry classification — that's the caller's job via hive-weave.gpu/gpu-fork-join + hive-dsl rescue helpers.
  • Streaming / SSE — generate returns once, no incremental delta.
  • Model autoload — assumes ollama pull <model> already happened.

Construct via (->ollama-executor opts) — never the raw record ctor.

OllamaGpuExecutor — IGpuExecutor + IGpuStatus over the ollama HTTP API.

First concretion of hive-system.protocols.gpu. Mirrors hive-system.secrets/*
placement: protocol in hive-system.protocols.*, concrete adapter in a
sibling sub-namespace.

Capabilities:
  :embed     — POST /api/embed
  :generate  — POST /api/generate (single-shot, no streaming for now)

What we deliberately don't do here:
  - Pool / retry classification — that's the caller's job via
    hive-weave.gpu/gpu-fork-join + hive-dsl rescue helpers.
  - Streaming / SSE — generate returns once, no incremental delta.
  - Model autoload — assumes `ollama pull <model>` already happened.

Construct via (->ollama-executor opts) — never the raw record ctor.
raw docstring

hive-system.gpu.probe

nvidia-smi probe satisfying IGpuStatus.

Authoritative source for VRAM observability. The OllamaGpuExecutor's gpu-status returns -1 for VRAM fields because ollama doesn't expose them reliably; this probe shells out to nvidia-smi for the truth.

Uses hive-system.protocols/IShell so a mock shell can drive tests without launching real subprocesses (DIP). Default ctor wires the stateless hive-system.shell.core/exec! convenience.

Output schema (ok branch): {:vram-free-mb long :vram-total-mb long :inflight 0 ; probe doesn't track in-flight calls :queued 0 ; idem :backend-id :nvidia-smi}

Err branch tags: :gpu/no-driver — nvidia-smi missing on PATH or returned non-zero :gpu/probe-parse — nvidia-smi output couldn't be parsed :gpu/transport-failed — exec layer raised

nvidia-smi probe satisfying IGpuStatus.

Authoritative source for VRAM observability. The OllamaGpuExecutor's
gpu-status returns -1 for VRAM fields because ollama doesn't expose them
reliably; this probe shells out to nvidia-smi for the truth.

Uses hive-system.protocols/IShell so a mock shell can drive tests
without launching real subprocesses (DIP). Default ctor wires the
stateless hive-system.shell.core/exec! convenience.

Output schema (ok branch):
  {:vram-free-mb  long
   :vram-total-mb long
   :inflight      0          ; probe doesn't track in-flight calls
   :queued        0          ; idem
   :backend-id    :nvidia-smi}

Err branch tags:
  :gpu/no-driver       — nvidia-smi missing on PATH or returned non-zero
  :gpu/probe-parse     — nvidia-smi output couldn't be parsed
  :gpu/transport-failed — exec layer raised
raw docstring

hive-system.process.core

IProcess implementation via java.lang.ProcessBuilder / ProcessHandle. Long-lived process lifecycle: spawn returns a live handle; wait/signal/pipe act on it. All operations return hive-dsl Result.

IProcess implementation via java.lang.ProcessBuilder / ProcessHandle.
Long-lived process lifecycle: spawn returns a live handle; wait/signal/pipe
act on it. All operations return hive-dsl Result.
raw docstring

hive-system.process.liveness

Process liveness detection — single source of truth for is this pid alive? semantics across the hive ecosystem.

Use this instead of inlining kill -0, ProcessHandle/of, or backend- specific tricks. Liveness check is a system-level concern and belongs in hive-system (per the IProcess family of protocols), not in callers.

The LivenessSignal ADT is the closed sum of valid outcomes:

:liveness/alive — pid is owned by a live OS process :liveness/dead — pid was once valid but the process is gone (ESRCH) :liveness/unknown — pid is nil/non-integer, or the check itself raised transiently. Callers MUST NOT zombify on :unknown (degrade-soft semantics — protect against false positives during boot races, container migrations, and short-lived OS hiccups).

Process liveness detection — single source of truth for `is this pid alive?`
semantics across the hive ecosystem.

Use this instead of inlining `kill -0`, `ProcessHandle/of`, or backend-
specific tricks. Liveness check is a system-level concern and belongs in
hive-system (per the IProcess family of protocols), not in callers.

The `LivenessSignal` ADT is the closed sum of valid outcomes:

  :liveness/alive   — pid is owned by a live OS process
  :liveness/dead    — pid was once valid but the process is gone (ESRCH)
  :liveness/unknown — pid is nil/non-integer, or the check itself raised
                      transiently. Callers MUST NOT zombify on :unknown
                      (degrade-soft semantics — protect against false
                      positives during boot races, container migrations,
                      and short-lived OS hiccups).
raw docstring

hive-system.process.worker

IWorker implementation — a warm request/response worker over a long-lived process (hive-system.process IProcess). Requests/responses are newline- delimited EDN; a monotonic :id correlates each response. Calls are single- flight via a hive-weave gate (1 permit); reads are timeout-bounded.

IWorker implementation — a warm request/response worker over a long-lived
process (hive-system.process IProcess). Requests/responses are newline-
delimited EDN; a monotonic :id correlates each response. Calls are single-
flight via a hive-weave gate (1 permit); reads are timeout-bounded.
raw docstring

hive-system.protocols

Core protocols for hive-system.

Layer 1: IJournal — temporal execution fabric (Datahike/Proximum) Layer 2: System operation protocols (IProcess, INetwork, IFilesystem, etc.)

Every system operation returns Result (ok/err) from hive-dsl. Every Result is journaled with bitemporal semantics.

SOLID-D: All consumers depend on these protocols, never concrete implementations. SOLID-O: New operation types = new protocol implementations, zero changes to journal.

Core protocols for hive-system.

Layer 1: IJournal — temporal execution fabric (Datahike/Proximum)
Layer 2: System operation protocols (IProcess, INetwork, IFilesystem, etc.)

Every system operation returns Result (ok/err) from hive-dsl.
Every Result is journaled with bitemporal semantics.

SOLID-D: All consumers depend on these protocols, never concrete implementations.
SOLID-O: New operation types = new protocol implementations, zero changes to journal.
raw docstring

hive-system.protocols.gpu

GPU executor protocols — DIP boundary for GPU-bound work.

Two protocols, ISP-split: IGpuExecutor — does work (embed, generate, rerank) IGpuStatus — introspects backend (free VRAM, inflight, queued)

Closed ADTs cross the boundary: GpuRequest — what the caller wants done + declared :gpu/vram-mb budget GpuResponse — output payload + executor-id + duration-ms

Layering rationale: hive-mcp consumers (embedders, future rerankers, future local-LLM compression) depend on these protocols, never on a concrete backend. hive-weave.gpu admits requests against a VRAM budget BEFORE dispatching through gpu-execute!. New backends (ollama, llama.cpp, vLLM) extend the protocols; admission control + consumers stay closed (OCP).

CPPB mapping: Promote — GpuRequest is the ADT shape callers build up Pipeline — hive-weave.gpu/gpu-fork-join admits + dispatches Boundary — concrete IGpuExecutor impl performs IO

SOLID: SRP — IGpuExecutor does work; IGpuStatus introspects; admission lives in hive-weave OCP — new backends extend; consumers + admission untouched LSP — every executor returns the same Result shape (see schemas below) ISP — split work vs introspection so a probe-only sidecar (nvidia-smi) can satisfy IGpuStatus without claiming work-execution capability DIP — every consumer depends on these protocols, never on a record

GPU executor protocols — DIP boundary for GPU-bound work.

Two protocols, ISP-split:
  IGpuExecutor  — does work (embed, generate, rerank)
  IGpuStatus    — introspects backend (free VRAM, inflight, queued)

Closed ADTs cross the boundary:
  GpuRequest    — what the caller wants done + declared :gpu/vram-mb budget
  GpuResponse   — output payload + executor-id + duration-ms

Layering rationale:
  hive-mcp consumers (embedders, future rerankers, future local-LLM
  compression) depend on these protocols, never on a concrete backend.
  hive-weave.gpu admits requests against a VRAM budget BEFORE dispatching
  through gpu-execute!. New backends (ollama, llama.cpp, vLLM) extend the
  protocols; admission control + consumers stay closed (OCP).

CPPB mapping:
  Promote   — GpuRequest is the ADT shape callers build up
  Pipeline  — hive-weave.gpu/gpu-fork-join admits + dispatches
  Boundary  — concrete IGpuExecutor impl performs IO

SOLID:
  SRP — IGpuExecutor does work; IGpuStatus introspects; admission lives in hive-weave
  OCP — new backends extend; consumers + admission untouched
  LSP — every executor returns the same Result shape (see schemas below)
  ISP — split work vs introspection so a probe-only sidecar (nvidia-smi)
        can satisfy IGpuStatus without claiming work-execution capability
  DIP — every consumer depends on these protocols, never on a record
raw docstring

hive-system.redaction.core

Redaction registry + walker for safely surfacing structured data (compiled plans, event payloads, env maps, log lines) to an AI assistant or any debug surface.

Model

A rule is a map:

{:select <selector> ; path-vector OR predicate fn (key,val)→bool :replace <fn> ; (fn [val] -> replacement) :id <keyword> ; assigned by register-rule! :doc <string?>}

Rules are stored in a global atom registry. redact walks input via clojure.walk/postwalk, applying matching rules and auto-replacing any Tainted it encounters with its print-method form.

Selector forms

  • Vector path — [:env "SSHPASS"] matches the value at that path inside any nested map.
  • Predicate fn — (fn [k v] ...) invoked for every map entry; truthy return → replace the value.

Default rules

Registered at namespace load time:

:env/sshpass → [:env "SSHPASS"] → "<redacted>" :env/ssh-auth-sock → [:env "SSH_AUTH_SOCK"] → "<redacted>" :env/ssh-askpass → [:env "SSH_ASKPASS"] → "<redacted>" :env/ssh-private-key → [:env "SSH_PRIVATE_KEY"] → "<redacted>"

Tainted handling

Any Tainted encountered during the walk is replaced with its pr-str form (the redacted print-method output) — no rule needed.

Privacy contract

redact never invokes untaint and never reads :value directly. It is safe to compose into a logger appender.

Redaction registry + walker for safely surfacing structured data
(compiled plans, event payloads, env maps, log lines) to an AI
assistant or any debug surface.

## Model

A *rule* is a map:

  {:select  <selector>     ; path-vector OR predicate fn (key,val)→bool
   :replace <fn>           ; (fn [val] -> replacement)
   :id      <keyword>      ; assigned by register-rule!
   :doc     <string?>}

Rules are stored in a global atom registry. `redact` walks input via
`clojure.walk/postwalk`, applying matching rules and auto-replacing
any `Tainted` it encounters with its print-method form.

## Selector forms

- Vector path  — `[:env "SSHPASS"]` matches the value at that path
                 inside any nested map.
- Predicate fn — `(fn [k v] ...)` invoked for every map entry; truthy
                 return → replace the value.

## Default rules

Registered at namespace load time:

  :env/sshpass         → [:env "SSHPASS"]        → "<redacted>"
  :env/ssh-auth-sock   → [:env "SSH_AUTH_SOCK"]  → "<redacted>"
  :env/ssh-askpass     → [:env "SSH_ASKPASS"]    → "<redacted>"
  :env/ssh-private-key → [:env "SSH_PRIVATE_KEY"] → "<redacted>"

## Tainted handling

Any `Tainted` encountered during the walk is replaced with its
`pr-str` form (the redacted print-method output) — no rule needed.

## Privacy contract

`redact` never invokes `untaint` and never reads `:value` directly.
It is safe to compose into a logger appender.
raw docstring

hive-system.redaction.ssh-argv

Structural redactor for ssh argv vectors.

Goal

Preserve the shape of the argv (every flag in its place, every option preserved, count unchanged) while replacing Tainted slots with stable hash tokens like <host:#a3f4> / <id:#7c2>.

The redactor is structurally aware: it understands the standard ssh(1) flag syntax and knows which slots can hold a hostname / identity / port. But it is intentionally CONSERVATIVE — it ONLY touches slots whose contents are Tainted. Plain strings pass through unchanged.

Why conservative

A hostname is whatever the user happens to call their VPS. We don't want to pattern-match hostnames (false positives, false negatives). Instead, the credential resolver / plan compiler decides what is sensitive by wrapping in Tainted. The redactor's job is to take that signal and present it as a token rather than a <redacted ...> blob — preserving structural fidelity for debugging.

Recognized ssh flag idioms

Single-arg flags (the next argv slot is the value):

-l <user> → identity -i <keyfile> → identity (keyfile path) -p <port> → port -o <key=val> → option (passed through; we don't parse it) -F, -E, -S, -W, -L, -R, -D, -J, -Q, -e, -m, -c, -O, -B (each of the above takes a value in the following slot)

Boolean flags (no following value): -1 -2 -4 -6 -A -a -C -f -G -g -K -k -M -N -n -q -s -T -t -V -v -X -x -Y -y

Anything that doesn't look like a flag and appears after we've consumed flags is treated as the destination (host, or user@host).

Behavior

Plain strings: pass through verbatim. Tainted slots: replaced with their <src:#hash> token form. If a Tainted carries :source :argv-host, you get <host:#xxxx>; for :argv-id you get <id:#xxxx>; the source label IS the token prefix.

Repeated Tainted with the same underlying value within a single argv produces the SAME token (because the hash is value-stable within a JVM). Operators can spot "this argv references the same host twice" at a glance.

The function does NOT call untaint and does NOT lengthen or shorten the argv. Output count == input count.

Structural redactor for ssh argv vectors.

## Goal

Preserve the *shape* of the argv (every flag in its place, every
option preserved, count unchanged) while replacing Tainted slots with
stable hash tokens like `<host:#a3f4>` / `<id:#7c2>`.

The redactor is structurally aware: it understands the standard
ssh(1) flag syntax and knows which slots can hold a hostname /
identity / port. But it is intentionally CONSERVATIVE — it ONLY
touches slots whose contents are `Tainted`. Plain strings pass
through unchanged.

## Why conservative

A hostname is whatever the user happens to call their VPS. We don't
want to pattern-match hostnames (false positives, false negatives).
Instead, the credential resolver / plan compiler decides what is
sensitive by wrapping in `Tainted`. The redactor's job is to take
that signal and present it as a token rather than a `<redacted ...>`
blob — preserving structural fidelity for debugging.

## Recognized ssh flag idioms

Single-arg flags (the next argv slot is the value):

  -l <user>          → identity
  -i <keyfile>       → identity (keyfile path)
  -p <port>          → port
  -o <key=val>       → option (passed through; we don't parse it)
  -F, -E, -S, -W, -L, -R, -D, -J, -Q, -e, -m, -c, -O, -B
     (each of the above takes a value in the following slot)

Boolean flags (no following value): -1 -2 -4 -6 -A -a -C -f -G -g
  -K -k -M -N -n -q -s -T -t -V -v -X -x -Y -y

Anything that doesn't look like a flag and appears after we've
consumed flags is treated as the destination (host, or user@host).

## Behavior

Plain strings: pass through verbatim.
Tainted slots: replaced with their `<src:#hash>` token form. If a
               Tainted carries `:source` :argv-host, you get
               `<host:#xxxx>`; for :argv-id you get `<id:#xxxx>`;
               the source label IS the token prefix.

Repeated Tainted with the same underlying value within a single
argv produces the SAME token (because the hash is value-stable
within a JVM). Operators can spot "this argv references the same
host twice" at a glance.

The function does NOT call untaint and does NOT lengthen or shorten
the argv. Output count == input count.
raw docstring

hive-system.redaction.tainted

Tainted-value wrapper for sensitive material that must NOT reach an AI assistant or any debug surface — but whose presence and identity should still be observable via stable per-run hash tokens.

Purpose

Where hive-system.secrets.core/Secret is the storage primitive for credentials ("don't print, don't compare, don't serialize"), Tainted is a diagnostic primitive: it wraps any value (hostnames, ports, identities, env values, argv slots) so we can correlate the same underlying value across many log lines with a short hash token like <host:#a3f4> — without ever printing the value itself.

Type

Tainted is a defrecord with three fields:

:value — the wrapped sensitive value :source — non-sensitive label (e.g. "pass:vps/r1/ip", :argv-host) :hash — 4-hex-char stable token derived from HMAC-SHA256(salt, value)

Hash semantics

  • Hash is computed once at construction and cached.
  • Same value within a single JVM run produces the SAME hash token, so operators can correlate <host:#a3f4> across log lines.
  • Salt is generated per JVM at namespace-load time via SecureRandom and held in a private atom — cross-JVM-restart unlinkability is by design (the salt cannot be reconstructed from prior runs).
  • Hash space is 16^4 = 65,536 — collision probability is acceptable within a single run's working set of distinct sensitive values.

Print safety

print-method ALWAYS emits <redacted src=... h=#xxxx> and NEVER the underlying value. toString mirrors that.

Audit surface

  • untaint — the ONE blessed unwrap. Every call site is a leak risk. This is the only safe extraction point and MUST only be invoked at trust boundaries (process spawn, network write, file write to a trusted local sink). Never call it within reach of a log appender, event subscriber, or anything whose output may be surfaced to the assistant.

Non-goals

  • Encryption / secure memory wiping. JVM strings can't be reliably zeroed; the same caveats as Secret apply.
  • Cross-process correlation. By design — see Hash semantics above.
Tainted-value wrapper for sensitive material that must NOT reach an AI
assistant or any debug surface — but whose *presence and identity*
should still be observable via stable per-run hash tokens.

## Purpose

Where `hive-system.secrets.core/Secret` is the storage primitive for
credentials ("don't print, don't compare, don't serialize"), `Tainted`
is a *diagnostic* primitive: it wraps any value (hostnames, ports,
identities, env values, argv slots) so we can correlate the same
underlying value across many log lines with a short hash token like
`<host:#a3f4>` — without ever printing the value itself.

## Type

`Tainted` is a defrecord with three fields:

  :value  — the wrapped sensitive value
  :source — non-sensitive label (e.g. "pass:vps/r1/ip", :argv-host)
  :hash   — 4-hex-char stable token derived from HMAC-SHA256(salt, value)

## Hash semantics

- Hash is computed once at construction and cached.
- Same value within a single JVM run produces the SAME hash token,
  so operators can correlate `<host:#a3f4>` across log lines.
- Salt is generated per JVM at namespace-load time via SecureRandom
  and held in a private atom — cross-JVM-restart unlinkability is by
  design (the salt cannot be reconstructed from prior runs).
- Hash space is 16^4 = 65,536 — collision probability is acceptable
  within a single run's working set of distinct sensitive values.

## Print safety

`print-method` ALWAYS emits `<redacted src=... h=#xxxx>` and NEVER
the underlying value. `toString` mirrors that.

## Audit surface

- `untaint` — the ONE blessed unwrap. Every call site is a leak risk.
  This is the only safe extraction point and MUST only be invoked at
  trust boundaries (process spawn, network write, file write to a
  trusted local sink). Never call it within reach of a log appender,
  event subscriber, or anything whose output may be surfaced to the
  assistant.

## Non-goals

- Encryption / secure memory wiping. JVM strings can't be reliably
  zeroed; the same caveats as `Secret` apply.
- Cross-process correlation. By design — see Hash semantics above.
raw docstring

hive-system.secrets.core

Opaque secret container for credentials, keys, and other sensitive values.

Purpose

Carry sensitive values through the system without leaking them via logs, REPL output, exception traces, pretty-printers, or accidental stdout. Unwrapping requires an explicit expose call — auditable, greppable, intentional.

Type

Secret is a deftype (not defrecord) — it is intentionally NOT a map. Keyword lookup ((:value s)), get, and map destructuring all return nil. The underlying field is reachable only via Java interop ((.value s)), which is greppable and easy to ban via lint.

Audit surface

  • expose — the ONE blessed unwrap. Every call site is a leak risk.
  • (.value <Secret>) — interop escape hatch; ban in lint.

Print safety

Registered for print-method, print-dup, and clojure.pprint/simple-dispatch. toString overrides Object — covers exception messages, log lines. Hash is constant (0); equality is constant-time. Never serializable.

Non-goals (v1)

  • Secure memory wiping. JVM strings cannot be reliably zeroed; this would be theater for SSH-pass / API-token use cases. Use char[] wrappers if you need defense against heap dumps.
  • Encryption at rest. This wraps live values in memory, not storage.
Opaque secret container for credentials, keys, and other sensitive values.

## Purpose

Carry sensitive values through the system without leaking them via
logs, REPL output, exception traces, pretty-printers, or accidental
stdout. Unwrapping requires an explicit `expose` call — auditable,
greppable, intentional.

## Type

`Secret` is a deftype (not defrecord) — it is intentionally NOT a map.
Keyword lookup (`(:value s)`), `get`, and map destructuring all return
nil. The underlying field is reachable only via Java interop
(`(.value s)`), which is greppable and easy to ban via lint.

## Audit surface

- `expose` — the ONE blessed unwrap. Every call site is a leak risk.
- `(.value <Secret>)` — interop escape hatch; ban in lint.

## Print safety

Registered for `print-method`, `print-dup`, and `clojure.pprint/simple-dispatch`.
`toString` overrides Object — covers exception messages, log lines.
Hash is constant (0); equality is constant-time. Never serializable.

## Non-goals (v1)

- Secure memory wiping. JVM strings cannot be reliably zeroed; this
  would be theater for SSH-pass / API-token use cases. Use char[]
  wrappers if you need defense against heap dumps.
- Encryption at rest. This wraps live values in memory, not storage.
raw docstring

hive-system.secrets.pass

GNU pass (password-store) ISecretBackend implementation.

Resolves entries from the user's pass store into opaque Secret values. Never logs the resolved content. Stderr is captured but sanitized in error returns.

API

  • ->PassBackend — defrecord constructor (preferred via DIP)
  • pass-show — convenience: full output as one Secret
  • pass-show-line — convenience: first non-empty line only
  • pass-available? — convenience: Result<bool> backend health

Backend errors

  • :pass/not-found — entry does not exist
  • :pass/empty — entry exists but resolved to blank
  • :pass/exec-failpass binary failed (binary missing, gpg lock, etc.)
  • :pass/timeout — pass invocation exceeded deadline

Errors include the lookup :key (NOT the resolved value) for diagnostics.

GNU pass (password-store) ISecretBackend implementation.

Resolves entries from the user's `pass` store into opaque Secret
values. Never logs the resolved content. Stderr is captured but
sanitized in error returns.

## API

- `->PassBackend`         — defrecord constructor (preferred via DIP)
- `pass-show`             — convenience: full output as one Secret
- `pass-show-line`        — convenience: first non-empty line only
- `pass-available?`       — convenience: Result<bool> backend health

## Backend errors

- `:pass/not-found` — entry does not exist
- `:pass/empty`     — entry exists but resolved to blank
- `:pass/exec-fail` — `pass` binary failed (binary missing, gpg lock, etc.)
- `:pass/timeout`   — pass invocation exceeded deadline

Errors include the lookup `:key` (NOT the resolved value) for diagnostics.
raw docstring

hive-system.secrets.protocols

Protocols for the secrets subsystem.

ISP boundary

ISecretBackend is the DIP seam between consumers (probe, hive-mcp, etc.) and concrete secret stores (GNU pass, Bitwarden CLI, 1Password, Vault, age-encrypted files, etc.).

New backends implement this protocol; consumers depend only on the protocol. No call site needs to change to swap or add backends.

Backend contract

A backend MUST:

  • Return Result<Secret> from fetch — never raw values, never plaintext bound in a map outside the Secret type.
  • Surface :line-only? and :timeout-ms opts (may ignore others).
  • Report available? cheaply (no network round-trip if avoidable).
  • Use a stable, namespaced backend-id keyword (e.g. :pass, :bw, :op, :vault, :age).
Protocols for the secrets subsystem.

## ISP boundary

`ISecretBackend` is the DIP seam between consumers (probe, hive-mcp,
etc.) and concrete secret stores (GNU pass, Bitwarden CLI, 1Password,
Vault, age-encrypted files, etc.).

New backends implement this protocol; consumers depend only on the
protocol. No call site needs to change to swap or add backends.

## Backend contract

A backend MUST:
- Return `Result<Secret>` from `fetch` — never raw values, never
  plaintext bound in a map outside the Secret type.
- Surface `:line-only?` and `:timeout-ms` opts (may ignore others).
- Report `available?` cheaply (no network round-trip if avoidable).
- Use a stable, namespaced `backend-id` keyword (e.g. `:pass`,
  `:bw`, `:op`, `:vault`, `:age`).
raw docstring

hive-system.secrets.registry

Backend registry + uniform resolution for ISecretBackend implementations.

Consumers depend on this ns + protocols.clj. They never need to know which concrete backend (pass, bw, op, vault, age) is in use.

Workflow

  1. At process boot, register the backends you need: (registry/register! (pass/make-pass-backend)) (registry/register! (bw/make-bw-backend {:session ...}))

  2. At call sites, resolve via a SecretRef map: (registry/fetch {:backend :pass :key "vps/r1/root"}) (registry/fetch {:backend :pass :key "vps/r1/ip" :opts {:line-only? true}})

    Returns Result<Secret>.

SecretRef shape

{:backend <keyword> ;; backend-id (e.g. :pass, :bw) :key <string> ;; opaque key passed to the backend :opts <map?>} ;; optional per-fetch opts

Validation

validate-ref checks structure WITHOUT touching the backend — pure, safe to run during config loading.

Backend registry + uniform resolution for ISecretBackend implementations.

Consumers depend on this ns + protocols.clj. They never need to know
which concrete backend (`pass`, `bw`, `op`, `vault`, `age`) is in use.

## Workflow

1. At process boot, register the backends you need:
     (registry/register! (pass/make-pass-backend))
     (registry/register! (bw/make-bw-backend {:session ...}))

2. At call sites, resolve via a SecretRef map:
     (registry/fetch {:backend :pass :key "vps/r1/root"})
     (registry/fetch {:backend :pass :key "vps/r1/ip" :opts {:line-only? true}})

   Returns Result<Secret>.

## SecretRef shape

{:backend  <keyword>     ;; backend-id (e.g. :pass, :bw)
 :key      <string>      ;; opaque key passed to the backend
 :opts     <map?>}       ;; optional per-fetch opts

## Validation

`validate-ref` checks structure WITHOUT touching the backend — pure,
safe to run during config loading.
raw docstring

hive-system.shell.core

IShell implementation via ProcessBuilder. All operations return hive-dsl Results.

IShell implementation via ProcessBuilder.
All operations return hive-dsl Results.
raw docstring

hive-system.shell.detect

Detect available package managers and system capabilities. Delegates to babashka.fs for path resolution.

Detect available package managers and system capabilities.
Delegates to babashka.fs for path resolution.
raw docstring

hive-system.shell.posix

Pure POSIX shell-quoting helpers.

Two functions:

  • shell-quote — single-quote a string for safe embedding in a sh -c command, escaping embedded single-quotes and quoting the empty string as '' so it survives tokenization.
  • join-as-cmd — join an argv into one shell-command string by quoting each element with shell-quote.

Re-quoting an already-quoted string nests correctly — each sh -c peel removes exactly one quoting layer.

Pure POSIX shell-quoting helpers.

Two functions:

  - `shell-quote` — single-quote a string for safe embedding in a
    `sh -c` command, escaping embedded single-quotes and quoting the
    empty string as `''` so it survives tokenization.
  - `join-as-cmd`  — join an argv into one shell-command string by
    quoting each element with `shell-quote`.

Re-quoting an already-quoted string nests correctly — each `sh -c`
peel removes exactly one quoting layer.
raw docstring

hive-system.shell.tools

Tool registry: maps tool names to their binaries, descriptions, and install hints per package manager.

(require-tool :ripgrep) => (ok {:path "/usr/bin/rg"}) or (err :tool/missing {:hints [...]})

Tool registry: maps tool names to their binaries, descriptions,
and install hints per package manager.

(require-tool :ripgrep) => (ok {:path "/usr/bin/rg"})
                         or (err :tool/missing {:hints [...]})
raw docstring

hive-system.temporal.journal

IJournal implementation backed by Datahike.

Stores operation executions as Datalog entities with bitemporal attributes:

  • :op/tx-time — when the operation was recorded (Datahike transaction time)
  • :op/valid-time — when the operation actually occurred (wall clock)
  • :op/type — keyword (:process/spawn, :network/connect, :shell/exec, etc.)
  • :op/input — EDN-serialized input args
  • :op/output — EDN-serialized Result (ok value or err)
  • :op/duration-ms — wall-clock duration
  • :op/success? — boolean (derived from Result)
  • :op/caller — agent-id or context string
  • :op/session — session identifier
  • :op/causal-prev — reference to prior operation (causal chain)

Schema is installed on first connection. Idempotent.

IJournal implementation backed by Datahike.

Stores operation executions as Datalog entities with bitemporal attributes:
- :op/tx-time     — when the operation was recorded (Datahike transaction time)
- :op/valid-time  — when the operation actually occurred (wall clock)
- :op/type        — keyword (:process/spawn, :network/connect, :shell/exec, etc.)
- :op/input       — EDN-serialized input args
- :op/output      — EDN-serialized Result (ok value or err)
- :op/duration-ms — wall-clock duration
- :op/success?    — boolean (derived from Result)
- :op/caller      — agent-id or context string
- :op/session     — session identifier
- :op/causal-prev — reference to prior operation (causal chain)

Schema is installed on first connection. Idempotent.
raw docstring

No vars found in this namespace.

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close