carlos / platform Public

host: contract test — status publish never derives from metrics/ or alerts/

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Paul Campbell 3ada7ce7dffaedb406710bbce3e37bae4dc0548e parent 33df074
1 file changed, +57 −0
  • internal/host/host_test.go +57 −0
diff --git a/internal/host/host_test.go b/internal/host/host_test.go
index 4312df011..d5171d04e 100644
--- a/internal/host/host_test.go
+++ b/internal/host/host_test.go
@@ -2,6 +2,7 @@ package host
import (
"context"
+ "encoding/json"
"net"
"os"
"path/filepath"
@@ -11,6 +12,7 @@ import (
"time"
"github.com/carlosframework/platform/internal/domains"
+ "github.com/carlosframework/platform/internal/metrics"
"github.com/carlosframework/platform/internal/registry"
"github.com/carlosframework/platform/internal/release"
"github.com/carlosframework/platform/internal/status"
@@ -485,3 +487,58 @@ func TestAdoptTimerStateReading(t *testing.T) {
}
func boolPtr(v bool) *bool { return &v }
+
+// TestStatusPublishNeverReadsMetricsPrefixes is the privacy tripwire the
+// monitoring spec commits to: operator-grade needles live under metrics/ and
+// alerts/, and nothing the public status publisher writes may ever be
+// derived from them. Sentinel values planted in metrics objects must not
+// appear anywhere under status/ after a full publish tick.
+func TestStatusPublishNeverReadsMetricsPrefixes(t *testing.T) {
+ ctx := context.Background()
+ reg, err := registry.Open(filepath.Join(t.TempDir(), "registry.db"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ store := release.NewDirStore(t.TempDir())
+ sentinel := 0.987654321
+ chunk := metrics.RawChunk{V: 1, Box: "box-a", Hour: "2026-08-02-10", Samples: []metrics.Sample{
+ {At: time.Now(), Host: metrics.HostSample{CPUFrac: &sentinel}},
+ }}
+ if err := metrics.WriteRaw(ctx, store, chunk); err != nil {
+ t.Fatal(err)
+ }
+
+ // Plant sentinel in alerts/boxes/ as well
+ alertState := metrics.AlertState{
+ V: 1,
+ Box: "box-a",
+ UpdatedAt: time.Now(),
+ Rules: map[string]metrics.RuleState{
+ "disk": {Firing: true, Value: sentinel},
+ },
+ }
+ alertBody, err := json.Marshal(alertState)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if _, err := store.Put(ctx, metrics.AlertKey("box-a"), alertBody, ""); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := statusTick(ctx, store, reg, status.Probes{MachineID: "m"}, true); err != nil {
+ t.Fatal(err)
+ }
+ keys, err := store.List(ctx, "status/")
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, k := range keys {
+ body, _, err := store.Get(ctx, k)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if strings.Contains(string(body), "987654321") {
+ t.Errorf("%s contains the metrics sentinel — the status publisher read a metrics object", k)
+ }
+ }
+}