carlos / platform Public

test(release): pin the trash marker's key path and wire shape

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Paul Campbell 09f474c7528ba4dfe322c9d9edafd3bcb28cb0ba parent 4645a9e
1 file changed, +27 −0
  • internal/release/trash_test.go +27 −0
diff --git a/internal/release/trash_test.go b/internal/release/trash_test.go
index 7cd2dceaf..104017c04 100644
--- a/internal/release/trash_test.go
+++ b/internal/release/trash_test.go
@@ -11,6 +11,12 @@ func TestTrashAppRoundTrip(t *testing.T) {
s := NewDirStore(t.TempDir())
now := time.Date(2026, 8, 4, 16, 0, 0, 0, time.UTC)
+ // The key path is a wire contract: later tasks (route hiding, the purge
+ // pass) string-match "deleted.json" independently of this package.
+ if got, want := AppTombstoneKey("bab", "derp"), "apps/bab/derp/deleted.json"; got != want {
+ t.Fatalf("AppTombstoneKey(bab, derp) = %q, want %q", got, want)
+ }
+
// Absent: (nil, nil), not an error.
if tomb, err := ReadAppTombstone(ctx, s, "bab", "derp"); err != nil || tomb != nil {
t.Fatalf("absent marker: got %v, %v; want nil, nil", tomb, err)
@@ -45,6 +51,27 @@ func TestTrashAppRoundTrip(t *testing.T) {
}
}
+// TestReadAppTombstoneParsesWireShape pins the JSON tags against the spec's
+// exact example body — a struct-tag typo would still fail the negative
+// tests above (any parse error refuses), so only a positive round-trip on
+// literal bytes catches it.
+func TestReadAppTombstoneParsesWireShape(t *testing.T) {
+ ctx := context.Background()
+ s := NewDirStore(t.TempDir())
+ body := []byte(`{"schema":1,"account":"bab","app":"derp","deleted_at":"2026-08-04T16:00:00Z","actor":"paul@keymail.dev"}`)
+ if _, err := s.Put(ctx, AppTombstoneKey("bab", "derp"), body, ""); err != nil {
+ t.Fatal(err)
+ }
+ tomb, err := ReadAppTombstone(ctx, s, "bab", "derp")
+ if err != nil || tomb == nil {
+ t.Fatalf("ReadAppTombstone: got %v, %v", tomb, err)
+ }
+ want := time.Date(2026, 8, 4, 16, 0, 0, 0, time.UTC)
+ if tomb.Account != "bab" || tomb.App != "derp" || tomb.Actor != "paul@keymail.dev" || !tomb.DeletedAt.Equal(want) {
+ t.Fatalf("tombstone fields: %+v", tomb)
+ }
+}
+
func TestReadAppTombstoneRefusesDisagreement(t *testing.T) {
ctx := context.Background()
s := NewDirStore(t.TempDir())