Surface storage measurement

Scanner’s default surface cache and manifest writer store files on disk. surface-cache is the canonical authority used in manifest URIs; it does not identify a separately provisioned remote bucket for these implementations.

The web role registers volume:scanner-surface-cache under /doctor/scanner-web/checks. Its check ID is doctor.standard.state.size-budget.volume-scanner-surface-cache. The optional budget is Doctor:State:volume:scanner-surface-cache:BudgetBytes. Use a configuration file/provider for this key; the colon-containing state ID cannot be represented faithfully through a shell-safe double-underscore variable. No default budget or new write refusal is introduced.

The measurement uses the same resolved SurfaceCacheOptions.RootDirectory and SurfaceManifestStoreOptions.RootDirectory as the writers. It counts logical file lengths, including incomplete files, and counts overlapping roots once. It does not report filesystem allocation, remote artifacts referenced by a manifest, or an atomic snapshot during concurrent writes. Missing or unreadable directories, linked entries, arithmetic overflow and enumeration limits fail the measurement; Doctor reports Warning with no invented byte total.

Both deployed roles must select SCANNER_SURFACE_CACHE_ROOT=/var/lib/stellaops/surface and mount scanner-surface-cache at that location. A mount alone is insufficient: the worker previously used its default /tmp/stellaops/surface path even with the volume present. Before correcting an existing worker, stop its intake in an approved window, preserve every file under the old root, compare relative paths and SHA-256 values with the destination, and refuse differing collisions. Copy only missing files, verify their bytes, then recreate the worker with the new root and its existing image and analyzer cohort. Do not discard manifests as ordinary expendable cache entries. Keep the preserved source until verification is complete.

Source verified against bd20ac7ec4 under OSM-3: the filesystem tests exercise nested and separate roots, cancellation and missing storage. The registered Doctor check turns Critical above a declared budget and Warning when its root disappears. The live verification receipt records the lossless 101-file worker-root transfer, 102-file aggregate measurement, 401/403/200 controls and eight accepted analyzer probes. Re-verify with tools/scripts/test-targeted-xunit.ps1 -Project src/Scanner/__Tests/StellaOps.Scanner.Surface.FS.Tests/StellaOps.Scanner.Surface.FS.Tests.csproj -Class *SurfaceStorageMeasurementTests* -BuildProjectReferences and compare the authenticated Doctor byte total with the same roots on disk.