seam sweep: compile-time witness for BackupArchiveLister (no version bump)

localapi.BackupArchiveLister is satisfied by a runtime type assertion in
newestArchiveOn; a failed assertion degrades SILENTLY to archiveAbsent, which is
the pre-R-84 in-memory-only behaviour — i.e. the R-84 bug returning with nothing
in any log to say so. There was no compile-time witness anywhere in production
code in either repo.

No defect found: *BackupRunner does satisfy it today, so this is a guard, not a
fix. Verified the guard works — breaking NewestArchiveTime's signature now fails
go build, where before it compiled and vetted clean.

No version bump, no deploy: compile-time only, zero runtime effect.
This commit is contained in:
2026-07-27 18:23:49 +02:00
parent 9842c52853
commit 023655370b
+28
View File
@@ -0,0 +1,28 @@
package main
import (
"gitea.dooplex.hu/admin/felhom-agent/internal/backup"
"gitea.dooplex.hu/admin/felhom-agent/internal/localapi"
)
// COMPILE-TIME WITNESSES for OPTIONAL interfaces that are satisfied by a RUNTIME type assertion.
//
// WHY THIS FILE EXISTS. `localapi.BackupArchiveLister` is asserted at server.go's `newestArchiveOn`
// via `tier.Service.(BackupArchiveLister)`. A failed assertion does not error — it degrades to
// `archiveAbsent`, i.e. the pre-R-84 "ask the in-memory record only" behaviour. That degrade is
// SILENT and it is behaviour-relevant: it is exactly the R-84 bug (a cold store after a restart
// reading as "no backup ever") coming back, with nothing in any log to say so.
//
// The precedent is not hypothetical. During R-88 Part 2 the controller's `quiesceBackend` stopped
// satisfying `quiesce.TieredBackend` when a signature changed, and `go build` AND `go vet` both
// passed — because the interface is only ever asserted at runtime. Every box would have degraded to
// the single-tier path, losing R-82's multi-tier backups, with no error anywhere. It was caught by
// accident.
//
// A witness costs one line and converts that class of failure from a silent production degrade into
// a compile error.
//
// THIS DOES NOT MAKE THE INTERFACE REQUIRED. The optionality is deliberate — it is what lets a
// BackupService without a lister still work. The witness pins the IMPLEMENTATION (this concrete type
// really does satisfy it), not the CONTRACT.
var _ localapi.BackupArchiveLister = (*backup.BackupRunner)(nil)