Split out of #560's review, where changing one field drive-by proved to be the wrong venue.
The hand-written Go wrapper surface is inconsistent about how it types optional timestamps:
| Type |
Field |
Go type |
Card |
CompletedAt |
*time.Time |
TimelineEvent |
CreatedAt, UpdatedAt |
*time.Time |
EverythingFile |
CreatedAt, UpdatedAt |
*time.Time |
HillChart |
UpdatedAt |
time.Time |
All four schemas mark the field optional, so HillChart.UpdatedAt is the outlier: an absent updated_at surfaces as 0001-01-01T00:00:00Z, indistinguishable from a real (if implausible) value. Its omitempty is also inert — encoding/json never omits a zero time.Time, so the key is always emitted on re-marshal.
Why this was NOT fixed in #560, and why it needs its own PR: flipping the field to *time.Time is a silent breaking change for callers. hc.UpdatedAt.IsZero() still compiles — Go auto-dereferences the pointer receiver — and then panics at runtime on nil. Verified with a standalone repro. A change with that failure mode needs to be deliberate, announced in release notes, and ideally landed with the other wrapper-surface breaks rather than smuggled into a generated-types PR.
Options to decide:
- Make
HillChart.UpdatedAt a *time.Time (consistent with the other three; breaking, needs a release note).
- Leave it value-typed and accept that absent reads as the zero time, documenting it — but then the
omitempty tag should go, since it never fires.
Worth resolving alongside any future audit of value-typed optional fields on the hand-written surface generally; this issue is the timestamp instance, not necessarily the whole class.
🤖 Drafted with agent assistance; filed by @jeremy.
Split out of #560's review, where changing one field drive-by proved to be the wrong venue.
The hand-written Go wrapper surface is inconsistent about how it types optional timestamps:
CardCompletedAt*time.TimeTimelineEventCreatedAt,UpdatedAt*time.TimeEverythingFileCreatedAt,UpdatedAt*time.TimeHillChartUpdatedAttime.TimeAll four schemas mark the field optional, so
HillChart.UpdatedAtis the outlier: an absentupdated_atsurfaces as0001-01-01T00:00:00Z, indistinguishable from a real (if implausible) value. Itsomitemptyis also inert —encoding/jsonnever omits a zerotime.Time, so the key is always emitted on re-marshal.Why this was NOT fixed in #560, and why it needs its own PR: flipping the field to
*time.Timeis a silent breaking change for callers.hc.UpdatedAt.IsZero()still compiles — Go auto-dereferences the pointer receiver — and then panics at runtime on nil. Verified with a standalone repro. A change with that failure mode needs to be deliberate, announced in release notes, and ideally landed with the other wrapper-surface breaks rather than smuggled into a generated-types PR.Options to decide:
HillChart.UpdatedAta*time.Time(consistent with the other three; breaking, needs a release note).omitemptytag should go, since it never fires.Worth resolving alongside any future audit of value-typed optional fields on the hand-written surface generally; this issue is the timestamp instance, not necessarily the whole class.
🤖 Drafted with agent assistance; filed by @jeremy.