Problem
Several date-based lists used a random UUID as the final sort key. Rows from
the same business day therefore had a stable but arbitrary order. A full model
walk also found inconsistent creation and update metadata across business
tables.
Final plan
Table classification
Mutable records, with both timestamps:
Accounts, FarmLogos, EggUnitConversions, Products,
ProductEggGradeMappings, DailyEntries, DailyEntryGrades, EggGrades,
EggLots, Expenses, ExpenseCategories, Flocks, InventoryItems,
InventoryLots, WaterUsages, Customers, Payments, SalesOrders,
SalesOrderItems, SalesOrderAllocations, and AspNetUsers.
Create-only records, with CreatedAtUtc only:
UserRoleAssignments, BirdMovements, FeedUsages, InventoryMovements, and
EggInventoryMovements.
Chronological tables, with Sequence:
SalesOrders, Expenses, DailyEntries, EggLots, BirdMovements,
Payments, InventoryLots, FeedUsages, WaterUsages,
InventoryMovements, and EggInventoryMovements.
AuditEvents keeps its existing OccurredAtUtc and Sequence. Identity
support tables and operational tables retain their own lifecycle policies.
Migration and review outcome
The migration reuses account-scoped, action-specific audit events for creation
and update times, including User.RoleChanged. Unknown times use the explicit
1970-01-01T00:00:00Z sentinel; an unrecoverable update time equals creation.
Database triggers own future timestamp stamping across EF, bulk, and raw-SQL
writes. Legacy sequence values are deterministic but not historically exact.
Independent Opus, Fable, and Sonnet reviews found and drove fixes for the
payments direction, the missing Sequence regression guard, the user-role
backfill, recalled model census, duplicated ordering, and migration SQL shape.
The Sequence guard was mutation-tested and fails when the key is removed.
Accepted limits: a database clock rollback can defeat the CreatedAtUtc
middle key, offset pagination is not a concurrent-write snapshot, and the
five-second migration timeout bounds lock acquisition rather than execution.
Implementation: #820
Problem
Several date-based lists used a random UUID as the final sort key. Rows from
the same business day therefore had a stable but arbitrary order. A full model
walk also found inconsistent creation and update metadata across business
tables.
Final plan
DateOnly.CreatedAtUtcto every business record.UpdatedAtUtconly to mutable records, equal to creation time oninsert and replaced on every update.
ICreatedRecordandIMutableRecordinterfaces insteadof base classes.
bigint GENERATED ALWAYS AS IDENTITYSequenceon liststhat present or page insertion chronology.
CreatedAtUtc, andSequence, preserving eachlist's existing direction. Payments intentionally remain oldest-first.
tables.
Table classification
Mutable records, with both timestamps:
Accounts,FarmLogos,EggUnitConversions,Products,ProductEggGradeMappings,DailyEntries,DailyEntryGrades,EggGrades,EggLots,Expenses,ExpenseCategories,Flocks,InventoryItems,InventoryLots,WaterUsages,Customers,Payments,SalesOrders,SalesOrderItems,SalesOrderAllocations, andAspNetUsers.Create-only records, with
CreatedAtUtconly:UserRoleAssignments,BirdMovements,FeedUsages,InventoryMovements, andEggInventoryMovements.Chronological tables, with
Sequence:SalesOrders,Expenses,DailyEntries,EggLots,BirdMovements,Payments,InventoryLots,FeedUsages,WaterUsages,InventoryMovements, andEggInventoryMovements.AuditEventskeeps its existingOccurredAtUtcandSequence. Identitysupport tables and operational tables retain their own lifecycle policies.
Migration and review outcome
The migration reuses account-scoped, action-specific audit events for creation
and update times, including
User.RoleChanged. Unknown times use the explicit1970-01-01T00:00:00Zsentinel; an unrecoverable update time equals creation.Database triggers own future timestamp stamping across EF, bulk, and raw-SQL
writes. Legacy sequence values are deterministic but not historically exact.
Independent Opus, Fable, and Sonnet reviews found and drove fixes for the
payments direction, the missing Sequence regression guard, the user-role
backfill, recalled model census, duplicated ordering, and migration SQL shape.
The Sequence guard was mutation-tested and fails when the key is removed.
Accepted limits: a database clock rollback can defeat the
CreatedAtUtcmiddle key, offset pagination is not a concurrent-write snapshot, and the
five-second migration timeout bounds lock acquisition rather than execution.
Implementation: #820