fix(deployment): pending-updates tick uses a slim instance projection, hash-only flatten, one untracked mismatch snapshot read and a per-tick secret lookup memo (review 2026-10-21 04/P2)

This commit is contained in:
Joseph Doherty
2026-10-22 06:39:45 -04:00
parent 971a9886b8
commit df67fabe68
17 changed files with 443 additions and 128 deletions
@@ -464,12 +464,17 @@ cadence, agreeing exactly with the per-instance Topology badge
- All the flattens share **one `FlattenSession`** for the batch, so a template
chain used by N instances is walked once — the same trick `DeploySiteAsync`
uses.
uses — and each is **hash-only** (`IFlatteningPipeline.ComputeRevisionHashAsync`):
no structural/semantic validation and none of the shared-script / schema-library
loads that feed it, since staleness only ever compares the hash (identical to
`FlattenAndValidateAsync`'s `RevisionHash`). `StaleInstanceProbe` uses the same
entry point.
- The deployed side is read as the `(InstanceId, RevisionHash)` **projection**
(`IDeploymentManagerRepository.GetDeployedRevisionHashesAsync`), never the fat
`ConfigurationJson` for the whole fleet.
- **Mismatch-only normalisation**: only when the projected hash disagrees with
the re-flatten is the full `DeployedConfigSnapshot` read and the I-1 List-value
the re-flatten is the full `DeployedConfigSnapshot` read — in **one untracked
batch** for every mismatched instance — and the I-1 List-value
normalisation applied (see *Deployed vs. Template-Derived State* above) — the
same normalisation `GetDeploymentComparisonAsync` applies, so the aggregate
never disagrees with the Topology badge on an old-form List snapshot, without
@@ -491,7 +496,11 @@ cadence, agreeing exactly with the per-instance Topology badge
`ArtifactsDeployedAt`, `DeployedInstanceCount`, `StaleInstanceCount`,
`UnknownInstanceCount`) and fleet totals `StaleInstanceCount` /
`StaleArtifactSiteCount`. Only instances with a deployed snapshot (`State !=
NotDeployed`, the same gate Topology uses) are evaluated. **`NeverDeployed` is
NotDeployed`, the same gate Topology uses) are evaluated; the instance list is a
slim untracked projection (`GetDeployedInstanceSummariesAsync`: id, site, state —
no override collections), and `ComputeCurrentArtifactHashesAsync` reads each
referenced secret from the central store once per evaluation, however many sites
reference it. **`NeverDeployed` is
deliberately not a pending update** — a freshly-created site the operator has not
gotten to yet has nothing drifted, so it is surfaced on the Sites page but never
counted toward the fleet totals or the rail indicator's badge count. Nothing in