Story: Book codegen drift remediation
Table of Contents
This page documents a story in Sprint 23. It captures the goal, current status, acceptance criteria, and the tasks that compose it.
Goal
Get book, book_status, and regulatory_book_type onto a clean, fully-regenerated, end-to-end-tested codegen baseline, then migrate book to composite-entity versioning and re-verify — so the new-work tasks parked in Book data model cleanup (book_purpose_type, ledger_feed_type, is_sweepable, Wash risk-book link, child-entity toolbar buttons) build on solid ground rather than compounding existing drift.
Discovered via compass codegen entity show: book has almost no ✅
files (nearly every layer stale against current templates) despite
being fully codegen-synced as recently as PR #1449 (Sprint 22,
"Commission: book") — the templates themselves have evolved since
(composite-entity versioning support, NATS event registrars, a Qt
client-model bug fix, license-header format). That same PR's history
is a cautionary tale worth repeating here: its first regeneration
attempt silently dropped book's 5 insert-trigger validations (soft FKs
on parent_portfolio_id/party_id/owner_unit_id; value checks on
ledger_ccy/book_status) because book.org lacked * Foreign keys=/=*
Insert trigger sections at the time — caught only by 3 independent PR
review bot passes, not by the regen itself.
Status
| Field | Value |
|---|---|
| State | DONE |
| Parent sprint | Sprint 23 |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-07-12 |
Acceptance
- book, book_status, and regulatory_book_type show all-✅ in
compass codegen entity show(fully regenerated against current templates). - The 5 insert-trigger validations identified in PR #1449 (and any others found stale) are confirmed present in the regenerated SQL — via paste blocks or variability knobs in the .org models, not hand-patched post-generation.
- book builds cleanly on the configured preset; end-to-end manual test (login, list, add, edit, save, rename, history) passes with no regressions.
- Portfolio/Book are migrated to composite-entity versioning per Temporal Composite Entity Versioning: Target State (Portfolio is the composite parent, Book the child via parent_portfolio_id — not book_status/regulatory_book_type, which are enum-like FK attributes, not composite children), regenerated, and re-tested end to end.
- Book data model cleanup's remaining new-work tasks are unblocked.
Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|
| Regenerate book_status as a drift canary | DONE | 2026-07-11 | 2026-07-11 | Regenerated and manually verified; found and fixed 2 real bugs (missing has_change_reason_cache, stale TradingPlugin.cpp call site) beyond the mechanical regen. |
| Regenerate regulatory_book_type | DONE | 2026-07-12 | 2026-07-12 | Regenerated (had the same missing has_change_reason_cache gap as book_status, fixed proactively this time). Manual QA: all 6 steps PASS, zero ERROR-level log lines. |
| Regenerate book and restore insert-trigger validations | DONE | 2026-07-12 | 2026-07-12 | Regenerated (all 40 files ✅); all 6 insert-trigger validations confirmed present and firing (direct SQL insert rejected on bad parent_portfolio_id). Manual QA: all 6 steps PASS. |
| End-to-end test book after regeneration | ABANDONED | Superseded by the regen task's own manual QA scenario (login, list, add, edit, save, history, badges, change-reason) – a separate identical pass would be pure duplication. | ||
| Migrate Portfolio/Book to composite-entity versioning | DONE | 2026-07-12 | 2026-07-12 | Rescoped: book_status/regulatory_book_type are enum-like FK attributes, not composite children – the real 1-to-many relationship is Portfolio (parent) -> Book (child, via parent_portfolio_id), matching the proven party/party_identifier shape. |
| Regenerate and re-test book after composite migration | ABANDONED | Superseded by the composite-migration task's own full book regen and manual QA scenario – a separate identical pass would be pure duplication. |
Decisions
- book_status and regulatory_book_type are enum-like FK attributes
(many books reference one lookup row), not composite children of
Book –
:bump_parent_version:there would be wrong (editing a status definition would spuriously bump every book referencing it). - The real 1-to-many composite relationship is Portfolio (parent) -> Book (child, via parent_portfolio_id), matching the proven party/party_identifier and counterparty/counterparty_identifier shape.
- Portfolio's own
parent_portfolio_idself-reference is registered as composite parent-and-child of itself so a grandchild book's write recursively bumps every ancestor portfolio up the tree, not just the immediate parent. - As-of resolution of an FK's meaning at a historical version (e.g. what "book_status" meant at time t) is a distinct, common concern from composite parent/child version bumping – scoped out to its own story, As-of lookup resolution codegen facet, rather than folded in here.
- Portfolio's own Qt layer remains fully unmigrated/stale and out of scope for this story – its History dialog not live-refreshing on a sibling entity's (Book's) NATS events is a known, separately captured gap, not a regression from this work.
Out of scope
- book_purpose_type, ledger_feed_type, is_sweepable, Wash risk-book link, and child-entity toolbar buttons – picked up next in Book data model cleanup, now unblocked.
- As-of lookup resolution (resolving a historical FK value's meaning) – scoped to its own story.
- Portfolio's own Qt-layer relocation/regeneration.
Result
book, book_status, and regulatory_book_type are fully regenerated
against current codegen templates (all ✅ in compass codegen entity
show), with the insert-trigger validations from PR #1449 confirmed
present and firing. Portfolio/Book are migrated to composite-entity
versioning: adding, editing, or deleting a book bumps its parent
portfolio's version (and recursively bumps every ancestor up a nested
portfolio tree), and "portfolio as of version N" correctly composes
the books it contained at that point in time – verified directly via
SQL, not just via generated code, at up to 3 levels deep. A real
codegen-template bug (touch-function generation order vs. Postgres's
eager CREATE RULE resolution, affecting self-referencing composite
entities) was found and fixed along the way, confirmed safe for the
existing party/counterparty pilot. All manual QA scenarios PASSED.
Book data model cleanup's remaining new-work tasks are unblocked.