tr
TryGhost
GitHub
Ghost
Workspace
GitHub
CI Pipeline Executions
Filtered
Runs
Demo
Insights
Compare tasks
Analytics
Sign in
Toggle sidebar
Overview
⌘K
Ghost
Loading workspace stats
Loading workspace insights...
Statistics interval
7 days
30 days
Latest CI Pipeline Executions
Status
Fix filter
Filter
Fuzzy
Filter range
Sort by
Sort by
Start time
Sort ascending
Sort descending
Failed
30305
a9f08f18 Changed a value's writer to name a namespace its id resolves in Who wrote a member custom field value was declared twice, as a constant that guarded against typos and as a Zod object that accepted any string with any id, so the pair was free to drift and a writer could name a namespace nothing could resolve it in. One discriminated union now says which writers exist and which of them carries an id: a user, an integration and a binding each resolve to a row, and an import resolves to nothing, which makes it the only writer whose id is null. The stored type follows the rule and becomes required, since it is what makes the id resolvable at all, while the id stays nullable for that one writer; values written before the columns existed name a writer nobody can recover, so the migration drops them rather than invent one, the feature being behind a private flag with no released data. Editing a member through the Admin API now refuses a write it cannot attribute rather than storing a user with no identity. ref https://linear.app/ghost/issue/BER-3872 Claude-Session: https://claude.ai/code/session_018jPEJMYLoUzNvYbdxWb3dY
by Rob Lester
R
Succeeded
30305
f25890d2 Changed the import's writer port to take the shared writer type The composition root restated the writer's shape inline rather than naming the type the values service exports, and a port that restates a shape it builds a value against is a place for the two to drift apart quietly: method parameters are bivariant, so a writer that grew a field would still satisfy the port and the mismatch would surface nowhere. The plan stays opaque, because the import only ferries one; the writer does not, because the import constructs it. Claude-Session: https://claude.ai/code/session_018jPEJMYLoUzNvYbdxWb3dY
by Rob Lester
R
Succeeded
30305
1188efd8 Changed the import's writer port to take the shared writer type The composition root restated the writer's shape inline rather than naming the type the values service exports, and a port that restates a shape it builds a value against is a place for the two to drift apart quietly: method parameters are bivariant, so a writer that grew a field would still satisfy the port and the mismatch would surface nowhere. The plan stays opaque, because the import only ferries one; the writer does not, because the import constructs it. Claude-Session: https://claude.ai/code/session_018jPEJMYLoUzNvYbdxWb3dY
by Rob Lester
R
Failed
30305
04b7588d Added a record of who wrote each member custom field value A member's custom field values could be written by a person editing them in admin, by an import reading a file, and soon by things collecting data on Ghost's behalf. Nothing said which, so a value that looked wrong could not be traced to whatever put it there, and a value someone typed could not be told apart from one a machine supplied. Every write now names its writer as a type and an id, shaped the way the activity log records an actor. It is required at every call site and has no default, so a new writer has to say what it is rather than quietly inheriting the identity of whichever was written first. There is no foreign key, because provenance has to outlive its cause: that a value arrived through some route stays true after that route is deleted. It cannot be reconstructed after the fact, which is why it is recorded now, before anything reads it. ref https://linear.app/ghost/issue/BER-3872
by Rob Lester
R
Failed
30305
04b7588d Added a record of who wrote each member custom field value A member's custom field values could be written by a person editing them in admin, by an import reading a file, and soon by things collecting data on Ghost's behalf. Nothing said which, so a value that looked wrong could not be traced to whatever put it there, and a value someone typed could not be told apart from one a machine supplied. Every write now names its writer as a type and an id, shaped the way the activity log records an actor. It is required at every call site and has no default, so a new writer has to say what it is rather than quietly inheriting the identity of whichever was written first. There is no foreign key, because provenance has to outlive its cause: that a value arrived through some route stays true after that route is deleted. It cannot be reconstructed after the fact, which is why it is recorded now, before anything reads it. ref https://linear.app/ghost/issue/BER-3872
by Rob Lester
R
Previous
Next