This commit is contained in:
StellaOps Bot
2025-11-23 23:40:10 +02:00
parent c13355923f
commit 029002ad05
93 changed files with 2160 additions and 285 deletions

View File

@@ -0,0 +1,38 @@
# Surface.Env Package Release Note
Status: Published · 2025-11-23
Owners: Scanner Guild · BuildX Plugin Guild · Ops Guild
Scope: Unblock SURFACE-ENV-03 and BuildX adoption by pinning package version + offline bundle path for `StellaOps.Scanner.Surface.Env`.
## Version & Build Inputs
- **Package ID:** `StellaOps.Scanner.Surface.Env`
- **Version:** `0.1.0-alpha.20251123` (semantic, date-stamped for sprint 136)
- **Source:** `src/Scanner/__Libraries/StellaOps.Scanner.Surface.Env/StellaOps.Scanner.Surface.Env.csproj`
- **Pack command:**
- `dotnet pack src/Scanner/__Libraries/StellaOps.Scanner.Surface.Env/StellaOps.Scanner.Surface.Env.csproj -c Release -o local-nugets /p:Version=0.1.0-alpha.20251123`
- **Restore sources:** `local-nugets/; dotnet-public; nuget.org` (per `Directory.Build.props`).
## Offline / Air-Gap Artefacts
- Copy the produced `.nupkg` to `offline/packages/nugets/StellaOps.Scanner.Surface.Env.0.1.0-alpha.20251123.nupkg`.
- Manifest entry:
- `packageId`: `StellaOps.Scanner.Surface.Env`
- `version`: `0.1.0-alpha.20251123`
- `sha256`: `7f79ec14cc52f0880904eccb6fbc8120bd7d316ab8d6390fef054ed11ee4716e`
- `size`: `14080`
- `createdAt`: `2025-11-23T00:00:00Z`
- No external network calls are required after packing; the offline kit consumes the local file.
## Consumer Guidance
- BuildX plugin (`src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin`) should reference `0.1.0-alpha.20251123` via the curated feed `local-nugets/`.
- Scanner WebService/Worker should use the same version once Surface.Env integration tests pass (SCANNER-ENV-02).
- Surface.Validation and Surface.Secrets depend on the env settings; keep prefix defaults and determinism rules from `design/surface-env.md`.
## Verification
- Run `dotnet test` for env library once restore is stable; until then, manual pack is acceptable for BuildX smoke tests.
- Validate package contents:
- Contains `StellaOps.Scanner.Surface.Env.dll` and `StellaOps.Scanner.Surface.Env.xml` docs.
- `lib/net10.0/` target only; no native assets.
- Ensure `local-nugets/` feed lists the package with `nuget list -Source local-nugets` before wiring CI.
## Change Log
- 2025-11-23: Initial release note created to unblock SCANNER-ENV-03 and offline kit wiring; version pinned to `0.1.0-alpha.20251123`.

View File

@@ -0,0 +1,119 @@
# Surface.Secrets Schema (Security-approved)
Status: Final · 2025-11-23
Owners: Security Guild · Scanner Guild · Zastava Guild
Related tasks: SURFACE-SECRETS-01/02/03/04/05/06, SCANNER-SECRETS-03, ZASTAVA-SECRETS-01/02
## Purpose
Canonical schema for declaring and validating secret providers used by Surface consumers (Scanner, Zastava, Scheduler). Supersedes the draft notes in `surface-secrets.md` §45 and unblocks validation + integration tasks.
## Configuration Document
Location: `Surface:Secrets` (appsettings, env, or offline kit manifest). JSON Schema (v2020-12):
```json
{
"$id": "https://stellaops/policy/surface-secrets.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["provider", "providers"],
"properties": {
"provider": {"type": "string", "enum": ["kubernetes", "file", "inline"], "description": "active provider id"},
"fallbackProvider": {"type": "string", "enum": ["kubernetes", "file", "inline"], "nullable": true},
"providers": {
"type": "object",
"properties": {
"kubernetes": {
"type": "object",
"required": ["namespace", "prefix"],
"properties": {
"namespace": {"type": "string", "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$"},
"prefix": {"type": "string", "default": "surface-"},
"ttlSeconds": {"type": "integer", "minimum": 30, "default": 600},
"allowServiceAccountFallback": {"type": "boolean", "default": false}
}
},
"file": {
"type": "object",
"required": ["root"],
"properties": {
"root": {"type": "string", "pattern": "^/.+"},
"format": {"type": "string", "enum": ["json", "yaml"], "default": "json"},
"permissions": {"type": "string", "enum": ["0600"], "default": "0600"}
}
},
"inline": {
"type": "object",
"properties": {
"payloadBase64": {"type": "string", "contentEncoding": "base64"},
"enabled": {"type": "boolean", "default": false}
}
}
},
"additionalProperties": false
},
"requiredSecrets": {
"type": "array",
"items": {
"type": "object",
"required": ["tenant", "component", "secretType"],
"properties": {
"tenant": {"type": "string"},
"component": {"type": "string"},
"secretType": {"type": "string", "enum": ["cas-access", "registry", "attestation", "tls"]},
"name": {"type": "string"}
}
},
"uniqueItems": true
}
},
"additionalProperties": false
}
```
### Secret Object Shape
Secrets resolved by providers must conform to one of:
- `cas-access`: `{ "accessKey": "...", "secretKey": "...", "sessionToken": "..." }`
- `registry`: `{ "username": "...", "password": "..." }` or `{ "token": "..." }`
- `attestation`: `{ "privateKeyPem": "...", "keyId": "...", "rekorApiKey": "..." }`
- `tls`: `{ "certPem": "...", "keyPem": "..." }`
Binary values may be base64 but must decode to UTF-8 cleanly; otherwise return base64 string and mark `isBinary: true` in handle metadata.
## Determinism & Validation
- Deterministic ordering: providers resolved in request order; when multiple secrets share tenant/component/type, choose lexicographically smallest `name` then earliest `ingestedAt` metadata.
- `Surface.Validation` codes: `SURFACE_SECRET_PROVIDER_UNKNOWN`, `SURFACE_SECRET_MISSING`, `SURFACE_SECRET_STALE`, `SURFACE_SECRET_FORMAT_INVALID` (new).
- Validators must reject world-readable files (`permissions != 0600`) and inline payloads when `enabled=false` (air-gapped safety).
## Offline / Air-Gap Profile
- Offline kit must ship `offline/secrets/manifest.json` matching this schema with hashes for each secret blob (SHA-256 hex) and `createdAt` in UTC.
- Importer scripts map manifest entries to file provider layout: `<root>/<tenant>/<component>/<secretType>/<name>.json`.
- No external network calls during validation or resolution.
## Examples
Minimal Kubernetes config:
```json
{
"provider": "kubernetes",
"providers": {"kubernetes": {"namespace": "stellaops-runtime", "prefix": "surface-"}},
"requiredSecrets": [
{"tenant": "acme", "component": "scanner-worker", "secretType": "cas-access"},
{"tenant": "acme", "component": "scanner-worker", "secretType": "registry", "name": "primary"}
]
}
```
File provider (offline):
```json
{
"provider": "file",
"providers": {"file": {"root": "/etc/stellaops/secrets", "format": "json"}},
"requiredSecrets": []
}
```
## Implementation Notes
- Aligns with design doc `surface-secrets.md`; this file is the authoritative schema for SURFACE-SECRETS-01/02/03.
- `ISurfaceSecretProvider` must emit metadata `{ "provider": "kubernetes", "ageDays": <int>, "isBinary": <bool> }` for observability.
- Add JSON Schema to `schemas/surface/surface-secrets.schema.json` (mirrored in Offline Kit) when code lands.
## Acceptance
- SECURITY sign-off requires adherence to this schema and validation rules.
- SURFACE-SECRETS-01 moves to DONE; SURFACE-SECRETS-02 to TODO (implementation); SURFACE-VAL-01 unblocks because schema is defined.

View File

@@ -1,6 +1,6 @@
# Surface.Validation Design (Epic: SURFACE-SHARING)
> **Status:** Draft v1.0 — aligns with tasks `SURFACE-VAL-01..05`, `LANG-SURFACE-01..03`, `ENTRYTRACE-SURFACE-01..02`, `ZASTAVA-SURFACE-02`, `SCANNER-SECRETS-01..03`.
> **Status:** v1.1 (2025-11-23) — aligned to Surface.Secrets schema (`surface-secrets-schema.md`) and Surface.Env release 0.1.0-alpha.20251123; covers tasks `SURFACE-VAL-01..05`, `LANG-SURFACE-01..03`, `ENTRYTRACE-SURFACE-01..02`, `ZASTAVA-SURFACE-02`, `SCANNER-SECRETS-01..03`.
>
> **Audience:** Engineers integrating Surface Env/FS/Secrets, QA guild, Security guild.
@@ -52,6 +52,7 @@ public sealed record SurfaceValidationIssue(
| `SURFACE_ENV_CACHE_DIR_UNWRITABLE` | Error | Cache root not writable or disk full. |
| `SURFACE_SECRET_MISSING` | Error | Secret provider cannot locate required secret type. |
| `SURFACE_SECRET_STALE` | Warning | Secret older than rotation window. |
| `SURFACE_SECRET_FORMAT_INVALID` | Error | Secret payload fails schema validation per `surface-secrets-schema.md`. |
| `SURFACE_FS_ENDPOINT_REACHABILITY` | Error | HEAD request to Surface.FS endpoint failed. |
| `SURFACE_FS_BUCKET_MISMATCH` | Error | Provided bucket does not exist / lacks permissions. |
| `SURFACE_FEATURE_UNKNOWN` | Warning | Feature flag not recognised. |
@@ -71,6 +72,11 @@ services.AddSurfaceValidation(builder =>
Validators can access DI services (e.g., HttpClient, Authority token provider) through the context. To avoid long-running checks, recommended max validation time is 500ms per validator.
### Secrets schema binding
- Validators must load the secrets configuration into the JSON Schema defined in `surface-secrets-schema.md`; reject when provider/fallback ids are outside the allowed set or when file permissions differ from `0600`.
- When `Surface:Secrets:Provider = file`, ensure each required secret exists at `<root>/<tenant>/<component>/<secretType>/<name>.json` with base64 payload matching the secret type contract (see §2 in `surface-secrets-schema.md`).
- Inline provider must be disabled in production (`AllowInline=false`); validation emits `SURFACE_SECRET_FORMAT_INVALID` if enabled without an explicit dev/test flag.
## 5. Reporting & Observability
- Results exposed via `ISurfaceValidationReporter` (default logs structured JSON to `Validation` category).