NAME
Langertha::Skeid::KeyBroker - Pluggable API key resolution for Skeid nodes
VERSION
version 0.003
DESCRIPTION
The contract that turns a key reference (secret/skeid/remote/groq) into a secret, in memory, at the moment it is needed. Langertha::Skeid::KeyBroker::OpenBao is the implementation; this class is what code depends on.
Implement "resolve_key" in a subclass. Everything else — caching, request coalescing, the non-blocking entry point — is provided here, so a three-line broker gets them for free.
Two entry points, and which one is yours
"key_async" is the only one the request path may call. It answers from cache without touching the loop, and a miss is one round-trip however many requests are waiting on it.
"resolve_key" is what a subclass implements and what off-loop code (CLI, tests, setup scripts) may call directly. Calling it from a Mojolicious handler blocks every other in-flight request for the duration of the vault round-trip — see ADR 0005.
cache_ttl
How long a resolved key stays in memory, in seconds (default 300, 0 disables caching). Memory only: ADR 0003 forbids a disk cache, not this one. The cost of a stale key is one failed upstream call after a rotation; the cost of no cache is a vault round-trip on the request path, per request.
negative_cache_ttl
How long a failed resolution is remembered, in seconds (default 5, 0 disables). Short on purpose: it exists so a vault outage costs one round-trip per reference per few seconds instead of one per request, not to make a fixed misconfiguration stick.
resolve_key
my $key = $broker->resolve_key('secret/skeid/remote/groq');
What a subclass implements: resolve one reference, return the secret, die or return undef when it cannot. Blocking. Never call it from a request handler — call "key_async".
key_async
$broker->key_async($ref, sub {
my ($key, $error) = @_;
...
});
The request path's entry point. The callback always runs exactly once, with the key, or with undef and a message. A cached answer calls back immediately and synchronously.
resolve_key_async
$broker->resolve_key_async($ref, sub { my ($key, $error) = @_; ... });
The non-blocking half of "resolve_key", for subclasses that can do better than blocking. The default implementation calls resolve_key and hands the result to the callback, which keeps a simple broker correct — but keeps it blocking. Langertha::Skeid::KeyBroker::OpenBao overrides it.
Callers want "key_async": this one is uncached and uncoalesced.
cached_key
my $hit = $broker->cached_key($ref); # { key => …, error => … } or nothing
The live cache entry for a reference, or nothing when there is none or it has expired. Distinguishes "cached failure" from "not cached" — both would look like undef otherwise.
forget_key
$broker->forget_key($ref); # one reference
$broker->forget_key; # all of them
Drops cached resolutions, so the next request resolves again. What a key rotation calls.
needs_refresh
True when the broker's own credential has to be renewed before the next resolution. Always 0 here; Langertha::Skeid::KeyBroker::OpenBao overrides it.
refresh
Renews the broker's own credential. A no-op here; Langertha::Skeid::KeyBroker::OpenBao overrides it.
SEE ALSO
Langertha::Skeid::KeyBroker::OpenBao, "key_broker" in Langertha::Skeid, and ADR 0003 (secrets live in memory only) in the distribution repository.
SUPPORT
Issues
Please report bugs and feature requests on GitHub at https://github.com/Getty/langertha-skeid/issues.
IRC
Join #langertha on irc.perl.org or message Getty directly.
CONTRIBUTING
Contributions are welcome! Please fork the repository and submit a pull request.
AUTHOR
Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/
COPYRIGHT AND LICENSE
This software is copyright (c) 2026 by Torsten Raudssus.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.