User Journey: New party
Table of Contents
This page documents a user journey: A tenant administrator adds a party and links the accounts that work in 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
"I want a legal entity my team can work as, with the accounts that work in it." The tenant administrator finds the legal entity among those the deployment holds, or adds it by name when it has no LEI, names the party, and chooses the accounts that work in it. The journey is done when the party is active, its essential data is published, and its accounts can sign in to it.
2. Actor and trigger
The tenant administrator: an account of type user that holds the
tenant-administrator role, signed in, and acting inside one tenant. The trigger
is New party on the Parties page. It also starts from Add another party at
the end of this journey. The manual path, "It has no LEI: add it by name", is
the same journey with the search skipped. The tenant administrator never
chooses the tenant: the session already names it.
This is one of the three journeys that carry server-side state. Provisioning
runs on the server and can fail half way. The state lives in ores.workflow,
so the person can leave the page and come back, and the shell can drive the
same steps. Every other group in this corpus describes a journey that keeps no
such state. The order is fixed: this journey needs a running installation, a
signed-in tenant administrator and a tenant that is already active.
3. Steps
- Find the legal entity. The person searches the legal entities the deployment holds, by name or by LEI. Each result shows the legal name, the country, the LEI and how many parties the hierarchy would create, so a subsidiary is recognisable as one. The person picks one, or chooses It has no LEI: add it by name and types the name instead. Nothing is created yet.
- Describe the party. The person sets a short name, taken from the legal name, and ticks the accounts that work in it: this is the account-party association. Accounts that work in the party can sign in to it and act for it, and can switch between parties later. The tenant administrator's own account is ticked by default. There is no data-size question: counterparties are tenant-wide, and the party's bundles come from the tenant's seed profile.
- Review. The person reads one summary: legal entity, LEI, short name, the accounts, and the party data. The screen states that nothing is created until the person confirms.
- Provisioning. The person confirms, and the system starts the
provision workflow for the
party. The party stage is one request and its run is one step kind, so the
rail lists the profile's
provision_partystep, which publishes the party's bundles, activates the party and marks its onboarding complete, and the run joins the caller to the party. Each line reads pending, running, done or failed. This is the step that carries the state. The person can leave the page and come back. A failed step stops the instance, the party stays inactive, and a retry resumes from the failed step; the completed steps are kept. - Next steps. The party is active. The page offers three exits: switch to the new party and work in it now, set up its books, or add another party. The person can also just go back; the Parties page lists the new party as active. Where the deployment accepts self-registration, the page may also nominate this party as the one a new account joins; the tenant's first sign-in nominates it, and this is where a second party takes it over.
The rail is flat: a person sees five steps. Steps that change server state are final, so there is no Back past them.
4. Screens and wireframes
The same journey page as the tenant journeys: a flat step rail on the left and one step at a time. The party header, the short name and the LEI, appears on every step after the legal entity is chosen.
Figure 1: New party: a flat step rail on the left, the legal-entity search results, and one step at a time.
5. Prototype
Accepted by the user on 2026-09-22. The prototype is merged into main and
kept there as the record; the accepted commit names the state. The built journey keeps its
five steps, its two ways of naming a party and its three exits; what it does not
carry is the accounts picker, which the prototype showed and nothing writes.
- Accepted commit
97d63a01f2, the tip ofprototype/new-party-journey, merged intomain- Source
doc/prototypes/setup/new-party/index.html- Open
/OreStudio/doc/prototypes/setup/new-party/once the site is built, or the file directly- Design record
- Task: Prototype the new party journey
The party journey was the first built on the shared journey page, and it proved the step library: the tenant journey's steps and the party journey's steps come from the same place. It also settled two things. Counterparties are tenant-wide, so the Qt wizard's dataset-size question is gone. And the accounts that work in the party are chosen here, in the describe step, not in a later wizard.
6. Entities composed
| Entity | What it contributes | Model |
|---|---|---|
party |
Short name, legal name, status and type of the party being created | ores.refdata.party |
party_identifier |
The LEI of the legal entity, under the LEI scheme | ores.refdata.party_identifier |
party_id_scheme |
Names the identifier scheme the LEI belongs to | ores.refdata.party_id_scheme |
party_status |
The party moves to active at the activate step | ores.refdata.party_status |
party_type |
The classification the create step sets | ores.refdata.party_type |
account |
The accounts the picker offers, and the one that runs the journey | ores.iam.account |
account_party |
The accounts that work in the party — the association this journey writes | ores.iam.account_party |
counterparty |
The tenant-wide counterparties the tenant's seed profile already published | ores.refdata.counterparty |
| GLEIF legal entity | Legal name, country, LEI and parent, read from the register | ores.dq.lei_entity and ores.dq.lei_relationship |
No password or secret appears on this screen at all. The person chooses which accounts work in the party; the accounts themselves are created elsewhere.
7. Operations and messages
| Step | Operation | Subject | Status |
|---|---|---|---|
| Find the legal entity | Search the legal entities the deployment holds, by name or LEI | dq.v1.ops.search_lei_entities |
exists |
| Describe the party | List the accounts that may work in the party | iam.v1.accounts.list |
exists |
| Describe the party | Read the existing account-party associations | iam.v1.account_parties.list |
exists |
| Review | Add the party and start its run | iam.v1.ops.provision_party |
exists |
| Review | Create the party row, under the tenant's own party | refdata.v1.parties.put |
exists |
| Provisioning | Publish the party's essential data | iam.v1.ops.provision_party |
exists |
| Provisioning | Record the legal entity it was built from | refdata.v1.party_identifiers.put |
exists |
| Provisioning | Activate the party | refdata.v1.parties.put |
exists |
| Provisioning | Mark the party provisioning complete | iam.v1.ops.provision_party |
exists |
| Provisioning | Join the caller to the party | iam.v1.ops.provision_party |
exists |
| Provisioning | Retry from the failed step | workflow.v1.ops.retry_workflow_instance |
exists |
| Next steps | Switch to the new party | iam.v1.ops.switch_party |
exists |
| Next steps | Read the party's books | refdata.v1.books.list |
exists |
The two iam.v1.account_parties subjects are declared in
ores.iam.account_party, and
iam.v1.account_parties.put_many is what writes the accounts that work in a
party; the run the provision request starts joins the caller on its own.
iam.v1.ops.switch_party is declared in
ores.iam.account_messages, and
iam.v1.accounts.list is generated from
ores.iam.account. The
refdata.v1.parties and refdata.v1.books subjects are generated from their
entity models. All of them exist in the generated web protocol.
dq.v1.ops.search_lei_entities matches a name or an LEI over the legal entities the
deployment holds and states, per match, how many parties the hierarchy would
create; the BFF adds a route to it and the wire client parses the reply.
workflow.v1.ops.get_workflow_steps and workflow.v1.ops.retry_workflow_instance are not in the
generated web protocol: the generator emits no workflow package for the
browser, so the BFF adds a route for each and the wire client parses the reply.
The party stage is one request, iam.v1.ops.provision_party. It takes a party,
by its identifier or its exact full name, the starting point whose party stage
runs, and the legal entity the party was built from; it resolves the party in
the caller's own tenant, and answers at once with the id of a run that publishes
the party's bundles, records that entity as the party's LEI, activates the
party, marks its onboarding complete and joins the caller to it. The starting
point states which bundles a party is published from, as the arguments of its
provision_party step, and a profile that orders no party step is refused. A
reference that matches more than one party is refused as well, because a run
acts on one party.
An empty starting point means the deployment's own party stage, which is the
first profile that orders one. A tenant administrator cannot name a profile: the
profiles are the system tenant's rows and a tenant reads only its own, so the
service that holds both is the one that chooses. The shell's provision party
therefore names none by default and the browser names none at all.
The LEI travels with the run rather than being written by it. A party identifier is stamped with the party its writing session acts in, and the person who adds a party works in another one, so the run is the only client that can record it: it writes it with a client scoped to the party it is provisioning.
Every subject in the table exists on the wire, and the shell's provision party
sends iam.v1.ops.provision_party and follows the same progress read. The browser
reaches the search and the request that starts a party's run through the BFF, and
POST /api/provision-party is that request: it adds the party row, places it
under the tenant's own party, and starts the run.
8. What is missing
- The chosen accounts are not written. The describe step would pick the
accounts that work in the party, and the screen does not offer the picker
yet, because nothing writes them: the run joins the caller alone. Writing the
other chosen associations is
iam.v1.account_parties.put_many, and the request that provisions a party takes no account list, so no step of the party's own run writes them. A picker whose choices went nowhere would be worse than no picker. - No scripted end-to-end proof. No scripted run proves this browser's path
the way
projects/ores.web/scripts/verify-login.tsproves the sign-in, so the proof of the journey stays manual. - No completion signal the browser can read. The engine publishes
ores.workflow.workflow_instance_changedon every state change, but the payload is anentity_change_eventthat carriesentity_ids, and the schema the browser decodes readsalpha2_codeswith every field defaulted, so the browser receives an empty identifier list. The readsworkflow.v1.ops.get_workflow_stepsandworkflow.v1.ops.retry_workflow_instanceexist and are what a page follows a run with. That mismatch is owned by its capture. - A party hangs under the tenant's own party, and the person does not choose where. A party hangs under another and exactly one of a tenant's parties sits at the top, so the row whose parent is unset is what a new party is placed under; a tenant that has none gets the party it has just added as its root. Choosing the parent, or moving a party afterwards, is the Draw the reporting line journey and not this one.
The rest of the journey is in place, and the list below is the record of what each part turned out to be.
- The legal-entity search reads the deployment's own data.
dq.v1.ops.search_lei_entitiesmatches a name or an LEI over the legal entities the deployment holds, and states, per match, how many parties the hierarchy would create. The deployment's records are the ones a tenant is built from; no live proxy to the public register is needed. The browser reaches the search through a BFF route, and the party named by hand is the same journey with the search skipped. - No journey record, and none is added. A journey is a definition, not a
server-side object. Its progress state is a workflow instance in
ores.workflow, with its entities, services and subjects, and the run is followed by the id the request answers with. Only the server-side workflow resumes, so the human steps around it do not survive a reload. The retirediam.v1.journeys.get-activecandidate is dropped. - The provision-party request is one stage.
iam.v1.ops.provision_partytakes a party, by its identifier or its exact full name, a starting point and the entity the party was built from, resolves the party in the caller's tenant, and returns a workflow instance id at once. The run publishes the bundles the starting point orders, records the entity as the party's LEI, activates the party, marks its onboarding complete and joins the administrator who asked to it, so the request carries the whole active, onboard and publish stage. The LEI is written last, because an identifier's insert bumps the version of the party it belongs to and a party saved before it would then be refused as one that moved on. - The party's bundles are the starting point's. The
party_essentialsbundle is one of the bundles aprovision_partystep may order, as the step's own arguments, and every starting point that orders the kind orders it. A party's data is therefore the profile's, and the step the tenant run carries is the one the party stage runs. There is no separate publish request for a party on its own. The generic report set is theparty_reportingbundle. A profile that designs each party's reports leaves it out and publishes the party's own report definitions through the party's bundle. - A retry resumes a stopped run.
workflow.v1.ops.retry_workflow_instanceresumes a run that stopped on its failed step: it re-dispatches that step under its own identity, clears the run's error, and leaves every completed step and its result alone. The engine'srecover_in_progress()stays for runs that were in progress when a service restarted.
9. Related journeys
- Choose where I work — switch to the party you just created, and set it as your default
- Bring someone in — create the accounts that will work in the new party
- Draw the reporting line — set who reports to whom inside the new party
- New tenant — the tenant's seed profile decides the bundles every party gets
- First run — where the first party is created with the first tenant
10. Related knowledge
- Identity and Access Management — Provision, Onboard, Account-party association, Seed profile
- Registration and Onboarding Defaults — where the registration defaults live, including the party this journey may nominate
- Parties — the user guide chapter on what a party is
- Document type: user_journey
- How do I add a PlantUML diagram?
- Setup journeys