provision: SidecarRecord.CreatedAt is time.Time, not string
2 files changed,
+39
−12
internal/provision/sidecar.go+12 −12internal/provision/sidecar_test.go+27 −0
diff --git a/internal/provision/sidecar.go b/internal/provision/sidecar.go| index 474764e9a..96bff9b64 100644 |
| --- a/internal/provision/sidecar.go |
| +++ b/internal/provision/sidecar.go |
| @@ -67,18 +67,18 @@ type SidecarManifest struct { |
| // identity is never guessed at, the same discipline GetRecord applies to |
| // instances. |
| type SidecarRecord struct { |
| - Schema int `json:"schema"` // 1 |
| - Name string `json:"name"` |
| - Host string `json:"host"` |
| - App string `json:"app"` |
| - Account string `json:"account"` |
| - Pool string `json:"pool,omitempty"` |
| - Region string `json:"region,omitempty"` |
| - Channel string `json:"channel"` |
| - Placement string `json:"placement,omitempty"` |
| - Environment string `json:"environment,omitempty"` |
| - CreatedAt string `json:"created_at,omitempty"` |
| - CreatedBy string `json:"created_by,omitempty"` |
| + Schema int `json:"schema"` // 1 |
| + Name string `json:"name"` |
| + Host string `json:"host"` |
| + App string `json:"app"` |
| + Account string `json:"account"` |
| + Pool string `json:"pool,omitempty"` |
| + Region string `json:"region,omitempty"` |
| + Channel string `json:"channel"` |
| + Placement string `json:"placement,omitempty"` |
| + Environment string `json:"environment,omitempty"` |
| + CreatedAt time.Time `json:"created_at"` |
| + CreatedBy string `json:"created_by,omitempty"` |
| } |
| // SidecarHost builds a sidecar's synthetic host. It is the registry key, the |
diff --git a/internal/provision/sidecar_test.go b/internal/provision/sidecar_test.go| index 813e6df0c..42232d83d 100644 |
| --- a/internal/provision/sidecar_test.go |
| +++ b/internal/provision/sidecar_test.go |
| @@ -72,6 +72,33 @@ func TestCreateSidecarRecordIsCreateOnly(t *testing.T) { |
| } |
| } |
| +func TestCreateSidecarRecordRoundTripsCreatedAt(t *testing.T) { |
| + ctx := context.Background() |
| + s := dirStore(t) |
| + want := time.Date(2026, 8, 17, 23, 0, 0, 0, time.UTC) |
| + rec := SidecarRecord{ |
| + Schema: 1, Name: "bot-acme", Host: SidecarHost("bot-acme", "eleven", "bdm"), |
| + App: "eleven", Account: "bdm", Channel: "stable", CreatedAt: want, |
| + } |
| + if err := CreateSidecarRecord(ctx, s, rec); err != nil { |
| + t.Fatalf("create: %v", err) |
| + } |
| + got, err := GetSidecarRecord(ctx, s, "bdm", "eleven", "bot-acme") |
| + if err != nil { |
| + t.Fatalf("get: %v", err) |
| + } |
| + // .Equal, not ==: a struct comparison would fail on the monotonic-clock |
| + // reading time.Now() carries and json round-trips never preserve, and |
| + // .UTC() side-steps any location difference too — the store only owes |
| + // us the same instant back, not the same in-memory representation of it. |
| + if !got.CreatedAt.Equal(want) { |
| + t.Fatalf("CreatedAt round-trip = %v, want %v", got.CreatedAt, want) |
| + } |
| + if got.CreatedAt.UTC().Format(time.RFC3339) != "2026-08-17T23:00:00Z" { |
| + t.Fatalf("CreatedAt wire format = %v, want RFC3339 like the spec's example", got.CreatedAt.UTC().Format(time.RFC3339)) |
| + } |
| +} |
| + |
| func TestGetSidecarRecordRefusesRecordThatLiesAboutItsPath(t *testing.T) { |
| ctx := context.Background() |
| s := dirStore(t) |