Secrets management
A secret is the one thing a platform cannot govern by describing. It has to be stored, resolved, handed to exactly one caller, and destroyed, and every step is somewhere it can leak.
System9 runs one secret substrate with pluggable backends, so the sovereignty decision is a configuration choice rather than a product choice.
Where secrets live: your call
| Backend | For |
|---|---|
| Local | Fully in-platform. Nothing external is reachable or required |
| AWS Secrets Manager | An estate already standardised on it |
| AWS Systems Manager Parameter Store | The lighter-weight AWS option |
| Azure Key Vault | |
| GCP Secret Manager |
The same resolution path serves all of them, so an application does not know or care which one a deployment chose, and changing backends is not a rewrite.
For sovereign and air-gapped operation, the local backend is the whole story. Secrets never leave the cell, no external vault has to be reachable, and nothing in the resolution path requires egress. That is the default posture rather than a hardened variant of a cloud-first design.
Addressing a secret
Secrets are addressed by URI rather than by a filesystem path or a backend-specific handle:
s9://secrets/{namespace}/{key}
Some namespaces carry structured, slash-delimited sub-paths rather than one flat key. Identity federation is the worked example, where a provider's OIDC client secret, SAML signing key, LDAP bind password and SCIM token each live under the provider's own sub-path.
Every path segment is validated against a strict character set, so a crafted identifier cannot traverse out of its namespace.
Encryption at rest
Local secrets are envelope-encrypted before they touch disk.
| Layer | Mechanism |
|---|---|
| Key derivation | A per-scope key-encryption-key derived from a master key via HKDF-SHA256 |
| Sealing | A per-blob data-encryption key under one enterprise envelope, carrying a key version and identity as additional authenticated data |
| Cipher | AES-256-GCM |
| Rotation | Built into the envelope, with dedicated key and key-encryption-key rotation paths |
The envelope carrying identity as additional authenticated data is the part worth noticing: a sealed blob is bound to who it belongs to, so a ciphertext lifted from one scope cannot be decrypted under another even with the right key version.
Scopes
Secrets resolve within a scope, and the scope is checked rather than trusted:
- Entity scope, for a principal's own material.
- Workspace scope, so a workspace resolves its own secrets without reaching entity scope.
- Service scope, for platform services.
A scope principal checker enforces that the caller is entitled to the scope it is asking within, so a workspace-scoped resolution cannot quietly widen.
In memory, secrets are handled as secrets
Resolved plaintext is wrapped in a secure buffer with explicit zeroization, so secret material is overwritten when it is no longer needed rather than left for the garbage collector.
Around it sits a bounded, thread-safe cache with a TTL that zeroizes evicted and expired entries automatically. A cache that merely drops its reference leaves the plaintext in memory until something else overwrites the page; this one does not.
The credential never crosses a service boundary
This is the strongest property in the secrets story, and it shows up where you would least expect it: cloud inventory scanning.
A workspace's cloud connector credential lives in the compute secret substrate. A live scan has to resolve that credential and call the provider's APIs. The arrangement is deliberate:
Resolution and the cloud API calls both happen in-process, inside the owning service. Only the enumerated inventory is returned. The credential plaintext never crosses a service boundary.
The enumeration logic is owned by the assessment domain and imported into the service that holds the secret, rather than the secret being shipped to the service that holds the logic. The worker that wanted the inventory receives inventory, and never sees the credential.
That inversion is the whole trick, and it generalises: move the code to the secret, not the secret to the code.
What secrets are actually for
| Use | Example |
|---|---|
| Cloud storage | Credentials for external S3, Azure and GCS buckets backing lakehouse tables |
| Data-platform connectivity | Credentials for federated sources: PostgreSQL, MySQL, SQL Server, BigQuery, Snowflake, Databricks |
| SaaS content | OAuth connections to OneDrive, SharePoint, Google Drive and Dropbox, scoped per workspace and entity |
| Identity federation | OIDC client secrets, SAML signing keys, LDAP bind passwords, SCIM tokens |
| Connectors | Per-connector authentication across the stream connector catalog |
| Model providers | Where a deployment's tier permits a third-party provider at all |
Connection provisioning and scanning are first-class, so a credential is provisioned into the substrate as part of creating a connection rather than pasted somewhere afterward.
Secrets at the edge
An Edge Agent holds its own secret material on the device, and the posture is different because the threat is different: the device may be captured.
The device's own identity key is generated on-device and never traverses the wire. Material at rest is sealed, and zeroize destroys agent keys, revokes certificates and overwrites workflow state, journal and local model weights.
The tactical profile's zeroize is software-only. Where physical capture is in the threat model, pair it with hardware key custody rather than relying on software zeroize alone.
Access is logged
Secret access is recorded to its own audit trail, so "who resolved this credential and when" is answerable. That is separate from, and in addition to, the audit planes covering everything else.
Related
- Key custody and lifecycle, the key hierarchy this roots into.
- Entity credentials, the certificate material issued per principal.
- Interoperability, the external systems these credentials reach.
- Programmatic authentication, the credentials callers present to System9.