feat(sites): record the artifact revision last deployed to a site

Site.ArtifactRevisionHash / ArtifactsDeployedAt (nullable, migration
AddSiteArtifactRevision) so the Sites page can tell whether a site's
system-wide artifacts are current. Not transported. Adds the
GetDeployedRevisionHashesAsync projection for the fleet-wide staleness batch.

Claude-Session: https://claude.ai/code/session_01Y5ef34iUUMjmwnMpL9xgmB
This commit is contained in:
Joseph Doherty
2026-09-14 13:33:59 -04:00
parent 0762d69132
commit dd202e5dde
9 changed files with 2333 additions and 4 deletions
@@ -18,6 +18,18 @@ public class Site
public string? GrpcNodeAAddress { get; set; }
/// <summary>gRPC endpoint for site node B used by the central SiteStreamGrpcClient.</summary>
public string? GrpcNodeBAddress { get; set; }
/// <summary>
/// Revision hash (<c>ArtifactRevisionHashService</c>) of the per-site artifact set last
/// deployed to this site successfully; null = artifacts never deployed. Environment-specific
/// deploy state — deliberately NOT carried by Transport bundles (like <c>Instance.State</c>).
/// </summary>
public string? ArtifactRevisionHash { get; set; }
/// <summary>
/// UTC instant at which the artifact set identified by <see cref="ArtifactRevisionHash"/> was
/// last deployed to this site successfully; null = artifacts never deployed. Environment-specific
/// deploy state — deliberately NOT carried by Transport bundles (like <c>Instance.State</c>).
/// </summary>
public DateTimeOffset? ArtifactsDeployedAt { get; set; }
/// <summary>
/// Initializes a new site with the required name and identifier.