Story: Server-side UUID generation for all entities
Table of Contents
This page documents a story in Product backlog — inbox, carried unfinished from Sprint 24 at close. It captures the goal, current status, acceptance criteria, and the tasks that compose it.
Goal
Clients must never generate primary-key UUIDs. Today, every entity
with a UUID primary key (Book, Portfolio, the CRM entities, and many
more) has an Add dialog that calls
boost::uuids::random_generator()() client-side in setCreateMode()
(part of the shared ores.cpp.qt.detail_dialog_impl.org codegen
template) and submits that id in the create request. This is a
trust/integrity smell – key assignment is a server responsibility –
and surfaced concretely while investigating why a CRM entity's id
field was editable in the UI (see
the cross-rates matrix task).
Move id assignment to the server: the create request either omits the
id or the server ignores/overwrites whatever the client sent, the
server generates the real UUID during the save, and returns the
created entity (with its real id) in the response. The client shows a
nil UUID (00000000-0000-0000-0000-000000000000) as a placeholder
while in create mode, never a client-chosen value, and never allows
editing it.
Scoped to primary-key UUIDs only – other client-generated UUIDs (e.g. request correlation ids) are unaffected and out of scope.
Status
| Field | Value |
|---|---|
| State | BACKLOG |
| Carried from | Sprint 24 (unfinished at close) |
| Now | Not yet started. |
| Waiting on | Nothing. |
| Next | Break the story into tasks. |
| Last touched | 2026-07-21 |
Acceptance
- The shared Qt detail-dialog codegen template
(
ores.cpp.qt.detail_dialog_impl.org) no longer callsboost::uuids::random_generator()()insetCreateMode()for any UUID-primary-keyed entity – the id field shows a nil UUID placeholder and stays read-only in create mode (never user-editable, matching the fix already landed for the CRM entities this session). - Every UUID-primary-keyed entity's save/create path is audited: the server-side create handler generates the id (or a shared repository helper does, consistently across entities) rather than trusting whatever the client sent – a malicious or buggy client submitting a client-chosen id must not be able to make it stick.
- The save response includes the server-assigned id, and the client updates its in-memory copy from that response so the newly created row is immediately usable (e.g. selectable in a dynamic combo) without a manual reload.
- This is a codegen template + repository/service change applied once and regenerated everywhere, not N hand-patches across entities.
- Explicitly out of scope: non-primary-key UUIDs (correlation ids, etc.) – those remain client-generated.
Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|