User Journey: Decide a convention change

Table of Contents

This page documents a user journey: A market risk approver reads a requested convention change beside the terms it replaces, and approves or declines it.

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

"Someone asked to change a term that every desk reads. I want to see what it is now, what they want, who it reaches and why they asked, and then say yes or no."

The journey is done when the decision is recorded, the requester can read it, and the person knows whether the change was applied.

This journey is the second half of the four journeys that write a convention: Author a convention for a kind, Change the convention a party uses for one kind, Retire a convention and Name a convention set. The controls note says each write needs a second person. Today the first two write directly, and the other two draw the request. This journey is where the request waits for a decision.

2. Actor and trigger

The actor is the approver: a person from Market Risk. The controls note gives Market Risk the decision on a new convention, a change of its terms, and a change of how tenors resolve (Book types and the controls on each). The person is never the one who asked: the approval record refuses a decision by the asker.

The Market Risk that decides is the tenant's and not one party's, because a tenant kind belongs to no party and a permission is held by an account in a tenant. What is missing states the rule and why it follows.

The role exists. The part Market Risk is seeded with the description "Classification, capital treatment, agreements and conventions", and the permission inbox::approvals:decide_market_risk is seeded. What does not exist is a request kind for a convention. The queue lists a request only if its kind exists, so today the approver has nothing to open. See What is missing.

The trigger is a waiting request in the approver's queue. The journey starts on the queue and ends when the decision is read back. The requested change applies after the last required approval. It does not apply on a hold or a decline.

The journey keeps server state: the request, its decisions and its state. The approver can leave the screen at any step.

3. Steps

  1. Open the queue. The system lists the requests that the person may decide: those whose kind names a permission the person holds, and that the person did not raise. Each row shows what is asked, who asked, the kind of change and how long the request has waited.
  2. Read the change. The person opens one request. The system shows the target, for example the swap document of the party, and each term that changes with its present value beside the asked value. A new document or a new set has no present value, and the screen shows the whole new row. A close shows the row that would stop being read.
  3. Read the reason. The system shows the reason the requester gave, who asked and when. It shows when the request expires.
  4. Read the reach. The system states who reads the target: every definition of the party reads a party document, and every party of the tenant reads a tenant kind. It states what it cannot say: which runs are affected, because no run records the version of a document it read.
  5. Read the rule. The system shows how many approvals the request needs, the permission and the part that decide, and the decisions so far. For a tenant kind it also states that the decider is the tenant's Market Risk and not one party's, because the document is read by every party of the tenant.
  6. Decide. The person approves, declines or holds, and writes a comment. A decline needs a comment. The system records the decision under the person's own name.
  7. Read the outcome. After an approval, the system states whether the change is applied or waits for another decider. After a decline, the record keeps its version and the request ends. The system tells the requester.
  8. Leave, or go on. The person returns to the queue.

4. Screens and wireframes

One screen of four panels: the queue, the change, the decision and the outcome. The change panel is the one the journey is about. A person who decides a term must read the old and the new value in one place, and a request that shows only the new value is not a request a person can decide.

wireframe_decide_a_convention_change.png

Figure 1: Decide a convention change: the queue for Market Risk, one change as old term beside new term, the decision with its comment, and the outcome that states whether the change applied.

5. Prototype

A clickable prototype draws this journey: prototype, with its design note decide-a-convention-change. It opens with no build and reads mock data only. The page marks each server gap this journey names.

6. Entities composed

Entity What it contributes Model
approval_request The request under decision: who asked, which kind, why, when it expires and its state ores.inbox.approval_request
approval_kind How many approvals, the permission a decider holds, whether a hold is allowed, whether an approval needs a comment ores.inbox.approval_kind
approval_decision Each decision taken, with who, when and the comment ores.inbox.approval_decision
approval_decision_type The decisions on offer, and which need a comment ores.inbox.approval_decision_type
approval_request_state The state the request is in, and which states are final ores.inbox.approval_request_state
The kind's convention table The present row, which the change is read against one of the 26; see See the conventions a party uses

7. Operations and messages

Step Operation Subject Status
Open the queue List the requests this person may decide inbox.v1.ops.list_approval_queue exists
Open the queue A convention request in the queue (no convention request kind is seeded) missing
Read the change Read the request header inbox.v1.approval_requests.get exists
Read the change Read the present row refdata.v1.<kind>_conventions.get exists
Read the change Read the pending change (a request holds no pending change) missing
Read the reason Read the requests of one kind inbox.v1.approval_requests.list_by_kind_code exists
Read the reach Read the runs that read a version (no run records the version) missing
Read the rule Read how many approvals and who decides inbox.v1.approval_kinds.list exists
Read the rule Read the decisions so far inbox.v1.approval_decisions.list_by_request_id exists
Decide Approve, decline, hold or resume inbox.v1.ops.decide_approval exists
Read the outcome Apply the change when the last decider approves (no apply workflow for a convention) missing
The screen itself Decide a convention change from the browser (no BFF route) missing

8. What is missing

  1. No approval kind for a convention. iam.role_grant, refdata.book_change and refdata.counterparty_change are the only kinds seeded. The candidate is one kind, for example refdata.convention_change, whose decide_permission_code is inbox::approvals:decide_market_risk and whose approvals_required is 1. The part and the permission exist. The question the product owner answers is whether one kind serves all four requests or each request has its own kind.
  2. A request holds no pending change. A request carries a kind and a reason. It does not carry the row that is asked, so the change panel has nothing to read. The pending change needs a home: the request, or a staged row of the convention table.
  3. Nothing applies the change. Counterparty and book changes have an apply workflow. A convention has none, so an approval changes nothing. The apply must write the row with must_match_version, and it must refuse if the row changed after the request was raised.
  4. Who decides a tenant kind is now stated. The controls note names Market Risk as the decider and did not say which party's Market Risk decides a tenant kind. The rule the tenancy model gives, and the rule this journey now states, is that the tenant's Market Risk decides, and no party's:

    • A tenant kind belongs to the tenant and not to a party. Every party of the tenant reads the same row, so no party owns the document and no party's function is accountable for it.
    • A permission is held by an account in a tenant and never by a party. There is no party-scoped permission to grant, so "the London head of market risk" is not a decider the model can name.
    • The queue a decider works from is the tenant's. The list of requests a person may decide is filtered by the permission each kind names and by the tenant, and by no party, so the first holder of the permission who answers decides the tenant's request.

    The group's head of market risk is the person the demonstration intends to answer, because the group is the party that speaks for the tenant. Any other account of the tenant that holds inbox::approvals:decide_market_risk may answer too, and the record then names that person, which is the same answer the rest of the tenant's approvals give. The asker never answers. A set that names a tenant kind follows the same rule, because a set is a tenant-level choice over documents of which some belong to the tenant.

  5. The role is not tied to a person in the tenant. The permission exists. A Market Risk account in a tenant holds it only if the tenant's roles grant it, and this journey assumes they do. The first task of the implementation reads the seeded roles and the tenant's grants to confirm the assumption.
  6. No run records the version it read. The reach panel states the scope and cannot name the runs.
  7. No BFF route serves the queue for conventions. The inbox subjects exist and the browser reaches them through the inbox, so the journey adds the panel and no route.

9. Related journeys

10. Related knowledge

11. See also

Emacs 29.3 (Org mode 9.6.15)