diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-21 10:14:24 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-21 10:14:24 +0800 |
| commit | 958e24b0fd08e4bc92656964e832606dbf7d3fa3 (patch) | |
| tree | 01606b1c010fecc4d3379cbc796c100c32363bac /src/SomhairlesDream.Server/ArtifactRunCoordinator.fs | |
| parent | 07d6690b9b9de7db7debe25e8e3def5c0d68bb26 (diff) | |
| download | somhairles-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.fs | 24 |
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 |
