Skip to content
Ocean-Atlasv0.1.0Canonical Knowledge

Secure Secret Access

A service needs credentials or provider configuration — database credentials, JWT signing configuration, payment provider configuration — that must never appear in the DSL or generated source as literal values.

How do you give a service typed, named access to secret values from potentially different secret backends, without hardcoding any secret value anywhere in the model?

  • Coupling — services should depend on a typed secret contract, not on a specific secret-backend product.
  • Reuse — related secrets (auth, payment) are easier to maintain as small, focused vaults than as one large flat set.
  • Security — secret values must never be written into the DSL; only their type and shape are declared.
  • Composition — one physical backend often needs to serve several logical secret groups at once.

Declare small, focused @vault blocks per concern (for example AuthVault, PaymentVault), each with the required engine and configType attributes and typed Secret declarations (type = <TypeRef>, never a value). Compose them into one primary vault using includes. A service then use vaults the vaults it needs and connects an expression to retrieve each secret through its typed contract.

flowchart LR
MainVault -- includes --> AuthVault["AuthVault<br/>Secret JwtCfg"]
MainVault -- includes --> PaymentVault["PaymentVault<br/>Secret PaymentCfg"]
MainVault["MainVault (primary)<br/>engine: hashicorp<br/>Secret DbCredentials"]
SecretService -- use vault --> MainVault
SecretService -- use vault --> AuthVault
SecretService -- use vault --> PaymentVault
@vault
Vault AuthVault
primary = false
engine = hashicorp
configType = VaultConfig
Secret JwtCfg
type = JwtConfig
Vault PaymentVault
primary = false
engine = hashicorp
configType = VaultConfig
Secret PaymentCfg
type = PaymentApiConfig
Vault MainVault
primary = true
includes = AuthVault, PaymentVault
engine = hashicorp
configType = VaultConfig
Secret DbCredentials
type = DatabaseCredentials
@service
SecretService
use vault MainVault
use vault AuthVault
use vault PaymentVault
use expression GetDbCredentials
use expression GetJwtConfig
connect api.getDbCredentials -> GetDbCredentials
connect api.getJwtConfig -> GetJwtConfig

This is a minimal illustrative fragment, not a complete duplicated example — see Working Examples for the full, runnable model.

  • Secret values never appear in the DSL — only typed contracts do.
  • Splitting vaults by concern keeps each one small and independently owned.
  • A primary composition can map several logical vaults to one physical backend while preserving their qualified identities.
  • Each vault must declare a valid engine and compatible configuration schema; the corresponding environment values must be supplied correctly at deployment time.
  • A service that composes many vaults takes on a dependency on all of their secret contracts being resolvable at runtime.
  • If a value is genuinely not secret (feature flags, timeouts, ports), model it with @config instead of @vault — see the Config DSL Reference. Most real services combine both: @config for non-secret settings, @vault for secret ones.
  • Simple Vault Usage — typed database, authentication, and payment secrets in focused vaults, composed into one primary vault for service access.