Task: Build the cut take and its authorisation
Table of Contents
This page documents a task in the Rework the market data feeds into a market data service with adapters — the remaining work story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
A person takes a cut through the take flow, the body is assembled with its gaps, the take writes the cut and raises the authorisation request, and the cut records it.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Rework the market data feeds into a market data service with adapters — the remaining work |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-10-31 |
3. Acceptance
- The take flow assembles the body from the reads that exist, names each gap, and writes nothing until the take.
- The take writes the cut with the kind's retention and raises the approval request of the kind's approval kind, with the cut's detail keyed by the request.
- The cut record shows the acts and links the request.
- The screens and the tests are green, and a cut taken live is recorded and requests its authorisation.
4. Plan
The work follows the platform's own order: the model, then the store, then the operations, and the screens last.
- The cut's approval detail is a codegen entity in the reporting component: the cut the request authorises, the counts of the body's parts as the take counted them, and the applied facts. Its `request_id` is the natural key, so a request authorises one body, and it is client read only, so the take writes it and the apply stamps it.
- The assembly is a pure function over the facts the reads answer: a part is closed when a read answered it and a gap stands with the item, the reason and the remedy when it did not. That keeps the rule that a gap stops the press testable without a database.
- The reads are the components' own operations, called with the caller's Authorization header: trading's list at the as-of, market data's published sets, compute's app versions, and this component's own configuration rows.
- The take is one operation, `reporting.v1.ops.take_cut`, serving the preview and the press as the resolution serves its own two callers. It writes the cut through `plan_take` and raises the request in the same transaction as the body, with the detail row keyed by the request.
- The record read answers the detail beside the gaps, so the page states who waits without reading an inbox it may not see.
- The screens: the take flow with its rail, the list's take button gated on the permission, and the authorisation tab's subject panel.
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, it is in evidence/cut_take_live.txt and
named in the Command column.
| What | Value | Command | Commit |
|---|---|---|---|
| Reporting core cases | 243 cases, 1350 assertions, all passed | `./build/output/linux-clang-release-ninja/publish/bin/ores.reporting.core.tests` | 276b1e4b60 |
| The take's own cases | 20 cases, 136 assertions | the same binary with `[cut_assembly],[cut_take]` | 276b1e4b60 |
| Reporting service cases | 10 cases, 26 assertions, all passed | `./build/output/linux-clang-release-ninja/publish/bin/ores.reporting.service.tests` | 276b1e4b60 |
| BFF tests | 1195 tests, all passed | `npm test –workspace @ores/bff` | 8ef7b06362 |
| Web tests | 2392 tests, 2391 passed, 1 failed and inherited from main | `npm test –workspace @ores/web` | 8ef7b06362 |
| Live evidence | see `evidence/cut_take_live.txt` | the BFF at :21402 as henry.jones | a8c2b6617b |
The one web failure is `src/journeys/parts.test.tsx`, which asks the tenant form for "Empty operational uses its standard settings". The form stopped drawing that sentence in `5018f2a25b`, which is an ancestor of `origin/main`, so the failure is main's and not this branch's. It is left standing rather than edited here, because whether the sentence returns or the test goes is the tenant journey's call.
6. Notes
6.1. The environment holds no published curve set
`ores_marketdata_curve_publishes_tbl` is empty, so the market data part of every body stands as a gap and no hand take in this environment can reach the press that raises a request. That is the design's own gap ("a series with no value at or before the instant"), drawn with its remedy, and the flow states it. The request path itself was proven by the integration suite against the same database; the evidence file names the rows.
6.2. The take's reads run as the person
The caller's Authorization header travels with the parts' reads, so a person who may take a cut must be able to read what the body names: the engine version is compute's read, and the subject a request names is the detail row's. Both are granted where the take is, to the Finance role.
6.3. The assembly states what the store does not keep, and does not gap on it
No read materialises a copy of a deal population, a fixed market data snapshot, or the revision of the services that assembled the body. A body that refused over each of them could never be taken, so each part says so beside itself (`snapshot_note`) and the take records the parts it answered. A gap stands only where a read answered "nothing there" — the design's own gap table.
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 |
|---|---|
| #4314 | [reporting] Take a cut and raise its approval |
9. Review
| Comment summary | File | Decision | Notes |
|---|---|---|---|
10. Result
The take exists, it raises the authorisation it is for, and this pass closed the two-axis review of it.
- The subject of a cut's approval request is a codegen entity in the reporting component: the cut, the counts of the body's parts, and the applied facts. It is client read only, its request id is its natural key, and its SQL is applied to the development database additively and carried in the seeds.
- The assembly answers six parts: the kind and its retention, the deal population, the published sets in use, the versions in force, the engine and the code, and the taking identity. It records every part it could not fill as a gap with the item, the reason and the remedy, and the rule is a pure function, so it is tested without a store.
- A gap is not a hole. The design's gaps are the four a read answers "nothing there" for: a series with no value, a deal with no version, a curve nobody approved and an engine version nothing recorded. A day on which nothing traded is a body whose count is zero, and it closes.
- The take is one operation, `reporting.v1.ops.take_cut`, serving the flow's preview and its press. It writes the body through `plan_take` — the kind's retention, its destination and its authorisation basis copied, the take ordinal, the taker and the instant set — and, where the kind names an approval kind, raises the request in the same transaction with the cut's detail row keyed by it. A kind that names no approval kind records that none was required.
- The ordinal counts the day, the kind, the party, the scope and the centre, and it is read inside the write's own unit of work. Two takes of one occasion at two instants of one day carry `.1` and `.2` in their labels, and two takes of one occasion cannot read one count and write one ordinal.
- A body with a gap is kept as an incomplete draft that raises nothing and answers `ok`. A take the service refuses answers with its outcome's code and one sentence, both in `result`; there is no second field for a refusal, so no caller reads two answers to one call.
- The record read answers the detail row beside the gaps, so the page states who waits without reading the inbox. The page does not draw an Applied panel: the apply that would stamp it is not built, and the section says so.
- The permission is `reporting::cuts:take`. The handler checks it, the list's Take button is drawn only to a holder, and the take route and the flow check it too, so a saved link draws no Assemble and no press to a person who may not. The deciders are the kind's own, `inbox::approvals:decide_finance` for the close.
- The queue names a cut's authorisation request through its own descriptor, in the three locales. Nothing answers a cut by the request that raised it, so the request page says where the body is read and links it not.
Left to the next unit: the decide and the apply. The inbox decides, and the reporting side stamps the cut's authorisation by reconciliation over the request's state — the detail row's `applied_at` is the marker it will write, and nothing writes it yet.
Left open by the environment: a published curve set, without which no hand take can raise a request here; and the run's cut selection, which is the report journey's.
11. What the branch holds
The branch's history holds two `[synthetic]` commits, and neither leaves a change in the tree:
- `e83da91dec` `[synthetic] Build the inflation swap the planner draws` adds the inflation branch to the rate planner's visitor, because the component did not compile without it.
- `14efb501a6` `[synthetic] Take main's planner, the repair landed upstream` removes those two lines again, because the same repair landed on main.
So the branch holds no synthetic change, and its history holds both commits. An earlier version of this record said the two local synthetic repair commits had been dropped, which is not what the history shows.