Sprint Backlog 07
Sprint Mission
- finish reference implementation.
Stories
Active
| Tags | Headline | Time | % | ||
|---|---|---|---|---|---|
| Total time | 5:34 | 100.0 | |||
| Stories | 5:34 | 100.0 | |||
| Active | 5:34 | 100.0 | |||
| code | Replace MaxMind implementation | 1:08 | 20.4 | ||
| code | Setup basic Wt infrastructure | 0:52 | 15.6 | ||
| code | Document namespaces for doxygen | 0:21 | 6.3 | ||
| code | Fix compilation issues in main for Wt and HTTP | 3:13 | 57.8 |
| Tags | Headline | Time | % | ||
|---|---|---|---|---|---|
| Total time | 72:47 | 100.0 | |||
| Stories | 72:47 | 100.0 | |||
| Active | 72:47 | 100.0 | |||
| agile | Sprint and product backlog refinement | 1:07 | 1.5 | ||
| infra | OCR scan notebooks for this sprint | 0:53 | 1.2 | ||
| code | Consider compressing payload | 3:05 | 4.2 | ||
| code | Latest currencies should have different colour | 1:28 | 2.0 | ||
| code | Do not expose temporal machinery in domain | 1:25 | 1.9 | ||
| code | Add account management support to qt | 3:43 | 5.1 | ||
| code | Add password reset functionality to accounts | 1:49 | 2.5 | ||
| code | Add core infrastructure for roles and permissions | 4:52 | 6.7 | ||
| code | Add exit confirmation dialog | 0:03 | 0.1 | ||
| code | Improve error messages in shell | 0:23 | 0.5 | ||
| code | Add support for relative time formatting | 2:01 | 2.8 | ||
| code | Setup windows laptop with WSL | 5:10 | 7.1 | ||
| code | Add listen/notify to shell | 2:45 | 3.8 | ||
| code | Define type traits for message grouping | 0:44 | 1.0 | ||
| code | Rename accounts to iam |
1:30 | 2.1 | ||
| code | Create the observability component | 1:59 | 2.7 | ||
| code | Consider renaming utility to system |
0:25 | 0.6 | ||
| code | Use chrono timepoints for domain entities | 1:44 | 2.4 | ||
| code | Use prebuilt qt | 0:26 | 0.6 | ||
| code | Add flags for currencies | 4:45 | 6.5 | ||
| code | Add skills for code review | 0:52 | 1.2 | ||
| code | Compilation fixes to current main | 3:47 | 5.2 | ||
| code | Ignore warnings on windows and OSX | 0:23 | 0.5 | ||
| code | Add sign-up workflow | 0:15 | 0.3 | ||
| code | Implement RBAC enforcement | 6:34 | 9.0 | ||
| code | Add session information to database | 3:36 | 4.9 | ||
| code | Add UI for roles and permission management | 0:28 | 0.6 | ||
| code | Improve unit test coverage | 1:00 | 1.4 | ||
| code | Incorporate new telemetry component | 4:47 | 6.6 | ||
| code | Refactor SQL code | 1:29 | 2.0 | ||
| code | Add session recording support to comms | 1:30 | 2.1 | ||
| code | Replace MaxMind implementation | 1:08 | 1.6 | ||
| code | Consider exposing end points via HTTP | 2:15 | 3.1 | ||
| code | Setup basic Wt infrastructure | 0:52 | 1.2 | ||
| code | Document namespaces for doxygen | 0:21 | 0.5 | ||
| code | Fix compilation issues in main for Wt and HTTP | 3:13 | 4.4 |
COMPLETED Sprint and product backlog refinement agile
Updates to sprint and product backlog.
COMPLETED OCR scan notebooks for this sprint infra
We need to scan all of our finance notebooks so we can use them with AI. Each sprint will have a story similar to this until we scan and process them all.
COMPLETED Add AI generated sprint summary infra
At the end of the sprint, generate the sprint summary using the prompt.
CANCELLED Sprint Demo infra
Time spent doing the demo. This is the first one so it will be very basic.
COMPLETED Consider compressing payload code
Sounds quite simple to extend the binary protocol with a compressed payload. We just need some information in the header about it. We should support both compressed and uncompressed payloads. Play with compression algos in boost.
COMPLETED Add lock account request code
Rationale: implemented last sprint.
As per gemini's comments, we should have a request to lock an account.
Notes:
- account unlock should return boolean rather than throw.
Test.
TEST_CASE("handle_login_request_locked_account", tags) { auto lg(make_logger(test_suite)); database_helper h; h.truncate_table(database_table); accounts_message_handler handler(h.get_context()); boost::asio::io_context io_context; const auto account = generate_synthetic_account(); create_account_request create_req(to_create_account_request(account)); BOOST_LOG_SEV(lg, info) << "Create account request: " << create_req; const auto create_payload = create_req.serialize(); run_co_test(io_context, [&]() -> boost::asio::awaitable<void> { auto result = co_await handler.handle_message( message_type::create_account_request, create_payload, "127.0.0.1:12345"); REQUIRE(result.has_value()); }); // 2. Simulate locking the account (A dedicated lock request should exist, // but for this test, we'll assume the handler has a method/logic for it // or that the system supports a lock request message type). // Assuming a lock_account_request exists or the account is locked internally. unlock_account_request lock_req; // Re-use struct for simplicity, assuming a dedicated lock is handled internally lock_req.account_id = create_account_response::deserialize( handler.get_account_id_by_username(create_req.username)).value().account_id; // Hypothetical internal method // In a real system, you'd send a dedicated lock message here. // For now, we rely on a separate mechanism to put the account into a locked state. // **NOTE**: For a proper test, a dedicated LOCK_ACCOUNT_REQUEST is needed. // 3. Attempt login with valid credentials for the now-locked account login_request login_req; login_req.username = create_req.username; login_req.password = create_req.password; BOOST_LOG_SEV(lg, info) << "Attempting login for locked user: " << login_req.username; const auto login_payload = login_req.serialize(); run_co_test(io_context, [&]() -> boost::asio::awaitable<void> { auto result = co_await handler.handle_message( message_type::login_request, login_payload, "192.168.1.100:54321"); REQUIRE(result.has_value()); const auto response_result = login_response::deserialize(result.value()); REQUIRE(response_result.has_value()); const auto& response = response_result.value(); BOOST_LOG_SEV(lg, info) << "Response: " << response; CHECK(response.success == false); // Check for an explicit error message/code related to account lock. CHECK(response.error_message.find("locked") != std::string::npos); }); }
COMPLETED Add tests for messaging handler code
Rationale: implemented last sprint.
We need tests in comms which create a test request and response and a test handler.
COMPLETED Add version support to entities code
Rationale: implemented last sprint.
We need a "version" field which is incremented automatically by a trigger. It is used as follows:
- domain entities have a version field which is loaded from database.
- if we try to save at version
nbut current version is notn-1, it should fail to save. - version is incremented automatically on save.
- display version in UI prominently (e.g. next to entity key, iso code for currencies) so that we can see when we reload.
COMPLETED Add skill to create new project component code
Rationale: implemented last sprint.
Should create folders, CMakeLists, sample test, add to main make file etc. The new project should compile.
Links:
COMPLETED Latest currencies should have different colour code
After reloading we should mark latest currencies with a different colour so that it is obvious what was added. Consider colouring rows by recency.
Notes:
- valid to is the same as valid from, which is incorrect.
COMPLETED Do not expose temporal machinery in domain code
As per discussions with Claude:
> ok that looks good. but in terms of valid to/valid from: these are really > repository concerns, I think we are leaking them outside of the repository. I > wonder if it makes more sense for the domain entities to have a field such as > "created_at" which maps to the repository "valid_from" and not expose > temporarilty. what are your thoughts. do not change anything, we will deal > with that later, just want to capture this requirement for now.
That's a valid architectural concern. You're right that valid_from/valid_to are temporal table implementation details that are leaking into the domain layer.
Current state (leaky abstraction):
- Domain entity has valid_from and valid_to strings
- These are really repository/database concerns for temporal versioning (SCD Type 2 pattern)
- The UI now displays these raw database fields
Cleaner approach:
- Domain entity has created_at (or modified_at) - represents when this version was created
- Repository maps valid_from → created_at when loading
- valid_to stays internal to repository (used for querying current vs historical records)
- Domain doesn't need to know about the bi-temporal mechanics
Benefits:
- Domain entities are simpler and more intuitive
- Repository encapsulates temporal implementation details
- Easier to change temporal strategy without affecting domain
- created_at is more meaningful to users than "valid from"
I'll note this for future work. When you're ready to address it, the changes would involve:
- Rename valid_from → created_at in domain::currency
- Remove valid_to from domain (keep only in entity/repository layer)
- Update mapper to translate between them
- Update UI labels accordingly
COMPLETED Add account management support to qt code
At present we cannot add, remove etc accounts from the UI.
Notes:
- add history support for accounts.
- on delete we are automatically reloading.
- if a user has never logged in we should be able to see it. In fact we should
bucket accounts by recency:
- never logged in
- logged in a long time ago
- logged in recently
- is logged in
COMPLETED Add password reset functionality to accounts code
At present it is not possible to reset a user's password.
COMPLETED Add core infrastructure for roles and permissions code
At present we are monitoring authorisation at two levels:
- is logged in
- is admin
We need to introduce basic RBAC where we have roles such as:
- Trading
- Sales
- Operations: restricted access to some trading screens.
- Support: read-only, admin screens.
To start off with we can map these to read/write on CRUD dialogs.
Notes:
- rename
flag_initializertoflag_seederto make it consistent. Done.
COMPLETED Add exit confirmation dialog code
Add a simple dialog to check if the user really wants to exit.
COMPLETED Improve error messages in shell code
At present adding an account that violates some database constraint is not very informative:
ores-shell> ✗ Server returned an error
Client logs:
2025-12-16 10:20:39.538351 [TRACE] [ores.comms.net.client] send_request_sync: task completed. 2025-12-16 10:20:39.538431 [DEBUG] [ores.comms.net.client] Completed synchronous send request successfully. 2025-12-16 10:20:39.538494 [ERROR] [ores.comms.net.client_session] Server returned error: Repository error: Executing INSERT failed: ERROR: duplicate key value violates unique constraint "accounts_username_unique_idx" DETAIL: Key (username)=(newuser37) already exists. 2025-12-16 10:20:39.538567 [DEBUG] [ores.shell.app.repl] Sending logout request before exit.
Similarly, if the server goes down we don't know. Next messages just say:
accounts> list ✗ Request failed
Server logs:
2025-12-16 10:22:34.224094 [DEBUG] [ores.comms.net.connection] Waiting to read the next frame (skip_version_check=false) cancel_slot.is_connected=false 2025-12-16 10:22:34.224231 [ERROR] [ores.comms.net.connection] Network error in read_frame: stream truncated [asio.ssl.stream:1] 2025-12-16 10:22:34.224276 [ERROR] [ores.comms.net.client] Failed to read response frame, error network_error (0x7) 2025-12-16 10:22:34.224335 [WARN] [ores.comms.net.client] Connection lost 2025-12-16 10:22:34.224364 [TRACE] [ores.comms.net.client] send_request_sync: task completed.
COMPLETED Add support for relative time formatting code
"Relative Time Formatting" is part of the ECMAScript Internationalization API Intl.RelativeTimeFormat.
C++20's <chrono> library has extensive date/time support:
#include <chrono> #include <iostream> std::string relative_time(std::chrono::system_clock::time_point past) { auto now = std::chrono::system_clock::now(); auto diff = now - past; if (diff < std::chrono::minutes(1)) return "just now"; else if (diff < std::chrono::hours(1)) return std::to_string(std::chrono::duration_cast<std::chrono::minutes>(diff).count()) + " minutes ago"; // ... continue for hours, days, etc. }
COMPLETED Exit confirmation code
Rationale: Implemented.
We should ask if a user wants to exit before we exit.
COMPLETED Users cannot update their passwords code
Rationale: implemented.
At present it is not possible to update passwords, or any other property of an account.
COMPLETED Setup windows laptop with WSL code
Install all the tooling needed to build OreStudio in WSL on the windows laptop. Fix all the issues with Emacs bootstrap after elpaca move.
COMPLETED Add listen/notify to shell code
At present we cannot listen from the shell. This makes testing harder. Notification should show up in the next prompt like PSQL does.
COMPLETED Define type traits for message grouping code
At present we do:
auto result = client_->process_request< messaging::subscribe_request, messaging::subscribe_response, messaging::message_type::subscribe_request>(std::move(req));
This grouping is known in advance because these messages are defined together.
We should be able to create a type in the protocol that defines the grouping as
traits and then supply the group as the template argument, e.g.
messaging::subscribe, which unpacks the tuple.
COMPLETED Rename accounts to iam code
Gemini summary:
This pull request executes a significant refactoring effort by renaming the 'accounts' module to 'IAM' (Identity and Access Management). This change clarifies the module's responsibilities, which extend beyond simple account management to encompass broader identity and access control functionalities. The renaming impacts various aspects of the project, ensuring consistency in naming conventions across the entire codebase, from file structures and build systems to C++ namespaces and user-facing documentation.
Highlights:
- Module Renaming: The ores.accounts module has been comprehensively renamed to ores.iam to more accurately reflect its purpose as an Identity and Access Management component.
- Codebase-Wide Refactoring: This change involved updating directory names, C++ namespaces (ores::accounts to ores::iam), include paths, and references across all relevant files, including source code, headers, build configurations (CMakeLists.txt), and documentation.
- Documentation and Diagram Updates: All internal and external documentation, including CLAUDE.md, ores.hpp, Org-mode files (.org), and PlantUML diagrams (.puml), have been updated to reflect the new ores.iam naming convention and its expanded description.
COMPLETED Create the observability component code
We need some kind of observability context so that we can look at related log entries. This is sort of related to logging by thread except with coroutines we are no longer interested in threads per se but on some kind of "work identifier" which is preserved across function calls. For this we can have an observability context which is passed around.
Gemini summary;
This pull request integrates a new ores.telemetry component, establishing a robust framework for observability within the project. By adhering to the OpenTelemetry standard, it facilitates distributed tracing and log correlation, crucial for understanding complex system behavior. The design prioritizes coroutine-safety through explicit context management, ensuring that telemetry data can be accurately captured and propagated across asynchronous call chains.
Highlights:
- New Telemetry Component: Introduced a new ores.telemetry component, fully aligned with the OpenTelemetry specification, to enable distributed tracing and log correlation across the system.
- Core Observability Domain Types: Defined essential domain types including trace_id, span_id, span_context, span, log_record, and resource, providing a structured foundation for telemetry data.
- Unique ID Generators: Implemented thread-safe trace_id_generator and span_id_generator classes that embed timestamps and machine IDs, ensuring uniqueness, time-sortability, and efficient generation of identifiers.
- Coroutine-Safe Context Propagation: Provided a telemetry_context class designed for explicit, immutable context passing, making it safe and effective for tracing within coroutine-based asynchronous operations.
- Comprehensive Testing and Modeling: Included extensive unit tests for ID generation, context propagation, and span lifecycle management, alongside PlantUML diagrams for clear visualization of the component's architecture.
Notes:
- we should also add the notion of parents and children so that we can create a graph with the relationships. We should create specific messages for this which are not directly related to logging. The server can just keep track of the observability contexts in a table. We should link it back to each client etc.
- the observability context should also extend to the server so that we can filter all logs for that ID.
- consider using mongo IDs for this or create our own IDs:
Option A: 64-bit IDs (8 bytes) - Best balance cpp struct LogId { uint32_t timestamp; // seconds since 2020 uint16_t machine; // 0-65535 machines uint16_t sequence; // per-second counter // Encode to 11 Base64 chars or 8-10 Base62 chars };
Merged stories:
Log with session id
When we have a lot of clients all connecting we can't really see who is doing what in the server. We need an additional "tag" in logging to represent the session.
COMPLETED History should have a revert button code
It should be possible to choose a given version and ask the system to revert the currency to that version. It just makes an update with a new version to look like that version. It should also be possible to open at version. It shows the edit dialog in "read only mode" with the entity at that version. The tool bar should indicate this. It should also have a revert in that dialog.
COMPLETED History should have a reload button code
It should be possible to reload history without having to reload currencies. In an ideal world we should be able to listen to currency specific notifications. This will be needed in the future for other types of events.
COMPLETED Consider renaming utility to system code
Try to avoid the "grab bag" component that is littered with all sorts of random stuff. System implies extensions to core libraries like std and boost.
Gemini:
This pull request undertakes a significant refactoring effort to enhance the modularity and clarity of the codebase by splitting the monolithic ores.utility module into more focused components. The primary goal is to separate platform-specific functionalities into a dedicated ores.platform module, thereby improving dependency management and making the architecture more maintainable and extensible. This change ensures that core utilities remain lean, while system-level interactions are encapsulated in their own distinct layer.
Highlights:
- New Module: ores.platform: Introduced a new C++ module, ores.platform, specifically designed to house platform-specific utilities and abstractions for OS and hardware interaction. This module includes functionalities for environment variables, filesystem operations, and network information.
- Refactoring of ores.utility: Key components such as environment variable handling, filesystem operations (file I/O, directory search), and network information (hostname, MAC address, process ID) have been extracted from ores.utility and moved into the new ores.platform module. The ores.utility module has been updated to reflect these removals and now focuses on more general-purpose utilities like logging, UUID generation, string manipulation, DateTime, Converter (Base32/Base64), and program options.
- Dependency Updates: Build configurations (CMakeLists.txt) and PlantUML diagrams across various projects (ores.refdata, ores.telemetry, ores.testing) have been updated to correctly reference the new ores.platform module where platform-specific functionalities are now located, ensuring proper linking and architectural representation.
- Codebase Migration: All existing code references to ores.utility::environment, ores.utility::filesystem, and ores.utility::net have been updated to point to their new locations within ores.platform::environment, ores.platform::filesystem, and ores.platform::net respectively, ensuring a seamless transition to the new modular structure.
COMPLETED Use chrono timepoints for domain entities code
Gemini:
This pull request undertakes a significant refactoring effort to enhance the modularity and clarity of the codebase by splitting the monolithic ores.utility module into more focused components. The primary goal is to separate platform-specific functionalities into a dedicated ores.platform module, thereby improving dependency management and making the architecture more maintainable and extensible. This change ensures that core utilities remain lean, while system-level interactions are encapsulated in their own distinct layer.
Highlights:
- New Module: ores.platform: Introduced a new C++ module, ores.platform, specifically designed to house platform-specific utilities and abstractions for OS and hardware interaction. This module includes functionalities for environment variables, filesystem operations, and network information.
- Refactoring of ores.utility: Key components such as environment variable handling, filesystem operations (file I/O, directory search), and network information (hostname, MAC address, process ID) have been extracted from ores.utility and moved into the new ores.platform module. The ores.utility module has been updated to reflect these removals and now focuses on more general-purpose utilities like logging, UUID generation, string manipulation, DateTime, Converter (Base32/Base64), and program options.
- Dependency Updates: Build configurations (CMakeLists.txt) and PlantUML diagrams across various projects (ores.refdata, ores.telemetry, ores.testing) have been updated to correctly reference the new ores.platform module where platform-specific functionalities are now located, ensuring proper linking and architectural representation.
- Codebase Migration: All existing code references to ores.utility::environment, ores.utility::filesystem, and ores.utility::net have been updated to point to their new locations within ores.platform::environment, ores.platform::filesystem, and ores.platform::net respectively, ensuring a seamless transition to the new modular structure.
- Previous analysis
Gemini made an interesting review comment for
projects/ores.accounts/include/ores.accounts/domain/account_role.hpp
/** * @brief Timestamp when this role assignment was created. */ std::string assigned_at;
For consistency with other domain event objects and for better type safety, consider using
std::chrono::system_clock::time_pointfor assigned_at instead ofstd::string. Storing timestamps as strings in domain objects can be error-prone and makes date/time arithmetic difficult. The conversion from the database string format can be handled in the mapper.Suggested change:
-std::string assigned_at; +std::chrono::system_clock::time_point assigned_at;
Claude agrees:
Using
std::chrono::system_clock::time_pointis architecturally better for several reasons:Advantages:
- Type safety - Compiler catches errors; can't accidentally assign arbitrary strings
- Time arithmetic - Easy to compute durations, compare timestamps
- Idiomatic C++ - Standard library type for time handling
- Self-documenting - The type itself conveys "this is a point in time"
Trade-offs:
- Requires conversion code in mappers (string ↔ time_point)
- Need to handle timezone consistently (UTC recommended)
- Serialization to JSON/protocol buffers needs explicit handling
My recommendation: I agree with the reviewer's suggestion. The conversion complexity is localized to mappers, and the benefits of type safety throughout the rest of the codebase outweigh the cost.
However, this should be done consistently across all domain types (accounts, roles, permissions, etc.), not just RBAC. Otherwise you'd have mixed patterns - some types using strings, some using time_point.
Good candidate for a separate PR that:
- Adds timestamp conversion utilities to the mapper infrastructure
- Updates all domain types to use time_point
- Updates all mappers consistently
This keeps the RBAC PR focused and makes the timestamp improvement a coherent, reviewable change.
COMPLETED Use prebuilt qt code
At present we are having problems creating an installable gui. This is because Qt is hard to build and package from vcpkg. We should use prebuilt binaries for all platforms.
Links:
COMPLETED Windows clang build failures code
Seems like we are failing with a SEGFAULT:
<Catch2TestRun name="ores.comms.tests.exe" rng-seed="1383371051" xml-format-version="3" catch2-version="3.11.0"> <TestCase name="test_client_server_connection" tags="[networking][#net_client_tests]" filename="D:/a/OreStudio/OreStudio/projects/ores.comms/tests/net_client_tests.cpp" line="97"> <Expression success="false" filename="D:/a/OreStudio/OreStudio/projects/ores.comms/tests/net_client_tests.cpp" line="161"> <Original> {Unknown expression after the reported line} </Original> <Expanded> {Unknown expression after the reported line} </Expanded> <FatalErrorCondition filename="D:/a/OreStudio/OreStudio/projects/ores.comms/tests/net_client_tests.cpp" line="161"> SIGSEGV - Segmentation violation signal </FatalErrorCondition> </Expression> <OverallResult success="false" skips="0" durationInSeconds="2.17718"/> </TestCase>
COMPLETED Add flags for currencies code
Add flags for the currencies. Need database support. Display them in the currencies dialog.
Gemini PR summary:
This pull request introduces a foundational ores.assets component, establishing a comprehensive system for managing dynamic assets within the application. It provides structured domain models for images, tags, and their relationships, backed by a bitemporal database design that supports versioning and historical tracking. The new component includes a full data access layer with mappers and repositories, complemented by synthetic data generators and extensive test coverage to ensure its stability and functionality.
Highlights:
- New Component: ores.assets: Introduced a new component, ores.assets, dedicated to dynamic asset management, particularly for images and their associations.
- Domain Models: Added core domain models including image (for SVG content), tag (for categorization), image_tag (for many-to-many relationships), and currency_image (to link currencies with their flags).
- Bitemporal Database Support: Implemented robust bitemporal database tables (images, tags, image_tags, currency_images) with valid_from and valid_to timestamps, triggers for versioning, optimistic locking, and soft deletes, ensuring historical data integrity.
- Repository Layer: Developed a complete repository layer with mappers and repository classes for each domain model, facilitating CRUD operations and data persistence.
- Synthetic Data Generators and Tests: Included generators for synthetic data for all new domain models and comprehensive test suites for the repository classes, ensuring the reliability and correctness of the data access layer.
- SQL Schema and Utilities: Provided detailed SQL scripts for creating and dropping the new asset-related tables, along with a utility function (load_flag) to easily load SVG flag images into the database.
Previous analysis
Actually it is better to have a generic mechanism to upload an SVG and maybe tag it with an identifier. Then we could have a way to associate a currency with one of the available SVGs. The currency dialog could have a tab where users can select the SVG from a list. We can then have a table with SVG for currency which remembers these. This provides a generic solution for all cases where we have some kind of asset and an associated image.
SQL:
-- Ensure you have the necessary extension for generating random UUIDs CREATE EXTENSION IF NOT EXISTS pgcrypto; -- 1. icons table: Stores the SVG data CREATE TABLE icons ( -- Primary key using UUID (GUID) icon_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), -- Unique key used by the application (e.g., 'usd_flag', 'btc_symbol') key VARCHAR(100) UNIQUE NOT NULL, -- The entire SVG content stored as plain text svg_data TEXT NOT NULL, -- Optional timestamps created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- Index the 'key' column for faster lookups CREATE INDEX idx_icons_key ON icons (key); --- -- 2. tags table: Stores the list of available categories CREATE TABLE tags ( -- Primary key remains SERIAL as tags are usually created centrally tag_id SERIAL PRIMARY KEY, -- The name of the tag (e.g., 'currency', 'flag', 'commodity') name VARCHAR(50) UNIQUE NOT NULL ); -- Index the 'name' column for quick lookups and joins CREATE INDEX idx_tags_name ON tags (name); --- -- 3. icon_tags table: Junction table for the many-to-many relationship CREATE TABLE icon_tags ( -- Foreign key to the icons table (now a UUID) icon_id UUID NOT NULL REFERENCES icons(icon_id) ON DELETE CASCADE, -- Foreign key to the tags table (remains INTEGER) tag_id INTEGER NOT NULL REFERENCES tags(tag_id) ON DELETE CASCADE, -- Ensures that each icon/tag combination can only exist once PRIMARY KEY (icon_id, tag_id) ); -- Optional: Create a separate index for lookups by tag CREATE INDEX idx_icon_tags_tag_id ON icon_tags (tag_id);
COMPLETED Add skills for code review code
This pull request significantly expands the project's internal documentation by introducing several new 'skills' designed to standardize and improve development workflows. It provides structured guidance for the initial design phase, detailed checklists for both granular pull request reviews and comprehensive component audits, and a crucial meta-skill for ensuring the quality and consistency of the documentation itself. These additions aim to foster more robust, maintainable, and well-understood code development practices.
Highlights:
- New Brainstorming Skill: Introduced a comprehensive skill for structured brainstorming and design, guiding users through understanding ideas, exploring approaches, presenting designs, and documenting outcomes.
- New Code Review Skills: Added two distinct code review skills: 'Code Review PR' for reviewing pull request changes and 'Code Review Component' for deep audits of entire components, covering aspects like technical debt, modernization, and convention compliance.
- New Skill Review Skill: Created a meta-skill dedicated to auditing and maintaining the quality, consistency, and accuracy of existing skill documentation, including checks for duplication and conflicts.
- Skill Catalog Update: The main skill catalog (claude_code_skills.org) has been updated to include and categorize all the newly added skills under 'Meta-Skills', 'Design', and 'Code Review'.
- Documentation Refactoring: The domain-type-creator skill was updated to replace explicit CMake build commands with a reference to the CMake Runner skill, promoting consistency and reducing redundant instructions across documentation.
COMPLETED Compilation fixes to current main code
Main is broken at present. Fix compilation and tests.
Gemini:
This pull request significantly improves the robustness and testability of the project. It addresses critical issues that could lead to test timeouts by ensuring the reliable generation of unique synthetic data. Furthermore, it resolves platform-specific build failures on macOS and expands the test suite with dedicated unit tests for key generator components, contributing to a more stable and well-tested codebase.
Highlights:
- Test Stability: Resolved potential infinite loops in unique synthetic data generation functions (e.g., for currency images, images, tags, and currencies) by implementing a suffix-based uniqueness mechanism when the faker library produces duplicate values.
- Cross-Platform Compatibility: Fixed macOS build errors related to std::chrono::system_clock::time_point construction by explicitly using std::chrono::duration_cast when converting from nanoseconds.
- Enhanced Test Coverage: Introduced new unit tests for tag, image, and currency_image generators to ensure their correct functionality, including single, multiple, and unique data generation scenarios.
- Standardized Testing Configuration: Centralized and updated Catch2 test arguments in the main CMakeLists.txt and individual project test CMakeLists.txt files for consistent reporting, specifically changing the XML reporter syntax.
BLOCKED Ignore warnings on windows and OSX code
At present we have a number of spurious warnings on both windows and OSX. Try to see if we can get CDash to ignore them.
Notes:
- Raised a Kitware ticket.
Links:
COMPLETED Add sign-up workflow code
It should be possible to sign-up and create a new account.
Gemini:
This pull request introduces a comprehensive user self-registration feature, enabling new users to create accounts independently. It encompasses updates across the backend messaging system, a new service layer for robust validation and account creation, and a fully integrated user interface within the Qt client. The functionality is controlled by system-level feature flags, ensuring administrators can manage its availability and behavior.
Highlights:
- User Self-Registration (Signup) Workflow: Introduced a complete workflow for new user self-registration, allowing unauthenticated users to create accounts when enabled by a feature flag. This includes new messaging protocols, a dedicated service for handling signup logic, and a frontend UI in the Qt client.
- New Messaging Protocol and Handler: Added signup_request and signup_response messages to the accounts messaging protocol. The accounts_message_handler now includes a handle_signup_request method to process these messages, leveraging the new signup service.
- Dedicated Signup Service: A new signup_service has been implemented to encapsulate the business logic for user registration. This service performs crucial validations such as checking for enabled user signups, username and email uniqueness, and password policy compliance before creating new accounts.
- Qt Client Integration: The Qt client has been updated with a new SignUpDialog and a ClientManager::signup method. This provides a user-friendly interface for self-registration, including input validation and asynchronous communication with the backend.
- System Flags for Control: Enhanced system flags with user_signups to enable/disable the self-registration feature and signup_requires_authorization (though not yet implemented) to control whether new accounts need admin approval.
- Account Repository Enhancement: The account_repository now includes a read_latest_by_email method, essential for ensuring email address uniqueness during the signup process.
- Protocol Version Increment: The communication protocol minor version has been incremented to 13.1 to reflect the addition of new message types and error codes related to the signup workflow.
At present this fails:
2025-12-22 00:21:41.174342 [DEBUG] [ores.comms.net.server_session] Received message type signup_request (0x2030) 2025-12-22 00:21:41.174444 [DEBUG] [ores.comms.messaging.message_dispatcher] Dispatching message type signup_request (0x2030) 2025-12-22 00:21:41.174536 [WARN] [ores.comms.service.auth_session_service] Authorization failed for signup_request (0x2030) from 127.0.0.1:38118: not authenticated 2025-12-22 00:21:41.174576 [WARN] [ores.comms.messaging.message_dispatcher] Authorization denied for signup_request (0x2030) from 127.0.0.1:38118 2025-12-22 00:21:41.174620 [ERROR] [ores.comms.net.server_session] Message dispatch failed: 10 2025-12-22 00:21:41.175062 [DEBUG] [ores.comms.net.server_session] Sending error response: Authentication failed (correlation_id=1) 2025-12-22 00:21:41.175190 [DEBUG] [ores.comms.messaging.frame] Serialised frame error_response (0x4), size: 104 2025-12-22 00:21:41.175266 [DEBUG] [ores.comms.net.connection] Writing frame of size 104 type: error_response (0x4) sequence: 2 2025-12-22 00:21:41.175499 [DEBUG] [ores.comms.net.connection] Successfully wrote frame 2025-12-22 00:21:41.175569 [DEBUG] [ores.comms.net.server_session] Sent response for message type signup_request (0x2030) 2025-12-22 00:21:41.175636 [DEBUG] [ores.comms.net.connection] Waiting to read the next frame (skip_version_check=false) cancel_slot.is_connected=false 2025-12-22 00:21:41.180487 [ERROR] [ores.comms.net.connection] Network error in read_frame: stream truncated [asio.ssl.stream:1] 2025-12-22 00:21:41.180768 [INFO] [ores.comms.net.server_session] Client disconnected 2025-12-22 00:21:41.183120 [ERROR] [ores.comms.net.server_session] Exception in notification writer: co_await: Operation canceled [system:125] 2025-12-22 00:21:41.183430 [DEBUG] [ores.comms.net.server_session] Notification writer coroutine ended 2025-12-22 00:21:41.184552 [INFO] [ores.comms.net.server_session] Unregistering session '127.0.0.1:38118' from subscription manager 2025-12-22 00:21:41.184856 [INFO] [ores.comms.service.subscription_manager] Unregistered session '127.0.0.1:38118' (had 0 subscriptions, remaining sessions: 0) 2025-12-22 00:21:41.185205 [INFO] [ores.comms.net.server_session] Session ended for client: 127.0.0.1:38118 2025-12-22 00:21:41.185372 [DEBUG] [ores.comms.net.server] Session completed, active connections: 0
COMPLETED Implement RBAC enforcement code
Conversation with Claude:
RBAC permission checking is not yet implemented. The handlers currently use simple session->is_admin checks rather than checking permissions via the authorization_service.
For example in handle_lock_account_request:301:
// Current: simple admin check if (!session->is_admin) { ... } // Should be: permission check if (!auth_service_.has_permission(session->account_id, permissions::accounts_lock)) { ... }
The RBAC infrastructure exists (permissions, roles seeded in DB), but it's not being enforced. To properly test RBAC, we need to:
- Inject authorization_service into accounts_message_handler
- Replace is_admin checks with permission checks
- Store permissions in session (optional, for performance)
Would you like me to implement proper RBAC enforcement in the message handlers? This would involve:
- Adding authorization_service to the handler
- Checking specific permissions like accounts:lock, accounts:reset_password, etc.
- Non-admin users with the right role/permissions would then be allowed to perform those operations
> actually maybe we should split that into a separate PR as this one is already > very large. I'll merge it as is
● Good call. The current PR already includes:
- RBAC domain types (permission, role, account_role, role_permission)
- Database schema for RBAC tables
- authorization_service for managing permissions/roles
- rbac_seeder for seeding predefined permissions and roles
- Protocol messages for RBAC operations (list_roles, list_permissions, assign_role, etc.)
- Protocol version bump to 13.0
The follow-up PR would implement:
- Injecting authorization_service into message handlers
- Replacing is_admin checks with proper permission checks
- Testing non-admin users with specific role permissions
This keeps the current PR focused on RBAC infrastructure and the next one on enforcement.
Notes:
- add tests for all new entities. Code coverage has dropped a lot after adding them.
COMPLETED Add session information to database code
At present we register the last login etc. It would be nice to record every session as well, including the duration.
Notes:
- record bytes sent/received.
- keep track of geolocation so we know where users are logging in from.
- calculate statistical measures (average session duration, average bytes etc) and consider plotting them. Also in the aggregate so we can see patterns over time.
- keep track of the session id so we know what client we are using, the version etc. We should display this information in the accounts dialog.
- on the main accounts dialog we should show the number of open sessions.
COMPLETED Add UI for roles and permission management code
We added the core infrastructure but we need a way to manage it from Qt and from the shell.
COMPLETED Improve unit test coverage code
We are dipping below 70% once more.
This pull request significantly enhances the test coverage across several core components of the system. By introducing new unit tests for geolocation services, CSV export functionality, filesystem operations, session management, currency versioning, and feature flags, it aims to improve the robustness, reliability, and maintainability of the codebase. These additions ensure that various functionalities behave as expected under different scenarios, including edge cases and data serialization.
Highlights:
- Geolocation Service Tests: New unit tests for geolocation_service covering initialization, error handling for unloaded databases, move semantics, and the geolocation_result/geolocation_error structs.
- CSV Exporter Tests: Comprehensive tests for csv_exporter, ensuring RFC 4180 compliance and proper escaping of special characters like commas, quotes, and newlines, along with header validation and multi-currency exports.
- Filesystem File Operations Tests: Extensive unit tests for filesystem::file operations, including reading/writing content, directory traversal, finding files, upward file searching, remove operations, and recreate_directory functionality.
- Session Domain Tests: Added tests for the session domain, verifying active status detection, duration calculation, JSON serialization, and the session_statistics struct.
- Currency Version JSON I/O Tests: Unit tests for JSON serialization of currency_version and currency_version_history objects, ensuring correct data representation.
- Feature Flags I/O Tests: Tests for feature_flags JSON and table I/O operations, including the print_feature_flags_table function and handling of special characters.
COMPLETED Incorporate new telemetry component code
Gemini:
This pull request establishes the foundational telemetry framework for the application by introducing a dedicated ores.telemetry module. It systematically migrates all existing logging functionalities to this new module and lays out a clear roadmap for implementing distributed tracing and OpenTelemetry integration. The changes ensure that the application's observability capabilities are enhanced and future-proofed, allowing for better monitoring and debugging of distributed systems.
Highlights:
- New Telemetry Component: A new ores.telemetry component has been introduced to centralize all telemetry-related functionalities, including logging and distributed tracing.
- Logging Infrastructure Migration: The existing logging infrastructure, previously located under ores.utility/log, has been fully migrated to the new ores.telemetry/log module. This involves updating include paths and namespace declarations across numerous files.
- Distributed Tracing Roadmap: The product_backlog.org document has been updated with a detailed plan for implementing distributed tracing. This includes tasks for instrumenting key components, propagating trace context in the messaging protocol, and establishing span collection and export infrastructure, including an OpenTelemetry Protocol (OTLP) exporter.
- Boost.Log Integration with Telemetry: New internal components like boost_severity, macros.hpp, and telemetry_sink_backend have been added to seamlessly integrate Boost.Log with the new telemetry system, allowing for automatic extraction of trace and span IDs from log records.
- File Log Exporter: A file_log_exporter has been added, implementing the log_exporter interface, to export log records in JSON Lines format, suitable for external log processing tools.
COMPLETED Refactor SQL code code
At present we have too many files, scattered around the sql directory. We need to add some kind of structure to it.
Gemini (only captures last tasks):
This pull request significantly enhances the project's documentation and modeling capabilities by integrating a new set of SQL recipes, a dedicated skill for authoring and maintaining these recipes, and detailed documentation for the ORES database schema. The changes aim to provide clear, executable examples for database interaction and establish a structured approach for expanding and maintaining documentation.
Highlights:
- Comprehensive SQL Recipes: Introduced a new, extensive set of SQL recipes providing executable examples for querying and managing the ORES database, covering accounts, RBAC, currencies, feature flags, sessions, and administrative tasks.
- Recipe Authoring Skill: Added a new 'Recipe Author' skill that guides users on how to create new recipe files and recipe-updating skills, ensuring consistency and best practices for executable documentation.
- Detailed SQL Schema Documentation: Integrated comprehensive documentation for the ORES Studio SQL Schema, detailing its architecture, bitemporal design patterns, database creation processes, and directory structure.
COMPLETED Add session recording support to comms code
We need to be able to record a client session in the socket.
COMPLETED Replace MaxMind implementation code
This pull request effectively replaces the MaxMind GeoLite2-City database with ip2country data, simplifying the geolocation system to be country-level only. The changes are consistently applied across the C++ code, SQL schema, tests, and documentation. The new SQL import script and schema are well-structured for the new data source. The review identified a critical SQL injection vulnerability in the C++ code and a high-severity bug in a new PostgreSQL function that fails to handle IPv6 addresses, which is a regression from the previous implementation. Detailed comments and a code suggestion are provided to address these issues.
COMPLETED Consider exposing end points via HTTP code
This pull request establishes a foundational HTTP server component, ores.http, and a corresponding executable, ores.http.server, designed to power RESTful APIs. Leveraging Boost.Beast for high-performance asynchronous operations, the new infrastructure provides essential features such as JWT-based authentication, dynamic routing with path parameter extraction, and comprehensive OpenAPI documentation with an integrated Swagger UI. It also includes a message adapter to seamlessly integrate with existing binary message handlers, promoting code reuse and a unified backend architecture.
Highlights:
- New HTTP Server Infrastructure: Introduction of the ores.http library and ores.http.server executable for building robust RESTful APIs using Boost.Beast.
- JWT Authentication Middleware: Integrated middleware for JWT token validation (HS256 and RS256) utilizing the jwt-cpp library.
- OpenAPI and Swagger Support: Automatic generation of OpenAPI 3.0 JSON specifications and a built-in Swagger UI for interactive API documentation.
- Flexible Routing with Path Parameters: Implementation of a fluent API for defining HTTP routes with dynamic path parameter matching capabilities.
- CORS Management: Configurable Cross-Origin Resource Sharing (CORS) support to facilitate secure interactions with web clients.
- HTTP Message Adapter: A mechanism to bridge incoming HTTP requests to existing binary message handlers, promoting code reuse and a unified backend architecture.
Having a binary protocol is helpful for performance but it may make life easier to expose some functionality via HTTP.
Links:
- GH: beauty: "Beauty is a layer above Boost.Beast which provide facilities to create Http server or client. Beauty allows the creation of synchronous or asynchronous server and client, and adds some signals and timer management based on Boost.Asio"
- Boost beast examples
- Boost JSON
Merged:
Create HTTP end point for currencies
Add a basic HTTP server using boost beast. Then we just need a couple of verbs:
- GET: return all currencies in database.
- POST: add one or more currencies.
COMPLETED Setup basic Wt infrastructure code
This pull request lays the groundwork for a new web-based interface for ORE Studio, named ores.wt. It integrates the Wt C++ web toolkit to enable browser-based access and direct interaction with existing ORE domain types. The changes establish the core project structure, build configurations, and a minimal working Wt application, along with initial testing and modeling setups.
Highlights:
- New ores.wt Component: Introduces a new ores.wt project, designed as a web component using the Wt C++ web toolkit, intended to provide a browser-based interface for ORE Studio.
- Initial Project Structure: Establishes the basic directory and build system (CMake) structure for the ores.wt component, including src, tests, and modeling subdirectories.
- Wt Web Application Setup: Implements a minimal Wt application (main.cpp) that displays a welcome message, serving as the entry point for the browser-based interface.
- Build System Integration: Updates the root CMakeLists.txt to include the new ores.wt project and configures its build process, linking against Wt and other ORE libraries.
- Testing Framework Integration: Sets up a testing environment for ores.wt using Catch2, including a basic stub test to ensure the framework is functional.
- Dependency Management: Adds the wt library as a new dependency in vcpkg.json, ensuring the necessary web toolkit is available for the project.
- Modeling with PlantUML: Includes initial PlantUML configuration and a diagram to visualize the ores.wt component's role and structure.
COMPLETED Document namespaces for doxygen code
This pull request standardizes and expands the Doxygen documentation for C++ namespaces across the project. It establishes a clear naming convention for documentation headers, updates the component creation guide to reflect this new practice, and adds a significant number of new documentation files for both main components and their sub-namespaces, ensuring comprehensive and consistent API documentation.
Highlights:
- Standardized Namespace Documentation: Introduced a new formalized naming convention for Doxygen namespace documentation headers: "ores..hpp" for main components and "ores…hpp" for sub-namespaces.
- Updated Component Creation Guide: The component-creator skill documentation has been updated to include a new "Step 4: Create the namespace documentation header" with a template for these new files, and subsequent steps were renumbered.
- Naming Convention Fix: Renamed ores.iam/ores.accounts.hpp to ores.iam.hpp to conform to the new standardized naming convention.
New Main Component Documentation: Added main documentation headers for 5 previously missing components: assets, comms.analyser, geo, platform, and telemetry.
- Extensive Sub-Namespace Documentation: Created approximately 60 new sub-namespace documentation headers across various components, covering facets like domain, service, repository, messaging, eventing, config, app, generators, security, export, log, net, filesystem, environment, time, csv, orexml, convert, faker, program_options, rfl, streaming, string, uuid, and version.
- Consistent Header Content: Each new documentation header includes a GPL license, a Doxygen @brief description of the namespace's purpose, and an empty namespace declaration for Doxygen association.
COMPLETED Fix compilation issues in main for Wt and HTTP code
This pull request primarily focuses on resolving compilation and linking errors, along with correcting several API mismatches and logical inconsistencies within the HTTP server. It introduces new service layers for asset and currency management, refines the reflection mechanism for OpenAPI specifications, and strengthens the build process for the ores.wt component by addressing transitive dependency linking and symbol visibility.
Highlights:
- New Service Layer Classes: Introduced dedicated service layer classes, assets_service and currency_service, to encapsulate business logic for asset and currency management, respectively.
- HTTP Route API Mismatches Fixed: Resolved numerous API mismatches and logical inconsistencies across several HTTP routes, including authentication (login, signup), account management, feature flags, and currency operations.
- RFL Reflection Issue Resolution: Fixed a reflection issue with the RFL library by moving OpenAPI specification structures from an anonymous namespace to a named detail namespace, ensuring proper serialization.
- ores.wt Build and Linking Enhancements: Addressed linker errors in the ores.wt component by converting it to a static library and explicitly linking all of Wt's transitive dependencies (e.g., Freetype, Pango, Harfbuzz) in its CMakeLists.txt.
- Application Context Refinements: Refactored the database context initialization and service seeding logic within application_context.cpp for improved clarity and correctness.
COMPLETED Clean up test databases code
Sometimes we end up with a few test db's left:
template1=> \l
List of databases
Name | Owner | Encoding | Locale Provider | Collate | Ctype | Locale | ICU Rules | Access privileges
-------------------------+----------+----------+-----------------+-------------+-------------+--------+-----------+-----------------------
oresdb_test_210496_4571 | ores | UTF8 | libc | en_US.UTF-8 | en_US.UTF-8 | | |
oresdb_test_214711_1947 | ores | UTF8 | libc | en_US.UTF-8 | en_US.UTF-8 | | |
oresdb_test_215309_7714 | ores | UTF8 | libc | en_US.UTF-8 | en_US.UTF-8 | | |
oresdb_test_216112_5205 | ores | UTF8 | libc | en_US.UTF-8 | en_US.UTF-8 | | |
oresdb_test_216966_9268 | ores | UTF8 | libc | en_US.UTF-8 | en_US.UTF-8 | | |
postgres | postgres | UTF8 | libc | en_US.UTF-8 | en_US.UTF-8 | | |
template0 | postgres | UTF8 | libc | en_US.UTF-8 | en_US.UTF-8 | | | =c/postgres +
| | | | | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | libc | en_US.UTF-8 | en_US.UTF-8 | | | =c/postgres +
We should have a script that tidies these up.
Footer
| Previous: Version Zero |