Surface.Secrets Design

FROZEN — LEGACY (bootstrap/file material only). As of SPRINT_20260703_004 (S5) this design is frozen. Surface.Secrets remains the mechanism for bootstrap/file secret material only (offline file provider + inline-for-tests). Its own secret:// scheme and the “future approved vault providers” described below are not the path for new secret-bearing features.

New secret-bearing features MUST use the unified secret provider and URL secret references — see ADR-031 (unified secret provider) and ADR-032 (URL secret references + multi-provider routing). Registry pull credentials are resolved through the Integrations catalog and, since SPRINT_20260703_004 (S1), returned to the scanner AEAD-sealed under the shared master-KEK chain (StellaOps.Cryptography.CredentialStore.CredentialAead), not via a Surface.Secrets provider. No code is removed by the freeze; existing file/inline provider behaviour is unchanged.

Status

This design is updated for the current Stella Ops deployment model: Docker Compose, Offline Kit, signed release manifests, and host/service-manager operations.

Kubernetes Secret support is retired from active Stella Ops deployment support. Any remaining source code or tests for Kubernetes secret providers must be handled through docs/implplan/SPRINT_20260501_058_Scanner_kubernetes_surface_retirement.md.

Goals

Surface.Secrets standardises how Scanner, Scheduler, and related services obtain credentials and sensitive material required for surface operations, including registry pull credentials, CAS tokens, manifest signing keys, and TLS material.

Key requirements:

Secret Types

Secret TypeDescriptionExample Consumers
cas-accessRustFS/S3-compatible object storage credentials.Scanner Worker/WebService
registryContainer registry auth.Scanner Worker
attestationDSSE signing key material or transparency tokens.Scanner WebService, Attestor
github-integrationGitHub API token JSON used for code-scanning SARIF upload and alert readback.Scanner WebService
tlsClient TLS certificate material.Scanner Worker

Provider Model

public interface ISurfaceSecretProvider
{
    ValueTask<SurfaceSecretHandle> GetAsync(SurfaceSecretRequest request, CancellationToken ct = default);
}

public sealed record SurfaceSecretRequest(
    string Tenant,
    string Component,
    string SecretType,
    string? Name);

Built-in active providers:

  1. File - loads JSON/YAML files from a directory. The path is derived from root, tenant, component, secret type, and optional name.
  2. Inline - accepts base64 encoded JSON from environment/config for tests only.

Future provider candidates, such as Vault or cloud secret stores, require a separate license/security review and release documentation. (Frozen, S5): do not add new providers here — route new secret-bearing needs through the unified secret provider (ADR-031) and URL secret references (ADR-032) instead.

Configuration

{
  "provider": "file",
  "prefix": "surface-",
  "file": {
    "root": "/etc/stellaops/secrets"
  }
}

Runtime configuration can reference secrets using secret://{secretType}/{name?}. Scanner.Worker resolves each placeholder before analyzer invocation. Missing or unreadable secrets raise typed Worker failures; unresolved placeholders must never reach analyzers.

Security Rules

Offline Support

Offline kits include offline/secrets/manifest.json with tenant, component, secret type, optional name, checksum, and creation metadata. Import scripts map entries into:

<root>/<tenant>/<component>/<secretType>/<name>.json

Validation performs no external network calls.