User Journey: Publish the approved set
Table of Contents
This page documents a user journey: A trader applies an approved candidate set so that the curve the system uses becomes the new one, and pricing and reporting see it from that moment.
A user journey describes what one person is trying to do, before anything is built. It is a design document that outlives any sprint, so it names the screens, the entity fields each screen shows, and the operations and messages each step needs.
1. Goal
"The decision has been made. I want the curve the desk uses to be this one now, and I want it to say who published it." The journey is done when the candidate set is the published curve, priced and reported from, and the act carries the name of the person who published it.
2. Actor and trigger
The actor is the trader who owns the curve. The trigger is a request that has reached its required number of approvals. The journey starts at the approved set and ends when the published version is visible to pricing and reporting. It follows Decide a publish; the request it applies was raised in Ask for a publish to be approved.
Publishing is a named, attributable act. The person who applies the approval is
recorded, and the moment the new version becomes visible is the moment of that
act. When the kind's approvals_required is zero, there is nobody to decide:
the raise is the publish, and the same operation applies it at once. When the
count is n, the publish applies only once n distinct approvals stand.
3. Steps
- Open the approved set. The trader opens Approvals or the curve and reads the set the approver said yes to. The system lists the approved requests with the curve each one is about.
- Read the approval. The system shows the request, who approved it, when, and the comment. The trader confirms that the required number of approvals stands before publishing.
- Read the points that will be published. The system lists the candidate
points the approval covers: each
oresmd_uri, its value and its source as the derivation wrote them. The trader reads exactly what is about to become live. - Apply the approved set. The trader chooses Publish approved set, naming the approved request, the curve configuration and the as-of. The system asks the approval record whether the request permits the publish, and refuses with the request's state when it does not. It also compares the subject: the request authorises one curve configuration at one as-of for one party, and a publish of another curve, another as-of or another party is refused with a message that names both subjects. When the subject matches and the request is approved, the system writes the published set and then records the act on the request's own detail row: the request that authorised it, the account that applied it, and the time. One request publishes once, so a second attempt is refused with the publisher and the instant the first one moved the set. A refusal leaves the curve as it was, so the published set moves only once approved.
- Watch the moment it becomes visible. The published version becomes the one pricing and reporting read, from the published time. The read that serves a curve states whether anybody has published it, when, by whom, and under which request, so a reader can tell the live set from a candidate that nobody has approved.
- Record who published. The act carries the publisher's name and the time, written on the same detail row that names the subject. The approval records who decided; the row records who applied the decision. The two are different people, and both are readable afterwards.
- Publish immediately when no approval is needed. When the kind's
approvals_requiredis zero, the raise is the publish and the set becomes live at once. No path applies a zero-approval request today; see What is missing. - Tell the consumers. The system tells the people and services that read this curve that a new version is live. No notification kind exists for a publish; see What is missing.
- Leave. The trader goes back to the curve, now showing the published version.
Step 4 is the moment. Before it, the candidate set is evidence the market or the recipe produced; after it, it is what the system uses. The publish record is what tells the two apart: a set with a published instant and a publisher is the one in use, and its request says which decision it stands on.
4. Screens and wireframes
One screen. The approval sits at the top, the points it covers sit beneath it, and the publish act and its effect on consumers sit at the bottom, so the trader reads what was approved and what would go live before the publishing control.
Figure 1: Publish the approved set: the approval, the points it covers, the publish act with its publisher, and the consumers that will see it.
The publish control is disabled while no publish operation exists, and the panel says why, so the trader is never left wondering whether the click failed.
5. Prototype
A static page at doc/prototypes/market_data/publish-the-approved-set/index.html: mock data only, no backend,
no build step and no session. It argues that publishing is the moment the candidate becomes what pricing uses, and the approval count decides whether a person stands in it.
- Variants
- a the set summary, b a per-curve list, c the publish with its notifications
- States
- zero (no approval configured), one, failed
- Source
doc/prototypes/market_data/publish-the-approved-set/index.html- Open
/OreStudio/doc/prototypes/market_data/publish-the-approved-set/once the site is built, or the file directly
6. Entities composed
| Entity | What it contributes | Model |
|---|---|---|
approval_request |
The approval being applied: the kind, who asked, and the state that says it is approved | ores.inbox.approval_request |
approval_kind |
How many approvals publish the set, and whether zero approvals publish at once | ores.inbox.approval_kind |
approval_decision |
Who approved, when and with what comment | ores.inbox.approval_decision |
market_series |
The curve that becomes the published one, and how it was derived | ores.marketdata.market_series |
market_observation |
The points the approval covers, and the rows the published version is read from | ores.marketdata.market_observation |
observation_lineage |
The recipe and source as-of the published points were built from | ores.marketdata.observation_lineage |
curve_publish |
The subject the request authorises, and the publication record: the request, the publisher and the instant | ores.marketdata.curve_publish |
notification_kind |
What kind of notice a publish sends, so consumers are told | ores.inbox.notification_kind |
notification |
The notice itself: who it is for and where it points | ores.inbox.notification |
A published curve has one entity: the curve_publish detail row of the
request that authorised it. The row names the subject from the raise, and the
apply stamps the publisher and the instant on that same row, so the published
set and the decision behind it are one record.
7. Operations and messages
| Step | Operation | Subject | Status |
|---|---|---|---|
| Open the approved set | List the approved requests of a kind | inbox.v1.approval_requests.list_by_kind_code |
exists |
| Read the approval | Read the request and its decisions | inbox.v1.approval_requests.get, inbox.v1.approval_decisions.list_by_request_id |
exists |
| Read the points | Read the candidates and the latest snapshot | marketdata.v1.market_observations.list_by_series_id, marketdata.v1.curve_snapshot.get |
exists |
| Apply the approved set | Publish the approved set as the curve the system uses | marketdata.v1.ops.publish_curve |
exists |
| Apply the approved set | Write the derived observations unconditionally | marketdata.v1.ops.republish_curve |
partial |
| Watch the moment | Read the published version a consumer sees, with its publisher and as-of | marketdata.v1.curve_snapshot.get |
exists |
| Record who published | Name the publisher and the time on the publication record | marketdata.v1.ops.publish_curve |
exists |
| Record who published | Read the publication record of a request | marketdata.v1.curve_publishes.list_by_request_id |
exists |
| Publish with zero approvals | Raise a request that is approved at once, then apply it | inbox.v1.ops.raise_approval with approvals_required 0 |
missing |
| Tell the consumers | Raise a publish notice to the consumers | inbox.v1.ops.raise_notification |
partial |
marketdata.v1.ops.publish_curve exists and carries the decision: a call that
names no approved marketdata.curve_publish request raises one and publishes
nothing, and a call that names an approved one writes the output. The call also
carries the subject. It reads the curve configuration and the as-of out of the
call, and the party out of the configuration, and refuses a publish that names
another curve, another as-of or another party than the request authorised. The
answer states the published instant and the publisher when it published, so the
caller reads what the record holds rather than its own clock.
marketdata.v1.ops.republish_curve still writes the derived observations with
no gate at all, and its own contract says so. It stays as the internal write the
gated operation calls, and is partial because a caller can still bypass the
decision by sending it.
inbox.v1.ops.raise_notification exists and is generic, but no market-data
notification kind tells it what a publish notice is.
8. What is missing
- There is no read of every published curve. A reader finds the published set of one series, and no read lists the tenant's published curves with their publishers. The candidate is a list over the publication records. Until then the screen reads one curve at a time through the snapshot read.
- There is no notification kind for a publish. Consumers are not told a new
version is live. The candidate is an
ores.inbox.notification_kindsuch asmarketdata.curve_published, withmessage_keyandmail_optional, seeded beside the kind that raises it. Until then the consumers panel states that nobody is told. The recipients, the trigger and what the notice carries are the decision The publish notice below. - Zero approvals have no path.
approvals_requiredis a count the kind carries, including zero, but nothing moves a zero-approval request to approved without a person. The candidate is the rule in the inbox service that a raise withapprovals_required0 closes the request approved at once, which then lets the owning publish apply it. Until then a kind that publishes immediately cannot be expressed. The rule, the actor and the record it leaves are the decision The zero-approval path below. - There is no candidate set to publish. The thing published would be a set of points with one as-of, and no entity holds it. The candidate is the candidate set of the first journey. Until then the publish names the curve configuration and the as-of, takes whatever the derivation wrote under them, and the record names that pair rather than a set identifier.
9. The decisions
9.1. The zero-approval path
9.1.1. The rule
approval_kind.approvals_required is a count on the kind, and zero is a count
like any other. When it is zero, nobody decides, and the raise is the publish.
One operation performs the whole act: marketdata.v1.ops.publish_curve, called
with the configuration and the as-of and no approved request. It raises the
request, writes its subject, and, because the kind needs no approval, the inbox
closes the request approved in the same act. The owning operation applies the
subject at once, and the answer carries the published instant and the publisher,
which the publish record holds.
The gate still states what happened. The request exists after the act, in the
state approved, with its reason, its subject and its actor, so the audit reads
one request and one publish and not a silent write. The publish record names the
asker as the publisher, because the asker is the person who applied it.
The zero-approval close is not a decision by a person. The rule that a decider is not the asker refuses a decision by the asker, so the inbox writes the close as a state transition whose decider is the system account, and whose comment names the kind and its zero count. A person's decision and the system's close therefore never read the same way.
9.1.2. Who may take it
An account that holds the kind's raise permission and the write the act needs: the market data maker's right to publish a curve. The decide permission is not needed, because there is no decision. The account is the maker and the publisher at once, and the record says so.
9.1.3. Why this answer
A tenant may run a curve family that needs no second pair of eyes: a synthetic curve, or a reference curve that no trade prices from. The count already exists on the kind, so the model should not carry a count it cannot reach. The gate stays in force either way: the publish is one operation with one record, and a tenant can raise the count to one without changing a screen.
The alternative is that the raise writes no request and publishes straight away. That is rejected, because the gate would then have two shapes and the audit would have to tell a request-shaped publish from a shapeless one.
9.1.4. Open questions
- May a tenant set the count to zero? The recommendation is yes, for a named list of curve families, and the setting is audited like any other kind change; the seeded value stays one for a curve publish. The alternative is that zero is refused for market data and only other kinds may use it.
- Does the system close name a decider? The recommendation is one system account, so every decision row names somebody and no row carries an empty decider. The alternative is a null decider and no decision row, which reads as a request that was never decided.
- What does the maker's screen say? The recommendation is that the act is named Publish when the kind's count is zero, and the ask is named Raise publish request when it is one or more, with the panel stating that no second person stands in the act. The alternative is one word for both acts and a note under it.
- Is the kind's expiry used? The recommendation is no: a zero-approval request closes in the raise and never waits.
9.2. The publish notice
9.2.1. The rule
The trigger is the apply, once, at the instant the published set moves. The notice is not sent at the raise and not at the approval: until somebody applies an approval, the curve the system uses has not changed, and a notice that says it has is untrue.
The recipients are the people and the services that read the curve:
- the accounts subscribed to the curve through their party's market data subscriptions, which is how the desk reads it;
- the roles that price from the curve, where a party holds the subscription by a role rather than by an account;
- the services that consume the curve: pricing and reporting, and the market data service itself.
The notice is one notification of the kind marketdata.curve_published, seeded
beside the kind that raises it, with a message key, its arguments and an
optional mail. It carries the subject and the act, and no values:
| Field | What it holds |
|---|---|
| Curve configuration | The code the reader knows |
| Party | The party whose curve changed |
| Published as-of | The instant the set was built at |
| Published at | The instant the set moved |
| Publisher | The account that applied it |
| Authorising request | The request the act stands on |
| Previous as-of | The set it replaced, or empty for the first |
The link on the notice opens the published curve's record page, and the record page is where the values are read. A notice names the change; it does not carry the curve.
A replacement sends the same notice, because a replacement is a publish. A
withdrawal sends marketdata.curve_withdrawn, with the same subject and the
withdrawal reason in words, because a withdrawn curve is a change a reader must
act on.
9.2.2. Why this answer
The consumers of a published curve are people at a desk and services in the platform, and the model already holds both: the subscriptions name the party, and a notification names the account and the link. A notice that carried the values would duplicate the curve and drift from it; a notice that names the subject and links to it cannot drift.
9.2.3. The alternative
A change event alone, marketdata.v1.events.market_series.updated, and no
notification. It is rejected because an event says a row changed, and a person
cannot read it; and because a consumer that misses the event has no place to
look.
9.2.4. Open questions
- Is the notice per party or per person? The recommendation is per account subscribed, because the party subscription names a party and the bell hangs on an account. The alternative is one notice per party, which needs a party bell the platform does not have.
- Does a consumer outside the tenant get a notice? The recommendation is not yet: a published curve is tenant-scoped, and a cross-tenant feed is its own design.
- Is mail sent? The recommendation is that mail is off for a publish and on for a withdrawal, because taking a curve out of use is the one a person must not miss. The alternative is mail on every publish.
- Does the notice carry the previous set's values? The recommendation is no: the previous as-of is enough to find them, and the delta shows the difference.
- Who is told when nobody is subscribed? The recommendation is the queue and nobody else: an unsubscribed curve changes without a notice, and the read states the new instant.
10. Related journeys
- Ask for a publish to be approved — where the request this journey applies was raised.
- Decide a publish — where the approval this journey applies was given.
- Withdraw or replace a published curve — what happens when the published version turns out to be wrong.
- Watch a curve or surface evolve — the consumer's view of the version this journey publishes.
- See who changed a curve, and when — the record of the publish, with the name on it.
- Bootstrap or refresh a curve — where the candidates that are published were built.
11. Related knowledge
- Approval requests — how an approval is applied through the owning component's own operation
- Interest Rate Curves
- Funding and Projection Curves
- Curve Point Provenance
- Term Structures and Tenors
- Tenor and Curve Bootstrapping Architecture
- Market Data Architecture
12. See also
- Bootstrapping a curve: from quotes to a published set — the structure note that orders this cluster, and where to read this page in it.
- The market data path: a public fixing, a curve, a report — the structure note that orders this cluster, and where to read this page in it.
- Market data journeys — the group hub
- User Journeys
- ores.marketdata.market_series — the curve that becomes the published one
- ores.marketdata.market_observation — the points the approval covers
- ores.marketdata.operations — where the compute, republish and snapshot subjects are defined
- ores.inbox.approval_request — the approval this journey applies