Skip to content

fix(genesis): carry the entity fields the writer never put on Create - #445

Merged
rickyrombo merged 1 commit into
mainfrom
fix/genesis-writer-create-fields
Aug 6, 2026
Merged

fix(genesis): carry the entity fields the writer never put on Create#445
rickyrombo merged 1 commit into
mainfrom
fix/genesis-writer-create-fields

Conversation

@rickyrombo

Copy link
Copy Markdown
Contributor

Three groups of source columns never reached the chain because genesis-writer did not select them, or because the field only exists on an action the migration never emits.

Tracks and playlists — DDEX rights metadata

The writer selected neither the contributor lists nor the copyright and rights-controller records, so they could not be indexed regardless of what the indexer reads. Added to the Create metadata for both:

tracks playlists
artists artists
resource_contributors ddex_release_ids
indirect_resource_contributors copyright_line
rights_controller producer_copyright_line
copyright_line
producer_copyright_line
parental_warning_type

This is live metadata, not a legacy shape: ddex-processor/src/publishRelease.ts sets every one of these on sdk.tracks.uploadTrack and sdk.albums.uploadAlbum today.

Users — fields the indexer only honors on Update

playlist_library, artist_pick_track_id and allow_ai_attribution are read by user_update.go and ignored by user_create.go. That is correct for production — a live client sets them by editing a profile, never at signup. Among the 292,111 users on a production clone never modified after creation, artist_pick_track_id and allow_ai_attribution appear exactly zero times.

A migrated Create is different in kind: it carries an account's final state, not a signup. So migratedUserCreateHandler now accepts them, via three new fields on userState that the production path leaves at their zero values.

// production — unchanged, still ignores them
insertUserWithState(ctx, params, userState{IsAvailable: true})

TestMigratedUserCreate_CarriesUpdateOnlyProfileFields pins both halves: the migration path writes them, the production path does not.

Why not a follow-up User:Update transaction?

That was the first cut. Emitting them on Create instead keeps 637,899 transactions out of genesis and avoids modelling a profile edit that never happened. The indexer change is confined to the migration override, so production create semantics are untouched either way.

Counts

Excluding jsonb columns holding the literal null — these tables use it heavily in place of SQL NULL, and IS NOT NULL counts them:

tracks     producer_copyright_line 1,459   parental_warning_type 1,459
           artists 1,447   rights_controller 1,404   copyright_line 782
           indirect_resource_contributors 782   resource_contributors 686
playlists  artists 143   ddex_release_ids 143
           copyright_line 28   producer_copyright_line 28
users      playlist_library 622,480   artist_pick_track_id 13,935
           allow_ai_attribution 1,484

JSON null values are dropped automatically: unmarshalJSONB decodes them to a nil interface{}, which omitempty omits.

Out of scope

is_original_available (28,827 tracks) is already emitted by the writer and dropped by the indexer, along with seven track DDEX readers this PR now feeds. That is an indexer-side gap that also affects live uploads, and it ships separately.

🤖 Generated with Claude Code

Three groups of source columns never reached the chain.

Tracks and playlists lost their DDEX rights metadata: the writer selected
neither the contributor lists nor the copyright and rights-controller records,
so they could not be indexed no matter what the indexer read. The DDEX
processor sets all of them on sdk.tracks.uploadTrack and sdk.albums.uploadAlbum
today, so this is live metadata, not a legacy shape.

Users lost playlist_library, artist_pick_track_id and allow_ai_attribution.
These are the awkward case: the indexer honors them only on User:Update,
because a live client only ever sends them by editing a profile. Among the
292,111 users on a production clone never modified after creation,
artist_pick_track_id and allow_ai_attribution appear exactly zero times. A
migrated Create is different in kind -- it carries an account's final state,
not a signup -- so the migration create override now accepts them. The
production create handler still ignores them, and a test pins both halves.

Emitting them on Create rather than as a follow-up User:Update keeps the
genesis 637,899 transactions smaller and avoids modelling an edit that never
happened.

Counts below exclude jsonb columns holding the literal `null`, which these
tables use heavily in place of SQL NULL:

  tracks     producer_copyright_line 1,459  parental_warning_type 1,459
             artists 1,447  rights_controller 1,404  copyright_line 782
             indirect_resource_contributors 782  resource_contributors 686
  playlists  artists 143  ddex_release_ids 143
             copyright_line 28  producer_copyright_line 28
  users      playlist_library 622,480  artist_pick_track_id 13,935
             allow_ai_attribution 1,484

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@rickyrombo
rickyrombo merged commit 947c053 into main Aug 6, 2026
5 checks passed
@rickyrombo
rickyrombo deleted the fix/genesis-writer-create-fields branch August 6, 2026 09:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant