ADR-011: Credential Sets data model 

Status 

Accepted

Date 

2026-01-12

Context 

nr-vault currently stores atomic secrets (single values). Real integrations often require a set of related fields (e.g. OAuth2 client credentials: client_id, client_secret, token_url, scopes). Managing these as separate secrets is error-prone and lacks semantic validation.

We need a "Credential Set" concept while preserving the existing tx_nrvault_secret primitive and its encryption/audit semantics.

Decision 

We will introduce a new table/concept tx_nrvault_credential_set and define:

  • tx_nrvault_secret remains the primitive encrypted storage unit (atomic, type-agnostic)
  • tx_nrvault_credential_set becomes a typed wrapper that references exactly one secret row via secret_uid
  • The referenced secret contains an encrypted JSON payload holding all credential fields for the set

Credential sets do not replace tx_nrvault_secret. They build on top of it.

Example decrypted payloads 

Bearer token:

{"token": "sk-abc123..."}
Copied!

OAuth2 Client Credentials:

{
  "client_id": "my-client",
  "client_secret": "secret123",
  "token_url": "https://oauth.example.com/token",
  "scopes": ["read", "write"]
}
Copied!

Consequences 

Positive 

  • Reuses nr-vault's encryption, ACL, and audit model without duplication
  • A credential set becomes the stable reference target for the Service Registry
  • Rotation becomes straightforward: update one credential set = update one encrypted payload
  • Simplifies Rust transport integration: pass one ciphertext payload instead of N

Negative 

  • Fine-grained per-field ACL inside one credential set is not supported (acceptable: if you can use the credential set, you can use its fields)
  • Requires a migration/import story for existing scattered secrets

Alternatives considered 

Parent-child secrets model 

Credential set as parent, multiple child secrets.

Rejected for MVP: more joins and complexity; awkward for FFI integration (multiple blobs); unclear audit semantics.

Store encrypted blob directly in credential_set 

No secret FK, store encryption directly in tx_nrvault_credential_set.

Rejected: duplicates encryption/audit logic and creates two competing secret stores.

Metadata-only linking (tags) 

Link secrets via tags or metadata.

Rejected: weak referential integrity; too easy to break.