From 023655370be5fa709e0e38cc6db0ef1d9cc4ef57 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Mon, 27 Jul 2026 18:23:49 +0200 Subject: [PATCH] seam sweep: compile-time witness for BackupArchiveLister (no version bump) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- cmd/felhom-agent/seam_witnesses.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 cmd/felhom-agent/seam_witnesses.go diff --git a/cmd/felhom-agent/seam_witnesses.go b/cmd/felhom-agent/seam_witnesses.go new file mode 100644 index 0000000..cfd928d --- /dev/null +++ b/cmd/felhom-agent/seam_witnesses.go @@ -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)