Entity lifecycle
Table of Contents
A full-stack ORE Studio entity spans seven layers: a domain type, a
SQL schema, and five exposure layers (HTTP REST, CLI, shell REPL, Wt
web UI, Qt desktop UI). All layers are mandatory for a regular
entity — do not skip one without explicit user approval. Use the
entity-creator orchestrator skill which creates a TaskCreate task for
each layer and drives the sub-skills in order.
Codegen is the primary path for every layer that has a profile; the
mustache templates in projects/ores.codegen/library/templates/ are
the ground truth for what each layer generates. Four layers (HTTP,
CLI, Shell, Wt) have no profile yet — see §Codegen gaps below.
Return to Knowledge.
Layer ordering
@startuml skinparam backgroundColor #FEFEFE skinparam componentStyle rectangle [domain type\n(ores.*api)] as D [SQL schema\n(ores.sql)] as S [HTTP endpoints\n(ores.http.server)] as H [CLI commands\n(ores.cli)] as C [shell commands\n(ores.shell)] as SH [Wt UI\n(ores.wt)] as W [Qt UI\n(ores.qt.*)] as Q D --> S : persists via repository D --> H : service → REST routes D --> C : service → CLI parser D --> SH : service → REPL command D --> W : service → Wt widget D --> Q : service → Qt model @enduml
Build all layers in order. An exposure layer must not be created before its domain type and SQL schema are merged.
| Layer | Skill | Pattern doc | Recipe |
|---|---|---|---|
| Domain type | domain-type-creator | (this doc §Type mappings) | — |
| SQL schema | sql-schema-creator | SQL entity schema patterns | How do I create a new entity SQL schema? |
| HTTP endpoints | http-entity-creator | HTTP entity patterns | How do I create HTTP endpoints for a new entity? |
| CLI commands | cli-entity-creator | CLI entity patterns | How do I create CLI commands for a new entity? |
| Shell commands | shell-entity-creator | Shell entity patterns | How do I create shell commands for a new entity? |
| Wt UI | wt-entity-creator | Wt entity patterns | How do I create Wt widgets for a new entity? |
| Qt UI | qt-entity-creator | Qt entity patterns | How do I create Qt UI for a new entity? |
Type mappings
Canonical DB → C++ type mapping used by all layers. Codegen reads these from the JSON model and enforces them. Apply the same mapping when writing or reviewing hand-crafted code.
| Database type | C++ type | Include |
|---|---|---|
uuid |
boost::uuids::uuid |
<boost/uuid/uuid.hpp> |
text |
std::string |
<string> |
integer |
int |
(built-in) |
bigint |
std::int64_t |
<cstdint> |
boolean |
bool |
(built-in) |
timestamp |
std::chrono::system_clock::time_point |
<chrono> |
real |
double |
(built-in) |
bytea |
std::vector<std::byte> |
<vector>, <cstddef> |
uuid (optional FK) |
std::optional<boost::uuids::uuid> |
<optional>, <boost/uuid/uuid.hpp> |
uuid (tenant) |
utility::uuid::tenant_id |
ores.utility/uuid/tenant_id.hpp |
Domain entities use UUID primary keys (id column). Lookup/reference
entities use text primary keys with a domain-specific column name
(iso_code, code, type, etc.).
Service method naming
The service layer wraps repository operations and is the contract all exposure layers consume. Names must follow this table — do not invent synonyms.
| Operation | Method pattern | Returns |
|---|---|---|
| Create or update (upsert) | save_<entity> |
void |
| Delete | remove_<entity> |
void |
| Find by primary key | find_<entity> |
std::optional<domain::<entity>> |
| List all | list_<entities> |
std::vector<domain::<entity>> |
| List with filter | list_<entities>_by_<key> |
std::vector<domain::<entity>> |
| List since timestamp | list_<entities>_since |
std::vector<domain::<entity>> |
| Get full history | get_<entity>_history |
std::vector<domain::<entity>> |
save_* exposes the repository's upsert semantics directly. Never
split it into separate create_* / update_* methods at the service
layer — doing so duplicates repository semantics without adding value.
Complete entity file checklist
The canonical reference is the currency entity. A complete regular
entity must have all of the following files (paths are relative to the
repo root, * = component-specific prefix):
Domain + infrastructure (ores.*api, generated by --profile all):
| File | Template |
|---|---|
include/ores.*/domain/{entity}.hpp |
cpp_domain_type_class.hpp.mustache |
include/ores.*/io/{entity}_json_io.hpp |
cpp_domain_type_json_io.hpp.mustache |
src/io/{entity}_json_io.cpp |
cpp_domain_type_json_io.cpp.mustache |
include/ores.*/io/{entity}_table.hpp |
cpp_domain_type_table.hpp.mustache |
src/io/{entity}_table.cpp |
cpp_domain_type_table.cpp.mustache |
include/ores.*/io/{entity}_table_io.hpp |
cpp_domain_type_table_io.hpp.mustache |
src/io/{entity}_table_io.cpp |
cpp_domain_type_table_io.cpp.mustache |
include/ores.*/generators/{entity}_generator.hpp |
cpp_domain_type_generator.hpp.mustache |
src/generators/{entity}_generator.cpp |
cpp_domain_type_generator.cpp.mustache |
include/ores.*/messaging/{entity}_protocol.hpp |
cpp_protocol.hpp.mustache |
include/ores.*/service/{entity}_service.hpp |
cpp_service.hpp.mustache |
src/service/{entity}_service.cpp |
cpp_service.cpp.mustache |
Repository (ores.*core, generated by --profile repository):
| File | Template |
|---|---|
include/ores.*.core/repository/{entity}_entity.hpp |
cpp_domain_type_entity.hpp.mustache |
src/repository/{entity}_entity.cpp |
cpp_domain_type_entity.cpp.mustache |
include/ores.*.core/repository/{entity}_mapper.hpp |
cpp_domain_type_mapper.hpp.mustache |
src/repository/{entity}_mapper.cpp |
cpp_domain_type_mapper.cpp.mustache |
include/ores.*.core/repository/{entity}_repository.hpp |
cpp_domain_type_repository.hpp.mustache |
src/repository/{entity}_repository.cpp |
cpp_domain_type_repository.cpp.mustache |
SQL schema (ores.sql, generated by --profile sql):
| File | Template |
|---|---|
create/{component}/{component}_{entity}_create.sql |
sql_schema_domain_entity_create.mustache |
create/{component}/{component}_{entity}_notify_trigger_create.sql |
sql_schema_notify_trigger.mustache |
drop/{component}/{component}_{entity}_drop.sql |
sql_schema_domain_entity_drop.mustache |
drop/{component}/{component}_{entity}_notify_trigger_drop.sql |
sql_schema_notify_trigger_drop.mustache |
Qt UI (ores.qt.{component}, generated by --profile qt):
| File | Template |
|---|---|
include/ores.qt/Client{Entity}Model.hpp |
cpp_qt_client_model.hpp.mustache |
src/Client{Entity}Model.cpp |
cpp_qt_client_model.cpp.mustache |
include/ores.qt/{Entity}MdiWindow.hpp |
cpp_qt_mdi_window.hpp.mustache |
src/{Entity}MdiWindow.cpp |
cpp_qt_mdi_window.cpp.mustache |
include/ores.qt/{Entity}DetailDialog.hpp |
cpp_qt_detail_dialog.hpp.mustache |
src/{Entity}DetailDialog.cpp |
cpp_qt_detail_dialog.cpp.mustache |
ui/{Entity}DetailDialog.ui |
qt_detail_dialog_ui.mustache |
include/ores.qt/{Entity}HistoryDialog.hpp |
cpp_qt_history_dialog.hpp.mustache |
src/{Entity}HistoryDialog.cpp |
cpp_qt_history_dialog.cpp.mustache |
ui/{Entity}HistoryDialog.ui |
qt_history_dialog_ui.mustache |
include/ores.qt/{Entity}Controller.hpp |
cpp_qt_controller.hpp.mustache |
src/{Entity}Controller.cpp |
cpp_qt_controller.cpp.mustache |
Layers with codegen gaps (manual until profiles are implemented):
| Layer | Component | Files needed |
|---|---|---|
| HTTP endpoints | ores.http.server |
routes header + implementation |
| CLI commands | ores.cli |
options struct + parser header + implementation |
| Shell commands | ores.shell |
commands header + implementation |
| Wt UI | ores.wt.service |
list widget header + implementation + dialog header + implementation |
Codegen gaps
Four layers have no codegen profile. When the entity-creator reaches one of these layers it must stop and raise a sprint story before proceeding.
The story for each gap must:
- Create mustache templates that encode the layer's conventions.
- Add a profile entry to facet_catalogue.org.
- Validate the profile against an existing entity (
currencyfor refdata,accountfor IAM). - Update this document's file checklist with the new profile's output paths.
Only after the profile is merged can the layer be generated for the new entity. Any hand-written files created as an interim workaround must be replaced with generated output once the profile exists.
See also
- entity-creator — orchestrator skill; use this when adding a new entity.
- domain-type-creator — first layer skill.
- ORE Studio Codegen — codegen component model, profile catalogue, model schema.
- ORE Studio SQL Schema — schema mental model and PostgreSQL setup.
- cpp_repository, cpp_service_app — the literate templates for the repository and service facets.