Task: Import a run's configuration through a service operation and the shell
Table of Contents
This page documents a task in the Model the ORE report configuration as entities story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
A user loads a run's configuration into a report definition, and reads it back, without writing code.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Model the ORE report configuration as entities |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-10-04 |
3. Acceptance
- A service operation imports an ORE input directory's files against a report definition under the caller's session, and returns what was stored and what was not.
- A shell command imports a directory and exports a definition to a directory.
- The handler's permission is seeded.
- The import runs as a workflow saga over the owning services: a failure in any step compensates the steps before it, so no partial run stays behind, and two imports into one report definition cannot both store a run document (raised in the review of PR #2624).
4. 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.)
5. Measurements
Every number this task claims about a tree, with the command that produced it
and the commit it was measured at. A number without both is not a measurement,
because a clean-up record describes a tree and trunk moves under a branch: a
consumer count, a gate's component count and a suite's size all change with no
code changing, and the reader of a bare number cannot tell which tree it came
from. Where the raw output matters, put it in an evidence/ file beside the
task and name that file in the Command column.
| What | Value | Command | Commit |
|---|---|---|---|
6. Notes
Raised on 2026-10-04 from the open items left after Import a run's configuration from an ORE input directory and Produce the engine's input from the entities.
7. Test Scenarios
Manual QA scenarios (scaffolded via compass add test_scenario)
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 |
|---|---|---|
8. PRs
| PR | Title |
|---|---|
| #2647 | [ore,shell] Import a run's configuration through a saga over its owners |
9. Review
| # | Comment summary | File | Decision | Notes |
|---|---|---|---|---|
| 1 | A failed re-import can delete content that existed before it | run_configuration_operations.cpp | Decline | Reporting refuses a save into a definition that already holds a run document, which is the import's first write; every other document lands in a new configuration with a new header, so nothing that existed is replaced. Conventions are replaced by id and not undone, as the PR states. |
| 2 | The workflow request holds the bearer token and the files; a large input exceeds the NATS payload | run_configuration_handler.cpp | Accept, in part | The token travels in the request exactly as the ORE trade import's does. The payload limit is real: the shell refuses an input over 900 KB with the reason, and Carry a run's input through object storage removes the limit and the files from the request. |
| 3 | Thin request validation | run_configuration_handler.cpp | Accept | The import and export refuse an id that is not a uuid, and the import refuses an empty name, before the workflow starts. |
| 4 | A bind can outlive a failed store | run_configuration_operations.cpp | Accept | It cannot: deleting the run document deletes every binding and its configuration row. A comment now says so. |
| 5 | with_header copies the document | run_configuration_operations.cpp | Accept | Returns a reference. |
| 6 | stamp_document is untested | handler_helpers.hpp | Accept | A unit test covers rows on their own, in a vector of optionals, and a leaf left alone. |
| 7 | Two bindings naming one file overwrite each other | run_configuration_operations.cpp | Decline | A run setup names one file per configuration type, and a definition fills each slot once. |
| 8 | No failure-injection test of import and export | run_configuration_operations.cpp | Decline here | The operations call the owners through the concrete NATS client; a test would need it injected. The live run covers the happy path. |
10. Result
A run's configuration now imports and exports through the owning services, from the shell or any NATS client, without the ORE service touching another component's tables.
ores.ore.run_configuration_messages: the client import, which startsrun_configuration_import_workflowand answers with its instance; the workflow's execute and rollback messages; and a synchronous export.- The execute step parses and maps every file first, saves the run document through reporting, then binds a configuration through reporting and saves each document through its owner, as the caller. A failure part way deletes what the step stored; the rollback, which the engine sends as compensation, does the same from the step's result. The export reads the run through reporting and each document through its owner, and rebuilds the files.
nats_callmoved to a shared header, so the trade import and the run import call the owners the same way.- The live run exposed that the document services stamped only the party: a
live tenant refuses a row with no modified_by, while the test tenants, which
have no user accounts, accept one.
stamp_documentinores.servicestamps every row of a document with the session's party and audit fields, and every document service uses it. - The shell's
ore import-runwaits for the workflow;ore export-runwrites the files. The recipe records the live run.
Live, against Acme Corporation: ORE-Python Example_1 imported into Acme Corporation Plc's NPV definition and exported back; pricing engines, today's market and the run document matched, the curve configuration differed only in how two tolerances print, and the conventions held all but the FX convention, which has no store yet. ctest 90/90 after a database recreate.