Vault

Architecture

How Vault's packages fit together.

Vault is organized as a set of focused Go packages. The root vault package defines shared types (entities, config, errors). Six service packages implement the domain logic. Supporting packages provide encryption, identity, scoping, configuration sources, plugins, audit hooks, and metrics. Three store backends implement the same composite interface.

Package diagram

┌─────────────────────────────────────────────────────────────────────────┐
│                          Service packages                               │
│                                                                         │
│  secret.Service   flag.Engine + flag.Service   config.Service           │
│  override.Resolver            rotation.Manager            audit.Logger  │
├──────────────────────────┬──────────────────────────────────────────────┤
│   Supporting packages    │   Plugin system                              │
│                          │                                              │
│  crypto (AES-256-GCM)   │  plugin.Plugin (base)                       │
│  id     (TypeID)         │  plugin.Registry                            │
│  scope  (context keys)   │    OnInit / OnShutdown                      │
│  source (config sources) │    SourceProvider                            │
│  audit_hook (events)     │    EncryptionProvider                       │
│  metrics (counters)      │    FlagEvaluator                            │
│                          │    OnSecretAccess / OnConfigChange           │
│                          │    RotationStrategy                          │
├──────────────────────────┴──────────────────────────────────────────────┤
│                           store.Store                                   │
│  (composite: secret.Store + flag.Store + config.Store +                │
│   override.Store + rotation.Store + audit.Store +                      │
│   Migrate / Ping / Close)                                              │
├───────────────┬─────────────────┬───────────────────────────────────────┤
│ store/memory  │ store/postgres  │ store/bun                            │
│ (in-process)  │ (pgx pool)      │ (Bun ORM)                           │
└───────────────┴─────────────────┴───────────────────────────────────────┘

Service construction

Each service is constructed independently. You choose which services to use and wire them together in your application.

import (
    "github.com/xraph/vault/crypto"
    "github.com/xraph/vault/secret"
    "github.com/xraph/vault/flag"
    "github.com/xraph/vault/config"
    "github.com/xraph/vault/override"
    "github.com/xraph/vault/rotation"
    "github.com/xraph/vault/audit"
    "github.com/xraph/vault/store/memory"
)

store := memory.New()

// Encryption
enc, _ := crypto.NewEncryptor(key)

// Secrets
secretSvc := secret.NewService(store, enc, secret.WithAppID("myapp"))

// Feature flags
engine := flag.NewEngine(store, flag.WithCacheTTL(30*time.Second))
flagSvc := flag.NewService(engine, flag.WithAppID("myapp"))

// Runtime config with tenant override resolution
resolver := override.NewResolver(store, store, override.WithCacheTTL(30*time.Second))
configSvc := config.NewService(store, config.WithAppID("myapp"), config.WithResolver(resolver))

// Secret rotation
rotMgr := rotation.NewManager(store, secretSvc, rotation.WithAppID("myapp"))

// Audit logging
logger := audit.NewLogger(store)

Request flow

Every Vault operation follows the same three-phase flow: scope, resolve, respond.

1. Scope

The scope package injects context values that identify the caller.

ctx = scope.WithScope(ctx, "myapp", "tenant-1", "user-42", "10.0.0.1")

These values are propagated automatically to every service, engine, and resolver.

2. Resolve

Each service resolves the requested resource using scope values from context:

  • secret.Service.Get -- looks up by key + appID, decrypts
  • flag.Engine.Evaluate -- reads tenant ID and user ID from context, evaluates rules in priority order (disabled check, tenant override, rules, default)
  • config.Service.String -- if a ValueResolver (override.Resolver) is configured, checks for a tenant override first, falls back to app-level config
  • override.Resolver.Resolve -- tenant override (if tenantID in context), then app config

3. Respond

The resolved value is returned to the caller. For type-safe services (flag.Service, config.Service), the value is coerced to the requested type. On error or type mismatch, the default value is returned.

Tenant isolation

Vault enforces tenant isolation at multiple layers:

LayerMechanism
Contextscope.WithTenantID injects tenant ID into context.Context
Flag engineReads vault.tenant_id from context for rule evaluation and tenant overrides
Override resolverReads vault.tenant_id from context to look up per-tenant config overrides
StoreAll queries include appID as a scoping parameter; composite keys are key:appID
Audit loggerExtracts all four scope values (appID, tenantID, userID, IP) from context

The context keys used by scope, flag, and override are intentionally identical (vault.tenant_id, vault.user_id), so a single scope.WithTenantID call propagates to all subsystems.

Plugin system

The plugin.Registry uses type-switch discovery. When a plugin is registered, the registry checks which capability interfaces it implements and categorizes it accordingly.

import "github.com/xraph/vault/plugin"

registry := plugin.NewRegistry()
registry.Register(myPlugin)

// Discovery
hooks := registry.InitHooks()          // []plugin.OnInit
sources := registry.SourceProviders()   // []plugin.SourceProvider
evaluator := registry.FlagEvaluatorByName("geo") // plugin.FlagEvaluator

A single plugin can implement multiple capabilities. For example, a plugin could implement both EncryptionProvider and OnSecretAccess to provide key management and audit logging in one type.

Capability interfaces

InterfaceMethod(s)Purpose
PluginName() stringBase interface -- all plugins must implement
OnInitOnInit(ctx) errorCalled during initialization
OnShutdownOnShutdown(ctx) errorCalled during shutdown
SourceProviderSource() source.Source, Priority() intProvides a configuration source
EncryptionProviderEncryptionKeyProvider() crypto.EncryptionKeyProviderProvides encryption keys
FlagEvaluatorEvaluatorName() string, Evaluate(ctx, rule, tenantID, userID) (bool, error)Custom flag rule evaluator
OnSecretAccessOnSecretAccess(ctx, key, action) errorHook for secret access events
OnConfigChangeOnConfigChange(ctx, key, oldValue, newValue) errorHook for config change events
RotationStrategyRotationName() string, Rotate(ctx, key, current) ([]byte, error)Custom secret rotation logic

Configuration sources

The source package provides a composable configuration source system. Sources are checked in priority order; the first hit wins.

SourceImportDescription
Memorygithub.com/xraph/vault/sourceIn-memory key-value map with watch support
Envgithub.com/xraph/vault/sourceReads from environment variables with optional prefix
Databasegithub.com/xraph/vault/sourceReads from a config.Store backend
Chaingithub.com/xraph/vault/sourcePriority-ordered list of sources (first hit wins)
import "github.com/xraph/vault/source"

chain := source.NewChain(
    source.NewEnv("MYAPP"),         // highest priority
    source.NewMemory(),             // dynamic overrides
    source.NewDatabase(store, "myapp"), // database fallback
)

val, err := chain.Get(ctx, "feature-x")

Package index

PackageImport pathPurpose
vaultgithub.com/xraph/vaultRoot -- Entity, Config, Option, sentinel errors
idgithub.com/xraph/vault/idTypeID-based entity identifiers with 8 prefixes
scopegithub.com/xraph/vault/scopeContext-based tenant/app/user/IP scoping
cryptogithub.com/xraph/vault/cryptoAES-256-GCM encryption, key providers, key store
secretgithub.com/xraph/vault/secretSecret entity, store interface, encrypted CRUD service
flaggithub.com/xraph/vault/flagFlag definitions, rules, engine, type-safe service
configgithub.com/xraph/vault/configConfig entries, store interface, typed accessor service
overridegithub.com/xraph/vault/overridePer-tenant config overrides and cached resolver
rotationgithub.com/xraph/vault/rotationRotation policies, records, background manager
auditgithub.com/xraph/vault/auditAudit log entries, store interface, logger
audit_hookgithub.com/xraph/vault/audit_hookAudit event extension for external systems
sourcegithub.com/xraph/vault/sourceComposable config sources (memory, env, database, chain)
plugingithub.com/xraph/vault/pluginPlugin interfaces (8 capabilities) and registry
metricsgithub.com/xraph/vault/metricsCounter/Histogram interfaces and collector
storegithub.com/xraph/vault/storeComposite Store interface definition
store/memorygithub.com/xraph/vault/store/memoryIn-memory store (testing and development)
store/postgresgithub.com/xraph/vault/store/postgresPostgreSQL store (pgx connection pool)
store/bungithub.com/xraph/vault/store/bunBun ORM store (PostgreSQL via Bun)

On this page