Story: As-of lookup resolution codegen facet
Table of Contents
This page documents a story in Sprint 24. It captures the goal, current status, acceptance criteria, and the tasks that compose it.
Goal
Give any bitemporal reference/lookup entity a codegen-generated way to
answer "what did code X mean as of timepoint t" — a point-in-time
query (valid_from < t and valid_to >= t=), distinct from and
unrelated to composite parent-child version bumping. Discovered while
working through book/book_status: opening a historical book version
correctly shows the raw status code it had then (stored inline on the
book row), but resolving that code's Name/Description/badge colour
today uses a current-only lookup, so a since-deleted or since-renamed
code silently fails to resolve for a perfectly valid historical view.
A hand-written precedent already exists (read_at_timepoint on
currency_repository=/=country_repository — not
business_centre_repository, despite an earlier version of this
story claiming otherwise): not codegen-generated, and with no
service/NATS/UI caller, though ores.cli export --as-of does call
it directly on the repository. This story generalises it into a
proper facet (correcting a boundary bug found along the way — see
Decisions) and applies it broadly, since resolving a historical FK
value correctly is a common need, not a book-specific one.
Status
| Field | Value |
|---|---|
| State | DONE |
| Parent sprint | Sprint 24 |
| Now | All three required tasks done; rollout to remaining refdata entities deferred as a follow-on per Acceptance. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-07-25 |
Acceptance
- A new codegen facet (e.g.
:has_as_of_lookup: true) generates a repository-levelread_at_timepoint(ctx, as_of[, key])method matching the existing hand-written shape, plus a service-level wrapper – consistently, not hand-added per entity. - The facet is actually wired to a caller (NATS request/response and/or a Qt read path) for at least the pilot entities – the current currency/country precedent has no service/NATS/UI caller, only a direct repository call from ores.cli.
- Piloted on
book_statusandregulatory_book_type(the entities that surfaced the gap) and verified: viewing a historical book version resolves its status/type badge correctly even after that code has since been deleted or renamed. - Existing
currency_repository=/=country_repositoryhand-writtenread_at_timepointmethods (including theirvalid_to >t= boundary bug) are either replaced by the generated facet or explicitly reconciled with it (not left as a second, inconsistent implementation). - Rollout to the remaining refdata lookup entities is scoped as a follow-on, not required for this story's completion.
Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|
| Design the as-of lookup codegen facet | DONE | 2026-07-23 | 2026-07-23 | Design a new codegen facet (candidate flag: :has_as_of_lookup: true) generating a repository-level read_at_timepoint(ctx, as_of[, key]) method and a service-level wrapper, matching the existing hand-written shape on currency_repository/country_repository/business_centre_repository but generated consistently. Decide: NATS protocol surface (new request/response, or reuse an existing one with an optional as_of param), where the flag lives in the .org model (entity-level, since this is about the entity's own bitemporal window, not a parent/child FK relationship), and how/whether to reconcile the 3 existing hand-written methods with the generated one. |
| Implement and pilot the as-of lookup facet on book_status/regulatory_book_type | DONE | 2026-07-23 | 2026-07-24 | Add the designed facet to the codegen templates (SQL/repository/service/protocol as scoped). Apply :has_as_of_lookup: true to book_status.org and regulatory_book_type.org (the entities that surfaced this gap), regenerate, and wire it to an actual caller – at minimum the Book history dialog resolving a historical version's status/type badge correctly, proving the facet isn't dead code like its hand-written predecessor. |
| Reconcile existing hand-written read_at_timepoint methods | DONE | 2026-07-24 | 2026-07-25 | currency_repository/country_repository already have a hand-written read_at_timepoint (not business_centre_repository), unwired to any service/NATS/UI caller and with a valid_to >= t boundary bug versus the documented valid_to > t convention. Once the codegen facet lands, either replace these with the generated (corrected) version or explicitly document why they diverge – don't leave two parallel implementations of the same concept. |
| Roll out as-of lookup facet to remaining refdata entities | BACKLOG | Once proven on book_status/regulatory_book_type, apply :has_as_of_lookup: true broadly across refdata lookup/reference entities referenced by FK elsewhere. Deferred follow-on, not required for this story's own completion. |
Decisions
- Corrected this story's own premise:
read_at_timepointis not fully dead code —ores.cli export currencies/countries --as-ofalready calls it directly on the repository.business_centre_repositorynever had the method at all (onlycurrency=/=countrydo); the real gap is service/NATS/UI wiring and test coverage, not "no caller anywhere". - The hand-written precedent has a boundary bug:
valid_to >t= should bevalid_to > t, per the schema's owntstzrange(valid_from, valid_to)exclusion constraint (PostgreSQL default[valid_from, valid_to), exclusive upper) and the documented convention in Time and Timestamps. The generated facet corrects this rather than reproducing it. - Facet is entity-level (
:has_as_of_lookup: true, not per-column like the existinglist_by_as_of, which is a different range-overlap shape for composite parent-child versioning and stays untouched by this story). - NATS surface: extend the existing
get_..._request=/=responsewith an optionalas_offield rather than minting a new request/response pair — backward compatible, no protocol sprawl. - Pilot caller (Book history dialog) resolves a historical book
version's status/type badge as-of that book version's own
valid_from, not "now". - Full design rationale in Design the as-of lookup codegen facet's
* Plan.