Skip to main content

Keep API secrets out of plaintext config: layered .ranbval* env files, decrypt vault tokens only when used, optional usage telemetry—minimal deps, your own HTTP/SDK stack.

Project description

Ranbval Python runtime

This package merges layered .ranbval* files into os.environ, keeps ranbval.* vault tokens opaque until safe_decrypt runs, and can optionally POST usage to your Ranbval password manager (Live Monitor). It ships only cryptography and certifi—your app keeps its own HTTP client and vendor SDKs.


Why we built Ranbval

With so many LLM models and APIs available today, managing secrets has become a nightmare. Someone shares an API key, it gets forwarded, and suddenly usage shows up on a bill nobody planned for. It is hard to know which API is in use, in which repository, or on which device—and who actually burned the tokens.

That is why we built Ranbval. It is a security and monitoring layer for API keys and secrets, not just another place to paste strings. Here is how it changes the game:

  • Total control — You decide which Git repositories may use a credential. If a repo is not authorized, the secret cannot be used for real API calls—even if a token or key string leaked.
  • Encrypted secretsNo plaintext .env in source control. Prefer load_ranbval() over scattering load_dotenv() everywhere: .ranbval* files hold config, and values shaped like ranbval.<salt>.<ciphertext>.<label> stay encrypted until your code explicitly decrypts them.
  • Full monitoringTelemetry and dashboards tie usage back to credentials and context so you can see what happened—including failed or suspicious paths—instead of flying blind.

No more paying for other people’s usage. Your secrets, your rules.

The Python runtime is on PyPI as ranbval-sdk. REST-facing integrations and no-code platform support are on the roadmap so the same model works beyond Python-only stacks.

We are talking to CEOs and investors who want to back the next wave of API secret governance; if that is you and you want to connect, reach out through the channels listed on the main Ranbval / password-manager project.


How it works (end-to-end)

  1. Config on disk — You keep KEY=value lines in .ranbval and related files (see below). Values can be plain text or ranbval.<salt>.<ciphertext>.<label> tokens produced by the vault.
  2. load_ranbval() — Merges those files into os.environ. Encrypted tokens are stored as-is; nothing is decrypted during this step.
  3. Your code — You read os.environ, call safe_decrypt(...) when a value is a ranbval.* token and you need the real secret for an API call.
  4. emit_telemetry(...) (optional) — After an outbound call, you POST a small payload to the password-manager so usage is attributed to the right vault credential (via client salt inside the token, or an explicit salt).

Importing the package does not load files or touch the network. You choose where to call load_ranbval() (e.g. start of main, app factory, worker entrypoint).


Install

pip install ranbval-sdk

Runtime dependencies are cryptography and certifi (for HTTPS verification). Everything else is your app’s own stack.


load_ranbval() — layered config

Call it explicitly when your process should pick up .ranbval* settings:

from ranbval_sdk import load_ranbval

load_ranbval()

Where files are found

With no arguments, the SDK walks from the current working directory upward until it finds a directory that contains .ranbval or any .ranbval.* file. That directory is the config root.

Helpers (optional):

  • find_ranbval_directory(start=None) — config root path or None
  • find_ranbval_file(start=None) — path to base .ranbval or first layer file
  • resolve_ranbval_mode(mode=None) — which mode name is active (see below)

Which mode is used

Mode selects .ranbval.{mode} and .ranbval.{mode}.local in the merge. Resolution order:

  1. load_ranbval(mode="...") if you pass mode
  2. Else RANBVAL_ENV, then ENVIRONMENT, then ENV
  3. Default development

Merge order (later wins)

For the chosen mode, existing files are merged in this order:

  1. .ranbval
  2. .ranbval.{mode}
  3. .ranbval.local
  4. .ranbval.{mode}.local

Duplicate keys: later file overrides earlier.

Applying values to os.environ

For each merged KEY=value:

  • override=False (default): set only if the key is missing or currently empty in os.environ.
  • override=True: merged values always replace what was already in os.environ.

Return value: True if at least one file was read, else False.

Single file instead of layers

load_ranbval("/absolute/or/relative/path/to/file")

Only that file is parsed; layer discovery is skipped.

Optional start directory

load_ranbval(start="/path/to/project/root")

Search for the config root begins at start instead of os.getcwd().


Vault tokens vs plain env values

  • Plain values in .ranbval* are copied into the environment unchanged.
  • ranbval.* tokens stay opaque strings in the environment until you call safe_decrypt(encoded, RANBVAL_VAULT_SECRET) (or your app’s equivalent secret).

Token shape: ranbval.<client_salt>.<blob>.<label> — telemetry uses <client_salt> when you pass vault_token_env="..." pointing at that env var.


safe_decrypt

from ranbval_sdk import safe_decrypt
import os

load_ranbval()
raw = os.environ["MY_API_CREDENTIAL"]
secret = os.environ["RANBVAL_VAULT_SECRET"]
plain = safe_decrypt(raw, secret) if raw.startswith("ranbval.") else raw
# use `plain` in headers, clients, etc.

Use this only when you actually need the secret; avoid logging it.


emit_telemetry

Sends one row to {RANBVAL_HOST}/api/telemetry (password-manager origin only—no /api suffix in RANBVAL_HOST).

Typical pattern after your HTTP or SDK call:

from ranbval_sdk import load_ranbval, emit_telemetry

load_ranbval()
# ... your request using decrypted credential if needed ...

emit_telemetry(
    vault_token_env="MY_API_CREDENTIAL",  # env var holding a ranbval.* token → salt extracted
    model_used="my-service.endpoint",     # free-form label in the dashboard
    prompt_tokens=0,
    completion_tokens=0,
    background=True,
)

If the credential is not a ranbval.* string, pass client_salt="..." instead of vault_token_env, or the call is a no-op (no salt → no POST).

Variable Purpose
RANBVAL_HOST Password-manager base URL (default: hosted instance).
RANBVAL_TELEMETRY 0 / false / off / no — skip telemetry POSTs.
RANBVAL_TELEMETRY_DEBUG 1 / true — print telemetry failures to stderr.

HTTPS uses certifi; upgrade certifi if certificate verification fails on your machine.


Optional: secure_client / build_secure_client

If you use a class-based third-party client that takes an API key in the constructor, you can wrap that class so it:

  • reads a named env var,
  • decrypts if it looks like ranbval.*,
  • passes the plain key into the constructor under the keyword your client expects,
  • optionally wraps one dotted method path to call emit_telemetry on the way back.
from ranbval_sdk import load_ranbval, secure_client
import some_sdk  # your dependency, not from this package

load_ranbval()
client = secure_client(
    some_sdk.Client,
    env_var="MY_API_CREDENTIAL",
    key_kwarg="api_key",
    method_path_to_patch="resources.create",  # optional
)

build_secure_client(...) returns a subclass instead of an instance—same parameters at the class level.


Git remote allowlist (optional)

The dashboard Allowed Git remotes list stores remote URLs (e.g. https://github.com/org/repo.git), not a folder path on disk. Enforcement runs inside safe_decrypt(): before decrypting a ranbval.* token, the SDK calls GET {RANBVAL_HOST}/api/public/repo-policy?client_salt=…. If the project has a non-empty allowlist, decryption raises PermissionError unless git config --get remote.origin.url (resolved from your current working directory upward to the repo root) normalizes to one of those URLs.

So: running the same script from …/ranbval-external-test/venv or from …/ranbval-sdk both succeed if they sit under one Git clone whose origin is allowlisted. To block usage from another clone, that other clone must have a different origin (or no origin)—the filesystem path alone is never compared.

Variable Purpose
RANBVAL_HOST Must reach the password-manager so repo policy can be loaded.
RANBVAL_SKIP_REPO_CHECK 1 / true — skip policy fetch and origin check (local dev only).

Example layout

See .ranbval.example. Put machine-only secrets in .ranbval.local / .ranbval.{mode}.local and add those files to .gitignore.


Further reading

In this monorepo, ranbval-password-manager README describes ingest schema, dashboard behavior, and backend APIs.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ranbval_sdk-0.4.4.tar.gz (15.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ranbval_sdk-0.4.4-cp312-cp312-macosx_26_0_arm64.whl (16.4 kB view details)

Uploaded CPython 3.12macOS 26.0+ ARM64

File details

Details for the file ranbval_sdk-0.4.4.tar.gz.

File metadata

  • Download URL: ranbval_sdk-0.4.4.tar.gz
  • Upload date:
  • Size: 15.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.3.2 CPython/3.12.0 Darwin/25.4.0

File hashes

Hashes for ranbval_sdk-0.4.4.tar.gz
Algorithm Hash digest
SHA256 21f34d70eadc9b687089b8d045dbceceb85470c562a5db8efb925ea96d3bb798
MD5 4f523310ccb30e58d925998748c069fd
BLAKE2b-256 b2db81e9bca19affa6b42fbaef059a0ca5db0e2abac0f77b6040baff9b06210f

See more details on using hashes here.

File details

Details for the file ranbval_sdk-0.4.4-cp312-cp312-macosx_26_0_arm64.whl.

File metadata

File hashes

Hashes for ranbval_sdk-0.4.4-cp312-cp312-macosx_26_0_arm64.whl
Algorithm Hash digest
SHA256 9c9c82c0b94e857eb901b53b030b26297409dc4e6460284f7656a51a6d14559f
MD5 eb336e320e8fe14ce9f84d829d3af628
BLAKE2b-256 63cc3e8cc70a1d5003ff3a68991fd5ec004551db590156d936ea1d20228d2761

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page