Expand description
x-lane QoS (lane/dl-metering gate, QoS-only extraction 2026-08-02): lane types, SLO admission policy, engine-truth step stats live in the memra-lanes crate so out-of-process controllers (the sidecar shape) can share them.
pub: the key file format, lifecycle helpers, and single-key path are the API a
deployment-owned binary provisions against (engine-billing-extraction-20260829).
API-key management (lane/api-keys, 2026-08-05): multi-key bearer auth that maps
key -> tenant, so metering, QoS lane class, and prefix-cache isolation key off a real
tenant identity instead of one shared trust domain.
DESIGN (launch-shaped, not enterprise-shaped):
- Keyring source:
MEMRA_API_KEYS— a TOML file path ([[keys]]entries, seeKeyEntry) or an inline env listtenant:sha256hex[:lane],...for file-less deploys. Keys are stored as SHA-256 hex ONLY — the plaintext exists exactly once, on the--gen-keyterminal. - Hot reload: mtime-poll (default 2s throttle) on every lookup — chosen over SIGHUP because it needs no signal thread and cannot be missed; a bad reload keeps the old ring and logs loudly (auth never degrades to open because of a typo).
- Back-compat:
MEMRA_API_KEY(the single static bearer — the owner’s daily driver and every serve script) keeps working unchanged as tenant"default", with or without a keyring configured. No keyring + no single key = open (dev behavior). - Tenant -> cache namespace: when a keyring is configured, every request’s PC-ISO
namespace is
t:<tenant>\x1f<cache_salt>(seescope_namespace). Tenant ids are validated[A-Za-z0-9_-]+, so the\x1fseparator cannot be forged from a client-controlledcache_salt— cross-tenant cache probing is structurally impossible. Keyring ABSENT keeps the raw-salt namespace, byte-identical to PC-ISO. - Lane class: a key is
interactive(default) orbatch. Batch-class keys default to the harvest QoS lane and are refused the protected interactive lane (403, loud — never a silent downgrade, per the honesty doctrine). - Per-key
rate_limit: optional concurrency-slot override; the effective cap is min(override, global lane cap) — the global cap stays authoritative.
CLI (--gen-key / --revoke-key, see run_cli): prints the plaintext once and
appends the hash entry; revoke flips enabled = false by key prefix. No web UI.
Structs§
- KeyEntry
- One keyring entry — the on-disk TOML shape (
[[keys]]). - KeyStore
- The live keyring: source + hot-reload state. File-backed rings re-stat on lookup
(throttled to
poll) and swap in the new ring when mtime moves; a reload that fails to parse KEEPS the old ring and logs the error (never fail-open, never flap). - Keyring
- Parsed keyring. Request-time lookup scans fixed-length digests with constant-time equality rather than relying on short-circuit String/HashMap key comparison.
- Tenant
Ctx - The resolved identity a request acts as — what flows to cache scoping, lane admission, rate-limit headers, and the usage/meter log line.
Enums§
- Auth
Denied - Why a presented key was refused.
Unknown-> 401,Disabled-> 403. - Lane
Class - A key’s QoS lane class.
Interactivekeys behave exactly like pre-lane traffic (default lane interactive, anyx-lanehonored).Batchkeys default to the harvest lane and may not claim the protected interactive lane.
Functions§
- authenticate_
with - The full auth law, pure over its inputs (unit-testable without env): keyring key match -> that key’s tenant (or Disabled -> 403) single static key match-> tenant “default” (the back-compat daily driver) nothing configured -> open, tenant “default” anything else -> Unknown -> 401 The keyring and the single key COMPOSE: setting MEMRA_API_KEYS does not break MEMRA_API_KEY callers (the owner’s serve scripts keep working unchanged).
- constant_
time_ secret_ eq - Compare secrets without length- or prefix-dependent early exit. Hashing first gives the comparison a fixed 32-byte shape even when callers supply different-length values.
- gen_key
- Generate a key for
tenant, print the plaintext ONCE, append the hash entry to the keys file (created if missing). Returns the plaintext (for tests). - global
- The global keystore, if
MEMRA_API_KEYSconfigured one. - init_
from_ env - Called once from main() before serving. Exits the process on a bad config.
- install_
key - Install an already-generated key into a ring. This is the fleet fan-out primitive: one control-plane key can be installed byte-identically on every serving origin without making any serving host the authority for the others. Replaying the exact same entry is idempotent; a prefix collision with different material or policy fails closed.
- meter_
key - The per-tenant METERING key for a PC-ISO namespace (lane/cache-metering): the tenant
half of
scope_namespace— keyring deployments aggregate one row per tenant across all its end-user salts; no-keyring namespaces (the raw salt) pass through unchanged (“” = the default single-tenant namespace). Unforgeable for the same reason scope_namespace is: NS_SEP is excluded from tenant ids, so a salt can never move its tokens into another tenant’s row. - revoke_
key - Disable every key whose
prefixstarts withhandle(or whose sha256 matches the handle’s hash, if a full plaintext key was pasted). Exactly one match required — ambiguity is an error, not a mass revoke. Rewrites the file (comments not preserved). - run_cli
- CLI dispatch: handles
--gen-key/--revoke-keyif present, returning the exit code; None = no key-management args, boot the server normally. - scope_
namespace - PC-ISO namespace scoping: with a keyring configured, a request’s cache namespace is
t:<tenant>\x1f<salt>— a tenant’s keys share cache; different tenants never do; a client-controlled salt cannot cross the\x1fboundary (tenant ids exclude it). Without a keyring the raw salt passes through, byte-identical to PC-ISO behavior. - sha256_
hex - SHA-256 of a plaintext key, lower-case hex — the only form a key is ever stored in.
- tenant_
is_ valid