---
title: "ADR-011: Credential Sets data model"
manual: "nr-vault"
version: "1.0"
permalink: "https://docs.typo3.org/permalink/netresearch/nr-vault:adr-011-credential-sets@1.0"
source: "Developer/Adr/ADR-011-CredentialSetsDataModel.rst"
rendered: "2026-09-18T07:37:50+00:00"
---

# ADR-011: Credential Sets data model {#adr-011-credential-sets-data-model}

**Table of contents**

-   [Status](https://docs.typo3.org/permalink/netresearch/nr-vault:status@1.0)
-   [Date](https://docs.typo3.org/permalink/netresearch/nr-vault:date@1.0)
-   [Context](https://docs.typo3.org/permalink/netresearch/nr-vault:context@1.0)
-   [Decision](https://docs.typo3.org/permalink/netresearch/nr-vault:decision@1.0)
-   [Consequences](https://docs.typo3.org/permalink/netresearch/nr-vault:consequences@1.0)
-   [Alternatives considered](https://docs.typo3.org/permalink/netresearch/nr-vault:alternatives-considered@1.0)
-   [Related decisions](https://docs.typo3.org/permalink/netresearch/nr-vault:related-decisions@1.0)

## Status {#status}

Accepted

## Date {#date}

2026-01-12

## Context {#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 {#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 {#example-decrypted-payloads}

Bearer token:

**Bearer token payload**

```json
{"token": "sk-abc123..."}
```

OAuth2 Client Credentials:

**OAuth2 client credentials payload**

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

## Consequences {#consequences}

### Positive {#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 {#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 {#alternatives-considered}

### Parent-child secrets model {#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 {#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) {#metadata-only-linking-tags}

Link secrets via tags or metadata.

**Rejected**: weak referential integrity; too easy to break.

## Related decisions {#related-decisions}

-   [ADR-002: Envelope encryption](https://docs.typo3.org/permalink/netresearch/nr-vault:adr-002-envelope-encryption@1.0) \- Encryption model used by credential sets
-   [ADR-010: Secure Outbound inside nr-vault](https://docs.typo3.org/permalink/netresearch/nr-vault:adr-010-secure-outbound@1.0) \- Parent decision for Secure Outbound feature
