summaryrefslogtreecommitdiff
path: root/src/SomhairlesDream.Server/ArtifactRunCoordinator.fs
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-21 10:14:24 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-21 10:14:24 +0800
commit958e24b0fd08e4bc92656964e832606dbf7d3fa3 (patch)
tree01606b1c010fecc4d3379cbc796c100c32363bac /src/SomhairlesDream.Server/ArtifactRunCoordinator.fs
parent07d6690b9b9de7db7debe25e8e3def5c0d68bb26 (diff)
downloadsomhairles-dream-fsharp-958e24b0fd08e4bc92656964e832606dbf7d3fa3.tar.gz
feat(boot): surface pre-published probe replay on landing page
- boot loads the completed run from /api/artifacts/manifest and renders its latest checkpoint with concrete build-review labels (no fake unknown-state wording); offline fallback still shows the honest placeholder - artifact manifest/steps endpoints now fall back to disk when a completed run has no in-memory registry entry, keeping pre-published history browsable after a service restart (digest-verified, .glb-only / steps/ / logs/ rejected) - driver: heritage flows pin heritage ids explicitly; new checks for the boot probe replay and its labels; 72/72 green with zero console errors
Diffstat (limited to 'src/SomhairlesDream.Server/ArtifactRunCoordinator.fs')
-rw-r--r--src/SomhairlesDream.Server/ArtifactRunCoordinator.fs24
1 files changed, 22 insertions, 2 deletions
diff --git a/src/SomhairlesDream.Server/ArtifactRunCoordinator.fs b/src/SomhairlesDream.Server/ArtifactRunCoordinator.fs
index 07ac984..51a4fcd 100644
--- a/src/SomhairlesDream.Server/ArtifactRunCoordinator.fs
+++ b/src/SomhairlesDream.Server/ArtifactRunCoordinator.fs
@@ -261,7 +261,9 @@ type ArtifactRunCoordinator(
member _.Manifest(projectId: string, runId: string) : Result<ArtifactManifest, ArtifactLookupError> =
match registry.TryFind(projectId, runId) with
- | None -> Error RunNotFound
+ // Pre-published historical runs persist on disk after restarts; serve
+ // them from the verified manifest when no live registry entry exists.
+ | None -> verifiedManifest projectId runId
| Some store ->
let snapshot = store.Observe(clock ())
@@ -293,7 +295,25 @@ type ArtifactRunCoordinator(
member _.StepArtifact(projectId: string, runId: string, relativePath: string) : Result<ArtifactFile, ArtifactLookupError> =
match registry.TryFind(projectId, runId) with
- | None -> Error RunNotFound
+ // Disk fallback keeps pre-published historical checkpoints reachable
+ // for boot replay after a service restart; only .glb step artifacts
+ // under steps/ are ever served, digest-verified against the manifest.
+ | None ->
+ match safeArtifactPath (runDirectory projectId runId) relativePath with
+ | Error message -> Error(InvalidArtifactPath message)
+ | Ok(_, normalized) when not (normalized.EndsWith(".glb", StringComparison.OrdinalIgnoreCase)) ->
+ Error(InvalidArtifactPath "step artifacts must be .glb files")
+ | Ok(_, normalized) when not (normalized.StartsWith("steps/", StringComparison.Ordinal)) ->
+ Error(InvalidArtifactPath "step artifacts must live under steps/")
+ | Ok(fullPath, normalized) ->
+ let digest =
+ match rejectLinks fullPath with
+ | Error message -> Error(InvalidArtifactPath message)
+ | Ok () -> completedDigest projectId runId normalized
+
+ match digest with
+ | Error lookupError -> Error lookupError
+ | Ok(sha256, bytes) -> openValidated fullPath normalized sha256 bytes
| Some store ->
let directory = runDirectory projectId runId