SkillAgentSearch skills...

Mamori

Typed, watchable config and secrets for Go: load from 30+ providers into validated structs, reconciled at runtime without a restart.

Install / Use

npx skills add xavidop/mamori

Installs into whichever agent you are using.

About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<div align="center">

守り  mamori

Typed, watchable config & secrets for Go

Load configuration and secrets from anywhere into validated Go structs - and keep them reconciled at runtime, without a restart.

Go Reference CI Go Report Card License: MIT

</div>

mamori (守り - Japanese for protection / safeguard) is an embedded Go library that loads application configuration and secrets from heterogeneous sources - environment, files, AWS Secrets Manager, Vault, GCP, Azure, Kubernetes, Consul, and more - into typed, validated structs, and keeps them reconciled at runtime. When a source value changes, mamori detects it, re-validates the whole configuration, and - only if the new snapshot is valid - atomically swaps it in and hands your application a diff-aware callback so it can react (rotate a DB pool, rebuild a client) without restarting.

Think: External Secrets Operator's provider model, one layer down - as a library inside your process instead of an operator inside your cluster.

Why

The primitives exist, but nobody composed them. runtimevar watches one variable but has no struct composition or validation. Viper/koanf do multi-source config but treat secrets and rotation as afterthoughts. The AWS caching client and Vault's LifetimeWatcher refresh one provider each, in silos. So every production Go service hand-rolls a ConfigManager with a ticker, a mutex, and a prayer. mamori is that glue, done once, with a provider ecosystem and a conformance kit.

Install

go get github.com/xavidop/mamori

env: and file:// work out of the box. Cloud providers are separate modules so the core has zero cloud-SDK dependencies:

go get github.com/xavidop/mamori/providers/aws            # aws-sm://  aws-ps://  aws-appconfig://
go get github.com/xavidop/mamori/providers/vault          # vault://
go get github.com/xavidop/mamori/providers/k8s            # k8s-secret://  k8s-cm://
go get github.com/xavidop/mamori/providers/vercel-gc      # vercel-gc://
go get github.com/xavidop/mamori/providers/cloudflare-kv  # cloudflare-kv://
go get github.com/xavidop/mamori/providers/heroku         # heroku://
go get github.com/xavidop/mamori/providers/https          # https://
go get github.com/xavidop/mamori/providers/hcp-vault-secrets # hcp-vs://
go get github.com/xavidop/mamori/providers/infisical      # infisical://
go get github.com/xavidop/mamori/providers/scaleway-sm    # scaleway-sm://
go get github.com/xavidop/mamori/providers/supabase       # supabase://
go get github.com/xavidop/mamori/providers/bitwarden      # bitwarden-sm://
# ... gcp, azure, consul, doppler, nacos, onepassword, sops

Quick start

type Config struct {
    // A secret from AWS Secrets Manager, redacted in logs by default.
    // ${ENV} expands from WithRefVars below, never from the ambient environment.
    DBPassword secret.String `source:"aws-sm://${ENV}/db#password"`

    // Plain config, with a default and validation
    LogLevel   string        `source:"env:LOG_LEVEL" default:"info" validate:"oneof=debug info warn error"`
    Workers    int           `source:"env:WORKERS"   default:"4"    validate:"gte=1,lte=256"`

    // A precedence chain: env wins if set, else Parameter Store, else the default
    Port       string        `source:"env:PORT,aws-ps://svc/port" default:"8080"`

    // A nested value, selected with an RFC 6901 JSON Pointer fragment
    DBUser     string        `source:"aws-sm://prod/db#/credentials/user"`

    // A file, hot-reloaded via fsnotify
    TLSCert    []byte        `source:"file:///etc/tls/tls.crt"`

    // ?decode= runs a stdlib decode pipeline before the field is populated
    TLSKey     []byte        `source:"aws-sm://prod/tls#key?decode=base64"`

    // A nested struct decoded from one JSON secret
    Redis      RedisConfig   `source:"aws-sm://prod/redis" flatten:"json"`
}

// One-shot load
cfg, err := mamori.Load[Config](ctx)

// Or: watch and reconcile at runtime
w, err := mamori.Watch[Config](ctx,
    mamori.WithRefVars(map[string]string{"ENV": "prod"}),
    // Prove a rotated password actually works before it becomes what Get() serves
    mamori.PreApply(func(ctx context.Context, ev mamori.Change[Config]) error {
        if !ev.Changed("DBPassword") {
            return nil
        }
        return pool.Ping(ctx, ev.New.DBPassword.Reveal())
    }),
    mamori.OnChange(func(ev mamori.Change[Config]) {
        if ev.Changed("DBPassword") {
            pool.Rotate(ev.New.DBPassword.Reveal())
        }
    }),
    mamori.OnError(func(err error) { metrics.Inc("config_error") }),
)
defer w.Close()

cfg := w.Get() // lock-free snapshot; always the last *valid* config

What makes it different

  • Typed & tag-driven - one struct, many sources, generics API (Load[T] / Watch[T]).
  • Atomic & validated - an update that fails validation is rejected; Get() keeps serving the last good config.
  • Rotation-safe - PreApply proves a rotated credential actually works before it goes live, at startup and on every rotation.
  • Derived fields - WithDerive rebuilds a value assembled from several fields, like a DSN from a host, a user, and a password, on every applied update, so it never goes stale after just one input rotates.
  • Precedence chains - source:"env:PORT,aws-ps://svc/port" tries sources in order, and every position stays watched.
  • Rich ref grammar - RFC 6901 JSON Pointer selection, ?decode= pipelines, and ${VAR} interpolation from an explicit, non-ambient source.
  • Reconciled at runtime - native watch where the backend supports it, polling with jitter everywhere else, lease-aware refresh for Vault.
  • Boots through an outage - WithBootstrapCache keeps an encrypted, on-disk snapshot of the last known-good values and starts from it when a restart cannot reach the backend, instead of failing to start.
  • Secret hygiene by default - secret.String / secret.Bytes redact in fmt, JSON, and slog; only the greppable Reveal() exposes a value, and mamori vet flags the ones you missed.
  • Observable - live per-field health, a readiness probe, a pre-deploy Doctor check, structured logs, and metrics.
  • Pluggable - providers register with the database/sql pattern, and a providertest conformance kit keeps them behaving identically.
  • Testable - a scriptable in-memory provider plus deterministic wait helpers, so OnChange and error paths are testable without a real backend.

Providers

| Module | Schemes | Watch | Errors classified beyond not-found | |---|---|---|---| | core (built-in) | env: · dotenv:// · file:// · exec: (opt-in) | fsnotify (file/dotenv) · poll (env/exec) | ✅ | | providers/aws | aws-sm:// · aws-ps:// · aws-appconfig:// | poll | ✅ | | providers/gcp | gcp-sm:// | poll | ✅ | | providers/azure | azure-kv:// · azure-appconfig:// | poll | ✅ | | providers/vault | vault:// | lease-aware poll (NotAfter) | ✅ | | providers/k8s | k8s-secret:// · k8s-cm:// | native (watch API) | ✅ | | providers/consul | consul:// | native (blocking queries) | ✅ | | providers/doppler | doppler:// | poll | ✅ | | providers/infisical | infisical:// | poll | ✅ | | providers/hcp-vault-secrets | hcp-vs:// | poll | ✅ | | providers/scaleway-sm | scaleway-sm:// | poll | ✅ | | providers/bitwarden | bitwarden-sm:// | poll | ✅ | | providers/onepassword | op:// | poll | ✅ | | providers/sops | sops:// | fsnotify | ✅ | | providers/supabase | supabase:// | poll | ✅ | | providers/postgres | postgres:// | native (LISTEN/NOTIFY) | ✅ | | providers/mysql | mysql:// | poll | ✅ | | providers/sqlite | sqlite:// | fsnotify | ✅ | | providers/mongodb | mongodb:// | native (change streams) | ✅ | | providers/dynamodb | dynamodb:// | poll | ✅ | | providers/redis | redis:// | native (keyspace notifications) | ✅ | | providers/etcd | etcd:// | native (watch API) | ✅ | | providers/nacos | nacos:// | native (long-poll listener) | ✅ | | providers/vercel-gc | vercel-gc:// | poll (digest) | ✅ | | providers/cloudflare-kv | cloudflare-kv:// | poll | ✅ | | providers/heroku | heroku:// | poll | ✅ | | providers/https | https:// | poll | ✅ | | providers/firestore | firestore:// | native (snapshot listeners) | ✅ | | providers/firebase-rc | firebase-rc:// | poll | ✅ | | providers/firebase-rtdb | firebase-rtdb:// | native (streaming) | no (chain preserved) | | providers/s3 | s3:// | poll (ETag) | ✅ | | providers/gcs | gcs:// | poll (generation) | ✅ | | providers/azblob | azblob:// | poll (ETag) | ✅ | | providers/cosmos | cosmos:// | poll (ETag) | ✅ | | providers/launchdarkly | launchdarkly:// | native (streaming) | ✅ | | providers/unleash | unleash:// | poll | n/a (no error surface) | | providers/flagsmith | flagsmith:// | poll | no (chain preserved) | | providers/configcat | configcat:// | poll | n/a (no error surface) | | providers/split | split:// | poll | n/a (no error surface) | | providers/growthbook | growthbook:// | poll | no (chain

Related Skills

View on GitHub
GitHub Stars14
CategoryDevelopment
Updated5h ago
Forks1

Languages

Go

Security Score

95/100

Audited on Aug 8, 2026

No findings