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

nordisk/edda

crates/nornir-vault/Cargo.toml

[package]
name = "nornir-vault"
# 0.1.1: DRIFTED from the published 0.1.0 — `CachedKekProvider` ("the KDF already ran,
# here is its output", provider.rs:171) exists here and not in the registry copy, so
# `dwarves` cannot compile against its own stated minimum. Found by the dwarves
# release gate as an ApiSkew blocker, 2026-08-23. It arrived when nornir-vault
# ABSORBED dwarves' own Argon2id+AES-256-GCM store (the younger shared crate winning
# over the elder private one, the owner's call) — `Session` then cached the KEK rather
# than a whole-file key, which is what needed a provider for it.
# 0.1.3: THE SAME DRIFT AGAIN, AND MEASURED. The registry's 0.1.2 (downloaded
# and unpacked 2026-09-20) contains NO `slots`, no `KeySlot`, no `nornir-tpm`
# dependency — it is the single-wrapped-DEK crate. The tree's 0.1.2 is the
# multi-holder v2 crate. Two different crates wearing one version number, which
# is the exact defect the 0.1.1 note below records, repeated three weeks later.
# The multi-key work therefore ships as 0.1.3 and the number moves with the
# shape from here on. (`nornir-tpm` had never been published at all, so the
# `tpm` feature of the registry's 0.1.2 could not have resolved either.)
version = "0.2.0"
edition = "2021"
authors = ["Ignalina ApS"]
description = "Client-side, at-rest-encrypted secrets vault for the nordisk THIN CLIENTS (korp first) — the local locked store a thin client keeps its OWN credentials in (mTLS client cert+key, Spark token) so they are not lying in plaintext on the container filesystem. Envelope encryption: a random per-vault DEK (AES-256-GCM) seals the entries; the DEK is wrapped by a KEK produced by a pluggable `VaultKeyProvider` chosen by auth method — `PinProvider` (Argon2id) and `OsKeyringProvider` (Secret Service) are implemented, OIDC→OpenBao / TPM / FIDO2 are trait stubs that slot in later. Unlock decrypts the file into MEMORY only (never plaintext to disk); secrets are `zeroize`-on-drop and never logged, Debug-printed, or placed in any state_json. Distinct from the server-side OpenBao (that is infra); this is the client's local store, sibling to the `nornir-auth-*` leaves. Consumed by korp (thin client), later holger/dwarves."
license = "MIT OR Apache-2.0"
repository = "https://git.gunnar.rs/nordisk/edda"
keywords = ["vault", "secrets", "envelope-encryption", "argon2", "zeroize"]
categories = ["cryptography", "authentication"]

[lib]
name = "nornir_vault"

[dependencies]
nornir-tpm = { path = "../nornir-tpm", version = "0.1.0", optional = true }
# AEAD for the envelope (DEK seals entries, KEK wraps DEK). AES-256-GCM: already
# vetted in the edda workspace lock (aes-gcm 0.11 = the aead-0.6 generation, a
# FULL release, not an rc) → guaranteed-green + supply-chain-minimal, and the
# thin-client host has AES-NI. Nonces are a fresh 96-bit random per seal; see the
# crate docs for why that is safe here and why XChaCha20-Poly1305 is the noted
# alternative.
aes-gcm = "0.11"
# Argon2id KDF for the PIN provider (memory-hard → stretches a low-entropy PIN).
argon2 = "0.6"
# Zeroize-on-drop for every in-memory secret + transient plaintext buffers.
zeroize = { version = "1", features = ["derive"] }
# CSPRNG for the DEK, salts and nonces (0.2 = the copy already in the lock).
getrandom = "0.4"
# Base64 for the binary blobs (wrapped DEK, nonces, ciphertext) inside the JSON
# header file. 0.22 = the copy already vetted in the lock.
base64 = "0.23"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
thiserror = "2"

# The OS-keyring provider (Secret Service / libsecret / KDE Wallet) is behind an
# OFF-BY-DEFAULT feature so the default build + the workspace check pull ONLY the
# crates already in the lock. Enabling it adds the `keyring` crate (a new dep) and
# needs a running Secret Service — its live test is `#[ignore]`d. See provider.rs.
[dependencies.keyring]
version = "3"
optional = true

[features]
default = []
os-keyring = ["dep:keyring"]
# The hardware slot. Off by default: it pulls a TPM client into every consumer
# and most of them have no chip. A build that turns it on gets `TpmProvider`.
tpm = ["dep:nornir-tpm"]

[dev-dependencies]
tempfile = "3"