Task: Appraise business_centre against the entity evaluation checklist
Table of Contents
This page documents a task in the Commission: business_centre story. It captures the goal, current status, acceptance, and any notes or results.
Goal
A complete per-layer appraisal of business_centre's current state, identifying any codegen drift, missing pieces, or regressions to fix in later tasks.
Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Commission: business_centre |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-07-12 |
Acceptance
- Checklist scored for every layer; findings recorded in the task's Notes/Result; any drift or gaps found are either fixed inline (trivial) or become explicit follow-on task scope.
Plan
(Implementation strategy. Written when work starts; key decisions
are distilled into the parent story's * Decisions at close, but the
plan itself stays — it is the historical record of what we did.)
Notes
Ran the Domain entity evaluation checklist against business_centre. Per
the Entity Coverage Matrix SQL/Domain/Tbl IO/JSON IO/Qt were already
marked Y; static inspection below confirms most of that but surfaces
four findings, two of them real bugs.
DB layer
- Table, temporal columns, GIST exclusion, primary key, version/natural-key unique indexes, tenant index, insert trigger, soft-delete rule, and validate function are all present and structurally correct (refdata_business_centres_create.sql).
- Finding 1 (security gap): neither
ores_refdata_business_centres_insert_fn()norores_refdata_validate_business_centre_fn()carriessecurity definerorset search_path = public, pg_temp. Same class of bug the Commission: country story fixed and the checklist calls out by name – without both, a service role with a manipulated search path can shadowores_refdata_business_centres_tbland bypass validation. - Finding 2 (bootstrap guard): the validate function's bootstrap
pass-through is
if not exists (select 1 from ores_refdata_business_centres_tbl limit 1)– novalid_to = ores_utility_infinity_timestamp_fn()filter. Same bug pattern as Commission: country: a table left with only soft-deleted rows would incorrectly skip the pass-through. - Foreign-key validation for
coding_scheme_code/country_alpha2_codeis inlined directly in the insert trigger (raises its own exception) rather than delegating to avalidate_<other-entity>_fn. Functionally fine, just a style inconsistency versus the documented pattern – not fixing as part of this story.
Codegen layer
- Finding 3 (no live model):
refdata_business_centres_create.sqlcarries an "AUTO-GENERATED FILE – DO NOT EDIT MANUALLY,sql_schema_table_create.mustache" banner, but no codegen entity model exists anywhere in the tree forbusiness_centre– searchedprojects/ores.codegen/library,projects/modeling/*.org(entity_viewdocs), and every*.json=/=*.yamlin the repo. The entity is effectively hand-maintained today despite the banner's claim. Authoring a fresh codegen model is out of scope for the codegen-sync task below (documented as a known gap instead) – it is a materially bigger effort (newentity_view+ regenerating and diffing all twelve output profiles from scratch) than "sync existing drift", and risks destabilising a currently-working entity mid-story.
Domain / repository / service / messaging layers
- Domain struct (business_centre.hpp) covers every DB column including
recorded_at; canonical C++ types throughout; no business logic in the struct. - Repository/service/messaging headers present and match the standard shape (entity, mapper, repository, service, json_io, protocol).
- NATS eventing:
business_centre_changed_eventis registered in the LISTEN/NOTIFY-to-NATS relay in application.cpp (register_mapping<...>+event_bus.subscribe<...>both present) – not the party_type-style miss the checklist warns about.
Qt layer
- Finding 4 (wrong plugin – matches the "should be in refdata"
instinct that kicked off this story): all of business_centre's Qt
CRUD code (
BusinessCentreController,BusinessCentreMdiWindow,BusinessCentreDetailDialog,BusinessCentreHistoryDialog,ClientBusinessCentreModel) lives underores.qt/party, andPartyPlugin.cppconstructs the controller and wires its "Business Centres" menu action. This is the exact cross-component leakage pattern the Move book to refdata story fixed for Book/BookStatus/ RegulatoryBookType: the C++ backend is correctly inores.refdata, but the Qt layer sits under the wrong plugin.business_unitandcontact_type(two other open Commission stories) show the exact same pattern underPartyPlugin– out of scope here, worth a capture for whoever picks those up next. - All five expected Qt artefacts (list/detail/history/controller/model) otherwise exist; the manual end-to-end verification (list loads, detail round-trips, history correct, delete preserves history, cross-session eventing) is deferred to the dedicated Qt-verification task, and should happen after the plugin move so it isn't repeated twice like the Book story's rationale for sequencing.
Manual layer
- No entity chapter exists under
doc/manualforbusiness_centretoday – confirmed by thedocument-business-centretask already in this story's scope.
Rescope decision (see story * Decisions)
Findings 1, 2, and 4 are real, fixable gaps in scope for a commissioning
story (not just "verify," but "commission"), so two new tasks were added
to the story ahead of Qt verification: move the Qt CRUD/plugin wiring to
ores.qt/refdata / RefdataPlugin, and fix the two SQL security/bootstrap
gaps. Finding 3 (no codegen model) is recorded as a known gap, not
actioned – the sync-codegen-business-centre task is downgraded to a
drift/consistency check against the DB-vs-domain-vs-checklist criteria by
hand, since there is no model to regenerate from.
Test Scenarios
Manual QA scenarios (scaffolded via compass add test_scenario, run
through the QA Validation Runner panel) that verify this task. Link
new ones here as they're created; the scenario doc itself links back
via its "Verifies task" field.
| Scenario | State | Notes |
|---|---|---|
PRs
| PR | Title |
|---|---|
Review
| Comment summary | File | Decision | Notes |
|---|---|---|---|
Result
Checklist scored across all applicable layers via static inspection. Four findings recorded (details in Notes above); three drove a story rescope (two new tasks added: SQL security/bootstrap fix, Qt-to-RefdataPlugin move), one (no live codegen model) recorded as an out-of-scope known gap. No trivial fixes were made inline – all findings are substantial enough to warrant their own task or explicit out-of-scope decision.