docs(mesh): Phase 3 plan — config fetch-and-cache from central (gRPC + shared key)

Eleven tasks. User decisions baked in: gRPC fetch RPC (not token-gated HTTP),
shared node bearer key (not a per-deployment token, so no migration and
DispatchDeployment is unchanged), a ConfigSource:Mode dark switch (Direct
default), both pair nodes fetch (no Primary gating). Header carries the five
recon facts and the Phase 3/4 boundary (config READS only; the NodeDeploymentState
write, DbHealthProbe and EfAlarmConditionStateStore stay for Phase 4).

Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
This commit is contained in:
Joseph Doherty
2026-07-22 19:00:36 -04:00
parent 6eaa81cae7
commit b3cb0f4a54
2 changed files with 561 additions and 0 deletions
@@ -0,0 +1,88 @@
{
"planPath": "docs/plans/2026-07-22-mesh-phase3-config-fetch-and-cache.md",
"note": "Per-cluster mesh Phase 3. Decisions pre-made by the user: gRPC fetch RPC (NOT token-gated HTTP); shared node key (NOT per-deployment token, so no migration and DispatchDeployment is UNCHANGED); config-flagged dark switch ConfigSource:Mode=Direct default; both pair nodes fetch (no Primary gating). Five recon facts + the phase-boundary rule (Phase 3 = config READS only; NodeDeploymentState write / DbHealthProbe / EfAlarmConditionStateStore stay for Phase 4) are in the plan header. RevisionHash == SHA-256(blob) is load-bearing for fetch verification.",
"tasks": [
{
"id": 0,
"subject": "Task 0: ConfigSource/ConfigServe options + validator + registration",
"status": "pending",
"classification": "small",
"parallelizableWith": [1]
},
{
"id": 1,
"subject": "Task 1: deployment_artifact.v1 proto + first in-repo Grpc.Tools codegen",
"status": "pending",
"classification": "standard",
"parallelizableWith": [0]
},
{
"id": 2,
"subject": "Task 2: central DeploymentArtifactService — stream sealed artifact, NotFound-hide the rest",
"status": "pending",
"classification": "standard",
"blockedBy": [1],
"parallelizableWith": [4]
},
{
"id": 3,
"subject": "Task 3: config-serve auth interceptor + dedicated h2c listener wiring",
"status": "pending",
"classification": "high-risk",
"blockedBy": [0, 2]
},
{
"id": 4,
"subject": "Task 4: node gRPC artifact fetcher — SHA-verified reassembly, endpoint failover, null-on-any-failure",
"status": "pending",
"classification": "standard",
"blockedBy": [1],
"parallelizableWith": [2]
},
{
"id": 5,
"subject": "Task 5: FetchAndCache apply path — fetch->cache->apply-from-bytes, null=apply-failure",
"status": "pending",
"classification": "high-risk",
"blockedBy": [4]
},
{
"id": 6,
"subject": "Task 6: FetchAndCache bootstrap from the LocalDb pointer; no driver-side config SQL read",
"status": "pending",
"classification": "high-risk",
"blockedBy": [5]
},
{
"id": 7,
"subject": "Task 7: #485 empty/corrupt/mismatch coverage on the FetchAndCache paths",
"status": "pending",
"classification": "high-risk",
"blockedBy": [6]
},
{
"id": 8,
"subject": "Task 8: real two-Host gRPC artifact-fetch boundary test + wrong-key falsifiability control",
"status": "pending",
"classification": "high-risk",
"blockedBy": [3, 4],
"parallelizableWith": [9]
},
{
"id": 9,
"subject": "Task 9: docker-dev rig config + docs + program-plan flip",
"status": "pending",
"classification": "small",
"blockedBy": [5],
"parallelizableWith": [8]
},
{
"id": 10,
"subject": "Task 10: live gate on docker-dev (site nodes -> FetchAndCache; step 4 = stop central SQL mid-fetch = the headline gate)",
"status": "pending",
"classification": "high-risk",
"blockedBy": [8, 9]
}
],
"lastUpdated": "2026-07-22T23:30:00Z"
}