Skip to content

axm-vault

Catalog-resolver secrets manager (keyring + SecretStr) for AXM

CI axm-init axm-audit Coverage Python 3.12+


Installation

Bash
uv add axm-vault

Quick Start

Declare the credentials a package needs — the catalog describes schema only, it never holds a secret value:

Python
from axm_vault import CredentialGroup, CredentialSpec

group = CredentialGroup(
    id="acme",
    package="axm-acme",
    title="Acme",
    specs=(CredentialSpec(name="api_key", env="ACME_API_KEY", kind="token"),),
)

spec = group.spec("api_key")  # -> CredentialSpec(name='api_key', ...)

Resolve a value by walking the layer precedence (env > file > keyring > default > prompt) — the file tier is delegated to axm-config, the keyring tier is consulted only for SECRET specs:

Python
from axm_vault import Resolver, get

resolved = Resolver().resolve(group, "api_key")
resolved.value, resolved.layer   # e.g. ("s3cr3t", "env")

api_key = get("acme", "api_key")  # singleton convenience -> just the value

Features

  • Value-less catalog — models describe credential schema only, never store a secret
  • Entry-point discoveryload_catalog() aggregates axm.credentials groups (empty-safe, cached)
  • Layered resolutionResolver walks env > file > keyring > default > prompt; file tier delegated to axm-config, keyring only for SECRET
  • Typed bindingbind(model, group) builds a pydantic model from resolved values, SECRET fields as SecretStr
  • Value-free doctordoctor_data() / vault_doctor report each credential's {layer, present} provenance without ever returning a secret
  • MCP toolsvault_doctor (provenance) and vault_set (keyring/config) ship as axm.tools (MCP + CLI + DAG node)
  • Operator CLIaxm-vault exposes setup/get/set/rotate/doctor/path; interactive setup is TTY-guarded and idempotent, get masks secrets unless --reveal
  • Frozen & strict — immutable pydantic v2 models that forbid unknown fields
  • Modern Python — 3.12+ with strict typing
  • Tested — Full coverage with pytest