Typed loading
One struct, tag-driven, many sources. A generics API - Load[T] and Watch[T] - decodes and validates into your own types. No stringly-typed lookups.
mamori loads configuration and secrets from anywhere into typed, validated Go structs - then watches every source and reconciles changes at runtime. Rotate a database password upstream; your pool rotates too. No restart.
go get github.com/xavidop/mamoriaws-sm://prod/db#passwordv1v2type Config {
DBPassword secret.String✓
}pool.Rotate(cfg.DBPassword.Reveal())Each does one thing, through a well-defined interface, testable on its own.
One struct, tag-driven, many sources. A generics API - Load[T] and Watch[T] - decodes and validates into your own types. No stringly-typed lookups.
Native watch where the backend supports it - Kubernetes informers, Consul blocking queries, fsnotify - polling with jitter everywhere else, and lease-aware refresh for Vault.
An update that fails validation is rejected. Get() keeps returning the last good config. Your process never observes a half-applied or invalid state.
secret.String redacts itself in logs, fmt, and JSON. Only Reveal() exposes the value - and a shipped go vet analyzer flags sensitive refs stored in plain strings.
Tag a struct with where each value lives. mamori resolves, validates, and - withWatch - keeps it reconciled, handing you a diff-aware callback.
// One struct, many sources.
type Config struct {
DBPassword secret.String `source:"aws-sm://prod/db#password"`
LogLevel string `source:"env:LOG_LEVEL" default:"info"`
Workers int `source:"env:WORKERS" validate:"gte=1,lte=256"`
TLSCert []byte `source:"file:///etc/tls/tls.crt"`
}// Watch: reconcile at runtime, react without restarting.
w, _ := mamori.Watch[Config](ctx,
mamori.OnChange(func(ev mamori.Change[Config]) {
if ev.Changed("DBPassword") {
pool.Rotate(ev.New.DBPassword.Reveal())
}
}),
)
defer w.Close()
cfg := w.Get() // lock-free; always the last valid configProviders register with the database/sql pattern. Core has zero cloud-SDK dependencies - each provider is its own module. All pass theprovidertest conformance kit.
env:built-indotenv://built-infile://built-inaws-sm://aws-ps://vault://k8s-secret://k8s-cm://consul://gcp-sm://azure-kv://doppler://op://sops://postgres://mysql://sqlite://mongodb://redis://dynamodb://etcd://firestore://firebase-rtdb://firebase-rc://s3://gcs://azblob://cosmos://launchdarkly://unleash://flagsmith://configcat://split://growthbook://flipt://goff://yours://Because every provider is a Provider, decorators nest freely. Cache to cut API cost, fail over to a replica, rate-limit a twitchy backend, audit every resolve, or rewrite refs per tenant.
mamori.WithProvider(
middleware.Cache(5*time.Minute,
middleware.Audit(logger,
middleware.Failover(
primarySM,
replicaSM,
),
),
),
)secret.String and secret.Bytes render as [REDACTED] in String(), fmt, JSON, and slog. Only Reveal() exposes the value - and it's greppable in review.
reconcilevet flags any secret-bearing ref assigned to a plain string or []byte, so a leak can't slip past code review.
The exec: provider is off by default. Refs are never interpolated from other resolved values - one secret can't build another's command.
Zero() is best-effort and documented as such - no false promises about Go's GC. No payloads are ever logged; the conformance kit asserts it.
Typed. Watched. Reconciled. Runs in a Lambda, a systemd unit, or a Pod.
mamori uses cookies only for anonymous analytics, to see which docs are useful. No ads, no cross-site tracking. You can change this any time from the footer.