# Surface.Secrets Design (Epic: SURFACE-SHARING) > **Status:** Draft v1.0 — aligns with tasks `SURFACE-SECRETS-01..06`, `SCANNER-SECRETS-01..03`, `ZASTAVA-SECRETS-01..02`, `OPS-SECRETS-01..02`. > > **Audience:** Scanner/Zastava engineers, Security Guild, DevOps/Ops teams. ## 1. Goals Surface.Secrets standardises how Scanner, Zastava, Scheduler, and related services obtain credentials and sensitive material required for surface operations (registry pull secrets, CAS tokens, manifest signing keys). Key requirements: - Consistent, pluggable providers (Kubernetes Secret, file, inline, future vaults). - Deterministic lookup keyed by tenant/component to avoid accidental leakage. - Integration with Surface.Env & Surface.Validation for configuration and pre-flight checks. - Minimal in-memory exposure; secrets wrapped in secure handles with automatic disposal. ## 2. Secret Types | Secret Type | Description | Example Consumers | |-------------|-------------|-------------------| | `cas-access` | Credentials for RustFS/S3 object storage (access key/secret, session token). | Scanner Worker/WebService, Zastava Observer/Webhook | | `registry` | Container registry auth (username/password or token). | Scanner Worker (pulling layers for SBOM) | | `attestation` | DSSE signing key material, Rekor API tokens. | Scanner WebService (delegation), Attestor (future integration) | | `tls` | Client TLS certificates for Surface.FS or other services. | Scanner Worker, Zastava Observer | Additional secret types can be registered via `ISurfaceSecretTypeRegistry`. ## 3. Provider Model ```csharp public interface ISurfaceSecretProvider { ValueTask GetAsync(SurfaceSecretRequest request, CancellationToken ct = default); } public sealed record SurfaceSecretRequest ( string Tenant, string Component, // e.g. "Scanner.Worker" string SecretType, // e.g. "cas-access" string? Name // optional override (e.g., "primary", "mirror-eu") ); ``` ### 3.1 Built-in providers 1. **Kubernetes** – Reads from `Secret` objects. Configuration: - `namespace`: derived from `SCANNER_SURFACE_SECRETS_ROOT` or component override. - Secret name format: `surface-{tenant}-{component}-{secretType}`. - Supports key mapping (e.g., `accessKey`, `secretKey`, `sessionToken`). 2. **File** – Loads JSON/YAML files from a directory (for offline kit, dev). File path derived from root + tenant/component. 3. **Inline** – Accepts base64 encoded JSON from env (useful for tests). ### 3.2 Secret Handle `SurfaceSecretHandle` exposes typed accessors (`AsCredentials()`, `AsTlsCertificate()`) and ensures sensitive data is cleared when disposed. ## 4. Configuration Surface.Env supplies provider configuration (`SecretsProviderConfiguration`). Example: ```json { "provider": "kubernetes", "namespace": "stellaops-runtime", "prefix": "surface-", "fallbackProvider": "file", "file": { "root": "/etc/stellaops/secrets" } } ``` Fallback provider allows offline development (use file provider if K8s secret missing). ## 5. Validation Surface.Validation supplies validators: - `SecretProviderValidator` – ensures provider ID is known; checks required configuration (namespace/root). - `SecretExistenceValidator` – optional check verifying required secret types exist at startup (configurable list). - `SecretRotationValidator` – warns when secrets are older than rotation window (uses metadata stored in provider). Failures produce error codes (`SURFACE_SECRET_PROVIDER_UNKNOWN`, `SURFACE_SECRET_MISSING`, `SURFACE_SECRET_STALE`). ## 6. Security Considerations - Secrets returned as `SecureString`/byte arrays; never log values. - Kubernetes provider caches secrets in-memory with TTL (default 10 minutes) to reduce API calls; cache invalidated when `generation` changes. - File provider enforces permissions (`0600`); rejects world-readable files. - Inline provider meant for tests only; flag `Surface:Secrets:AllowInline` enables it explicitly. ## 7. Offline & Air-Gap Support - Offline kits include `offline/secrets/` with encrypted archive plus manifest file enumerating secret metadata (tenant, component, type, checksum). - Import script decrypts archive using site-specific key and populates file provider root. - Documented workflow lives in `ops/offline-kit/TASKS.md` and associated runbooks. ## 8. Observability - Metrics: `surface_secrets_requests_total{provider,result}`. - Logs: only log secret identifiers, never values. - Traces: `surface.secrets.get` span showing provider latency. ## 9. Testing Strategy - Unit tests per provider with fake backends. - Integration tests in Scanner/Zastava verifying provider selection, fallback, and rotation. - Security tests ensuring secrets aren’t leaked in logs or exceptions. ## 10. Future Enhancements - Support for HashiCorp Vault / AWS Secrets Manager providers. - Built-in DSSE signing key management for Attestor/Signer. - Automatic rotation notifications via Notifier. ## 11. References - `docs/modules/scanner/design/surface-env.md` - `docs/modules/scanner/design/surface-fs.md` - `docs/modules/scanner/design/surface-validation.md` - `docs/modules/airgap/airgap-mode.md`