Story: Standardise the curve configuration's parameters on the one contract
Table of Contents
This page documents a story in Sprint 29. It captures the goal, current status, acceptance criteria, and the tasks that compose it.
1. Goal
A curve configuration is drawn like every other configuration that comes off an ORE document. Its leaves are documented once, in the ORE parameter contract, keyed by curveconfig.xsd and XPath; its sections and entry elements come from data; and a person reads and changes a curve's leaves with the shared switch, documentation panel, value in force and control that a product parameter, an engine run setting and a convention term already use. Nothing about a curve section is restated in code.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent sprint | Sprint 29 |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-10-30 |
3. Acceptance
- Every leaf of curveconfig.xsd that ORE reads has a documentation entry in the ORE parameter contract, keyed by its schema and XPath, with a value set, or a recorded reason it is not documented.
- The curve sections and their entry elements are read from the curve_section data, so no screen holds a table that names them.
- A curve definition's leaves are drawn with the shared leaf parts: the Simple and Advanced switch, the documentation panel, the value in force and the control its value set gives.
- The curve configuration page follows the configuration screen standard: Details, one tab per section in the declared order, Used by and History, with a curve entry drawn as a collection row.
- A write whose value lies outside its leaf's value set is refused on the server, so every client gets the same answer.
4. Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|
| Scaffold story: Standardise the curve configuration's parameters on the one contract | DONE | 2026-10-26 | 2026-10-26 | Story scaffolding rides this task: documents, sprint wiring, and the scaffold PR. Close it before merging that PR. |
| Bring curveconfig.xml onto the one contract | DONE | 2026-10-27 | 2026-10-27 | Initial task for: Standardise the curve configuration's parameters on the one contract |
| Document the curve configuration leaves in the one contract | DONE | 2026-10-26 | 2026-10-27 | Give every leaf of curveconfig.xsd that ORE reads a documentation entry and a value set in the ORE parameter contract, extracted from the ORE source and the guide with provenance per row, so a curve screen can read its words from data rather than hold them. |
| Give the curve configuration leaves their value sets | DONE | 2026-10-27 | Link every documented curve configuration leaf to a value set: a currency, a calendar, a day counter or an index draws on a refdata catalogue, a value an ORE parser maps takes that parser's list, and the rest take their type, so a screen draws the control from it and the write path can refuse a value outside it. | |
| Draw the curve configuration page with the shared leaf parts | DONE | 2026-10-27 | 2026-10-27 | Give the curve configuration a page that follows the configuration screen standard: Details, one tab per section in the declared order, Used by and History, each curve entry drawn as a collection row whose leaves use the shared switch, documentation panel, value in force and control. The sections come from curve_section, so the page restates nothing about a family. |
| Map the curve configuration columns to their leaves | DONE | 2026-10-29 | 2026-10-29 | The value-set guard already exists: ores_reporting_value_in_set_fn is the one rule and a generated trigger joins a column-to-leaf map to it. No map covers the curve tables, so a curve value in a typed column is unchecked. Add the map and attach the trigger, so a curve value outside its leaf's set is refused on write. |
| Draw the nested collections of a curve entry | DONE | 2026-10-29 | 2026-10-30 | A curve entry holds child elements of its own: Segments, Quotes, BootstrapConfig, Report, VolatilityConfig and their parts. The page names each block and stops there. Give each block the collection shape the configuration screen standard states, so its rows are read with the same leaf parts. |
| Let a person change a curve parameter | DONE | 2026-10-28 | 2026-10-28 | The curve configuration page reads a document of thirty-four families and writes nothing. A write must change one leaf without dropping the rows the page does not draw, refuse a value outside its leaf's set, and follow the lifecycle the configuration screen standard states. Give the page its edit path once the guard covers the curve tables. |
| Let a signed-in person open a curve configuration | DONE | 2026-10-27 | 2026-10-27 | The curve page is merged, but a person who signs in cannot open it: the read of a curve document is refused, and the address refuses the identifier the ORE import mints. Grant the reads a person's screen needs, accept the identifiers the import writes, and test both. |
| Draw the curves tab of the curve configuration | DONE | 2026-10-27 | 2026-10-27 | The page draws one tab per section, nineteen of them and usually fifteen empty. Replace them with the shape the product pricing screen uses for its products: one Curves tab, a searchable rail of curves grouped by the section that declares them, and the chosen curve's parameters in a workbench beside it. |
| Show a curve's documentation once | DONE | 2026-10-27 | 2026-10-27 | The workbench draws a leaf's help under its value and the same sentence again in the documentation panel, because for a curve the guide supplies one sentence as both help and description. The documentation belongs in the panel it is collapsed under, as the leaf standard states, so the row shows the label and the value and nothing else. |
| Carry the curve and report screens through the UX review | DONE | 2026-10-27 | 2026-10-28 | The owner's review of the two screens: a curve's documentation shows its help twice and never lists the values a closed list accepts; the report page calls its first tab Definition and carries a latest-run card that the runs tab already covers; the report's configurations deserve a tab with a sentence per kind; and a multi-party reader sees copies of the same report with no party on the row. |
| Document the curve segment and quote leaves | DONE | 2026-10-29 | 2026-10-29 | The curve configuration chapter documents every segment and quote leaf in prose and XML listings, but the term extractor reads only the parameterisation chapter, so 15 segment leaves and 3 quote leaves reach the contract with no words. The screen cannot draw a leaf the contract does not describe. Curate those leaves from the chapter that documents them, so the contract covers every leaf a segment holds. |
| Retire the curve parameter paths the schema does not declare | DONE | 2026-10-30 | 2026-10-30 | The parameter contract keys a curve leaf by its XPath, and every reader resolves that path against the document. Five paths name an element their parent does not declare: four from a block the extractor attributes to the wrong sibling class, and one the ORE schema omits where the ORE code reads it. A path that matches nothing describes a leaf no document holds. |
| Draw the quotes a curve segment holds | DONE | 2026-10-30 | A segment is mostly its quotes, and the page draws none of them: a quote's value is the Quote element's own text rather than a named child, and the list element that holds it varies by segment kind, so the collection rule the segments use does not carry over. Give the quotes their own shape and draw them under the segment that holds them. | |
| Generate the curve collection wiring | DONE | 2026-10-30 | 2026-10-30 | The page's section wiring is generated from the projection, but the child collections are a hand-written table in the BFF, because a segment leaf's path depends on the kind the row states and the wiring has no shape for that. Teach the generator to read import_segments and the quotes that follow each kind, and emit the rules the BFF now holds, so the store, the generator and the page are one source again. |
| Collect the snags from testing the curve screens | DONE | 2026-10-30 | 2026-10-30 | The curve screens were walked in a browser, and the walk left a QA scenario a person can repeat plus the defects it found. |
| Record the leaves a segment inherits | DONE | 2026-10-30 | 2026-10-30 | A segment reads six leaves from its base class before its own, and the extractor took a class's base from the same file it read. Read the base map across every file, so the contract carries the six and a segment stops showing its conventions as a gap. |
| Guard the shell's command units | DONE | 2026-10-30 | 2026-10-30 | Two branches wired the legal entity unit, the merge kept both registrations, and ores.shell stopped at start-up. State the guard's two rules over the source, so the next merge fails a check instead of a person. |
| Curate the shared segment leaves | DONE | 2026-10-30 | 2026-10-30 | Task for: Standardise the curve configuration's parameters on the one contract |
5. Decisions
- A save echoes the stored document and writes only the families it touched, decided 2026-10-28. A curve configuration is thirty-four families and the screen draws one entry at a time, so a document assembled from the screen would drop the rows it never read. The route reads the document, changes the named leaves and writes back those families, so a change to one curve leaves the other families at their versions. This also moved the edit (task CA40C9B0) ahead of the nested drawing (task 894F3A64): the echo is safe without it, and the contract documents 22 of the forty-odd leaves a segment holds.
A curve configuration's leaf is a parameter, decided 2026-10-26. Three words the leaf standard already spends do not serve this kind, and a fourth was rejected when the convention leaf was named.
Candidate Why it was not chosen setting Reserved to the engine run settings, the ORE Setupblock, by Configuration screen standard: "The word is not used for a parameter of any other configuration."term The conventions' word, and it collides with term structure, which is exactly what curveconfig.xmlconfigures.field Rejected when the convention leaf was named: "field is the record standard's word for any record and says nothing about ORE." entry Already the row: curve_definitionis "one curve entry", andcurve_section.entry_elementnames the entry element.option Already a thing inside a volatility config: the call or the put. attribute A leaf is an element or an attribute, so this word cannot name both. Parameter wins because the code already calls it that: the contract table is
ore_parameter, its docstring says "A parameter an ORE document accepts … a row documents one leaf of one ORE document", the configuration standard defines Parameter as "one leaf of an ORE document", and the generator that writes convention terms as contract rows isconvention_parameter_rows.py.The cost is one amendment. The ORE element and leaf screen standard defines Parameter narrowly, as "a leaf of a product or of the document's global parameters". The first task widens it to cover a curve configuration. No screen prints the word for this kind yet, so the amendment changes a definition, not a screen.
- The element type is the ORE entry element, read from
curve_section, decided 2026-10-26. That table already holds the container and the element its entries use:YieldCurvesholdsYieldCurve,CorrelationsholdsCorrelation. Its own model records nineteen sections across the seventy-sixcurveconfig.xmldocuments ORE ships; that count is the entity's claim, not a measurement this story has taken, and the extractor re-measures it in the first task. This is the shape the convention kind already has — a declaration in data that a screen reads and does not restate.curve_sectionis to this story whatconvention_kindwas to Draw every ORE leaf the same way. - The discriminator is not modelled yet, and the documentation does not wait
for it.
CurveTypedecides which leaves a yield curve may carry, and refdata holds no curve type today:yield_curve_configis one flat row of the union. The contract keys a leaf by its schema and XPath, and the XPath does not depend on the discriminator, so the documentation proceeds without it. Whether the discriminator joins the key as the element pair that OL-DOC-05 allows belongs to the task that moves the metadata into data. - This story does not own the structural refactor of the document. The
curve_configuration_documentis still one aggregate carrying 34 families, and that is Apply the same shape to the curve configuration document. The two tasks meet at the same document and do not block each other, because the contract is keyed by schema and XPath and not by the aggregate. - The column a leaf travels in is generated from the projection, decided
2026-10-27. A curve entry is spread over
curve_definitionand one family table, and the projection that reads and writescurveconfig.xmlis the only code that knows which column holds which element. The screen reads that fact frombff/src/curve-sections.generated.ts, whichgenerate_curve_section_parameters.pywrites out of the projection and checks againstcurveconfig.xsd: 250 columns of 22 tables across the 19 sections. The alternative, deriving the column from the element's name, is wrong forCurveId(acurve_id) and forYieldCurveDayCounter(aday_counter), and a hand-written table would drift from the projection in silence. The guard task emits the same map for the trigger, so one source serves both. - The curve page reads before it writes, decided 2026-10-27. A curve configuration is one document of thirty-four families and a save writes it whole, so a page that drew the leaves of one section and saved would drop every row it does not draw. No guard covers the curve tables yet either. The page therefore reads, and two tasks carry the rest: the nested collections and the write, which waits for the guard so that no client can store a value outside its leaf's set.
6. Out of scope
- Changing
curveconfig.xml, the ORE XSD, or the generated ORE model. - The structural split of the document by family, which the refactor task owns.
- Renaming a table, a configuration type code or an API route. The documentation and the screen words change; the model does not.