Skip to main content

Credential custody · service

Credentials held for people.
Read only by the workload that may.

Secrets keeps the tokens and keys a workload holds on a person's behalf. A workload hands it a value; Secrets encrypts it in the application, stores only ciphertext in PostgreSQL, and gives it back only to a workload granted that exact tenant and action. The person who owns it can see its metadata, revoke it or delete it, and nobody reads a value back through a user route.

Rust service and client · PostgreSQL · specified in ESS · Apache-2.0

secrets.custody · ESS domain

ENTITY · 6 FIELDSPreparedTransactionPreparedENTITY · 9 FIELDSSecretActiveRevoked
  • Entities2

Hover or focus an entity to see what it relates to.

The secrets.custody domain, generated from spec/ by secrets-docs.
entities in the domain
2
relations
0
shipped, runs today
11
planned
2

01 / What it does

Custody, not provider logic.

Secrets holds bytes, versions, ownership and audit records. OAuth exchange, refresh and upstream revocation stay in the service that integrates the provider.

  1. Encrypted before storage

    Shipped

    Every version gets its own data key, wrapped by a versioned key-encryption key that PostgreSQL never sees. The ciphertext is bound to its tenant, reference, version and disclosure.

  2. Tenant-bound, least privilege

    Shipped

    Workloads are Kubernetes service accounts granted explicit actions in one tenant; people are verified by Identity and act only on what they own.

  3. Atomic prepared batches

    Shipped

    A workload stages puts and deletes in one tenant and commits them in one PostgreSQL transaction, or aborts them.

  4. Named secrets over several backends

    Shipped

    An in-process library with named, scoped secrets over the OS keychain and this service, one backend per namespace and no fallback, and secretsctl, a local CLI that never prints a secret. Read-only 1Password is planned.

02 / One write

From request to ciphertext.

Every route follows the same order: the caller is verified before storage is touched, and the value is encrypted before it reaches the database.

  1. HTTPBounded request

    A JSON body of at most 1 MiB and a bearer token. Values travel only in bodies.

  2. AuthorityVerify the caller

    Kubernetes TokenReview for workloads, Identity for people: subject, tenant and actions.

  3. PolicyCheck tenant and action

    The route's action and the request's tenant must match the principal, or it is refused.

  4. CryptoSeal the value

    A fresh data key, AES-256-GCM, wrapped by the active key with the reference as associated data.

  5. PostgreSQLCommit with its audit row

    Ciphertext, wrapped key, metadata and one audit event in one transaction.

03 / Specification

What Secrets is specified in.

The secrets.custody domain of the ESS specification, retrofitted from the shipped service. A conformance suite of 111 scenarios runs it against the real router and store on every check. Generated from spec/ by secrets-docs.

ESS domain · secrets.custody

secrets.custody

Encrypted, tenant-scoped custody of secret values, their revocation and deletion, and atomic prepared mutation batches.

  • Entities2
  • One
  • Many
  • Initial state
ENTITY · 6 FIELDSPreparedTransactionPreparedENTITY · 9 FIELDSSecretActiveRevoked

Hover or focus an entity to see its fields, lifecycle and relations. Press Enter to pin it, Escape to clear.

Lifecycles with transitions

Secret
Domain as text
Entities
EntityIdentity and fieldsLifecycleRelations
PreparedTransactiontransaction: uuid (identity) tenant: string actor: string mutations: List<Mutation> created_at: string expires_at: stringstates Prepared; initial Prepared—
Secretreference: Reference (identity) id: uuid owner_subject: string disclosure: Disclosure version: integer labels: Map<string, string> value: bytes created_at: string updated_at: stringstates Active, Revoked; initial Active revoke: Active or Revoked → Revoked replace: Active or Revoked → Active—

Source: generated by secrets-docs from spec/ (ess specify compile); do not edit

04 / Status

Version 0.6.0. Here is what exists.

Shipped means in the released service today. Planned means specified and on the plan only.

Shipped · runs today

As of 2026-10-05 · Secrets' status record, maintained in the repository and checked against main