feat(mesh): ConfigSource/ConfigServe options + validator (Phase 3 dark switch)

ConfigSource:Mode = Direct (default, read central SQL) | FetchAndCache (fetch
the artifact from central over gRPC, read LocalDb). The validator fails host
start on a FetchAndCache shape that cannot fetch — no endpoints, a non-http(s)
endpoint, no shared key, or a non-positive timeout — because each otherwise
surfaces as a silent absence (a deploy that never applies). ConfigServe (the
central serve surface) takes a plain Configure: a 0 port is a valid "disabled".

Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
This commit is contained in:
Joseph Doherty
2026-07-22 19:03:39 -04:00
parent b3cb0f4a54
commit 9d1e60c00c
4 changed files with 278 additions and 0 deletions
@@ -40,6 +40,14 @@ public static class ServiceCollectionExtensions
services.AddValidatedOptions<MeshTransportOptions, MeshTransportOptionsValidator>(
configuration, MeshTransportOptions.SectionName);
// Per-cluster mesh Phase 3: where a driver reads its config (Direct SQL, or fetch-and-cache
// over gRPC). Validated at startup for the same reason — a FetchAndCache node with no endpoint
// or no key produces silence, not an error. ConfigServe (the central serve surface) needs no
// cross-field validation: a 0 port is a legitimate "disabled", so a plain Configure suffices.
services.AddValidatedOptions<ConfigSourceOptions, ConfigSourceOptionsValidator>(
configuration, ConfigSourceOptions.SectionName);
services.Configure<ConfigServeOptions>(configuration.GetSection(ConfigServeOptions.SectionName));
services.AddSingleton<IClusterRoleInfo, ClusterRoleInfo>();
return services;