Surface.Validation Design (Epic: SURFACE-SHARING)

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.

1. Objectives

Surface.Validation provides a shared validator framework to ensure all surface consumers meet configuration and data preconditions before performing work. It prevents subtle runtime errors by failing fast with actionable diagnostics.

2. Core Interfaces

public interface ISurfaceValidator
{
    ValueTask<SurfaceValidationResult> ValidateAsync(SurfaceValidationContext context, CancellationToken ct = default);
}

public sealed record SurfaceValidationContext(
    IServiceProvider Services,
    string ComponentName,
    SurfaceEnvironmentSettings Environment,
    IReadOnlyDictionary<string, object?> Properties)
{
    public static SurfaceValidationContext Create(
        IServiceProvider services,
        string componentName,
        SurfaceEnvironmentSettings environment,
        IReadOnlyDictionary<string, object?>? properties = null);
}

public interface ISurfaceValidatorRunner
{
    ValueTask<SurfaceValidationResult> RunAllAsync(SurfaceValidationContext context, CancellationToken ct = default);
    ValueTask EnsureAsync(SurfaceValidationContext context, CancellationToken ct = default);
}

public sealed record SurfaceValidationIssue(
    string Code,
    string Message,
    SurfaceValidationSeverity Severity,
    string? Hint = null);

Properties carries optional context-specific metadata (e.g., jobId, imageDigest, cache paths) so validators can tailor diagnostics without pulling additional services. Validators register with DI (services.AddSurfaceValidation()). Hosts call ISurfaceValidatorRunner.RunAllAsync() during startup and before workload execution to capture misconfiguration early; EnsureAsync() rethrows when Surface:Validation:ThrowOnFailure=true.

3. Built-in Validators

CodeSeverityDescription
SURFACE_ENV_MISSING_ENDPOINTErrorRaised when SurfaceFsEndpoint absent.
SURFACE_ENV_CACHE_DIR_UNWRITABLEErrorCache root not writable or disk full.
SURFACE_SECRET_MISSINGErrorSecret provider cannot locate required secret type.
SURFACE_SECRET_STALEWarningSecret older than rotation window.
SURFACE_SECRET_FORMAT_INVALIDErrorSecret payload fails schema validation per surface-secrets-schema.md.
SURFACE_FS_ENDPOINT_REACHABILITYErrorHEAD request to Surface.FS endpoint failed.
SURFACE_FS_BUCKET_MISMATCHErrorProvided bucket does not exist / lacks permissions.
SURFACE_FEATURE_UNKNOWNWarningFeature flag not recognised.
SURFACE_TENANT_MISMATCHErrorTenant from environment differs from Authority token tenant.

Validation pipeline stops on the first error (severity Error) unless Surface:Validation:ContinueOnError=true is set (useful for diagnostics mode).

4. Extensibility

Consumers can register custom validators:

services.AddSurfaceValidation(builder =>
    builder.AddValidator<RegistryCredentialsValidator>()
           .AddValidator<RuntimeCacheWarmupValidator>());

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

5. Reporting & Observability

6. Integration Guidelines

7. Testing Strategy

8. Error Handling & Remediation

9. References