Liking cljdoc? Tell your friends :D

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

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