Story: Implement the access journeys in ores.web
Table of Contents
This page documents a story in Sprint 26. It captures the goal, current status, acceptance criteria, and the tasks that compose it.
1. Goal
The first three Access journeys
run in ores.web against the real server:
- Know what I may do — the member reads the roles they hold and the permissions those roles carry.
- Change someone's access — the tenant administrator grants and revokes a colleague's roles.
- Shape the role catalogue — the tenant administrator defines roles and the permissions each one bundles.
The fourth journey, Ask for more access, is Land the role request journey, split out at the sprint 26 close on 2026-10-05.
This is the fifth group of Implement the user journeys in ores.web. It reuses the journey runtime the Setup group landed and adds no journey entity. The journey documents stay with the extraction pass, except where this group's survey proves one wrong.
Three of the four documents were written on 2026-09-23, before the IAM
clean standard and the security hardening, and two of the gaps they record
have already closed: iam.v1.roles.assign checks iam::roles:assign now,
and the account's credential fields are :no_wire:, so no read returns
them. What is left is a shorter and sharper list, and the build is sized
from the survey rather than from the documents as they stand.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent sprint | Sprint 26 |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-10-05 |
On 2026-10-05, at the sprint 26 close, this story was reworded to the three journeys it delivered and closed DONE. The fourth journey, the role request, is Land the role request journey, and the task Land the role request moved there.
3. Acceptance
- Every claim in the four journey documents is checked against the tree, and every gap is either closed with its evidence or still open with the subject that would close it.
- A member reads only their own access: the role reads are self-scoped or permission-gated, and a test proves that another account's access is refused.
- A role's permission bundle can be written, so the catalogue journey can save what it composes rather than reading it back unchanged.
- An assignment read exists, so who granted a role, when, and why is visible to the member and to the administrator from the same answer.
- The three journeys run in
ores.webagainst the real server, and the shell reaches the same subjects for the operations it carries today.
4. Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|
| Re-verify the four access documents against the tree | DONE | 2026-09-30 | Check every gap the four documents record against the current code, close the ones the IAM clean standard and the hardening already closed, and leave the rest with the subject that would close each. | |
| Close the access reads | DONE | 2026-09-30 | 2026-10-01 | Make the role reads self-scoped or permission-gated, add the read that pairs a permission with the role that grants it, and add the assignment read that carries who granted a role, when and why. |
| Let a role's permission bundle be written | DONE | 2026-10-01 | 2026-10-01 | Add the write the catalogue journey has never had: a role's permission list can be composed and saved, permission-gated, with the change reason every other write carries. |
| Build the access screen in ores.web | DONE | 2026-10-04 | 2026-10-04 | The three original journeys as screens against the real server: the member's own access, the administrator's grant and revoke with its audit, and the role catalogue with its permission picker. |
| Prototype the access screens | DONE | 2026-10-04 | 2026-10-04 | Prototype the member's own access, the administrator's grant and revoke, and the role catalogue against the real roles and permission catalogue, before the screens are built. |
| Give a role for a reason | DONE | 2026-10-04 | 2026-10-04 | Giving a role carries the reason and the note the administrator chose, from an access reason category, and nobody takes a role away from themselves. |
| Prototype the role request | DONE | 2026-10-04 | 2026-10-04 | Add asking for a role and answering the ask to the access screens prototype, before the request is built. |
5. Plan
The survey comes first and the reads come second, because the documents are older than the code they describe and a screen drawn from a stale gap list builds the wrong thing.
| # | Step | What it leaves behind |
|---|---|---|
| 1 | Scaffold the story and wire it into the programme | The story, its tasks, the sprint row and the programme's order table. |
| 2 | Re-verify the four documents against the tree | A corrected gap list per journey, and the corrections in the documents that are wrong. |
| 3 | Close the access reads | Self-scoping or a permission gate, the permission-to-role attribution, and the assignment read. |
| 4 | Let a role's bundle be written | The write subject, its handler and its permission. |
| 5 | Build the access screen | The three original journeys in ores.web. |
| 6 | Land the role request | The request subjects, the four-eyes guard, the ask screen and the queue. |
6. Decisions
- The survey precedes the build. Three of the four documents predate the clean standard that changed the code they describe, and two of their gaps have closed without anybody saying so. A build sized from the documents as they stand would re-do work that is done and miss what is left.
- The reads are closed before any screen shows them. A read that proves only a session and takes an arbitrary account id lets a member read a colleague's access. That is a defect with a screen in front of it, so it is fixed at the subject rather than guarded in the browser.
- The catalogue's write is one subject, not a screen. The journey's whole gap is that a role's permissions can be read and not written, so the unit is the write and its permission, and the screen is the group's own screen task.
- The bundle write takes the whole set. The screen knows the set it wants, not the difference, so one call carries the complete bundle: what is missing is added, what is unticked is removed, and sending the same set twice changes nothing. An add and a remove would make the screen compute a difference and then depend on both landing.
- A role's fields and a role's bundle are separate permissions.
iam::roles:writeguards the role's own fields andiam::roles:updateguards what the role grants, which is what the seeded descriptions already said. An administrator can shape what a role grants without being able to rename or delete the role itself. - The caller's account id is resolved from the actor, in one place. The request context carries the JWT's username, and the database-backed check and every self read are keyed by account id. Reading the username as a uuid failed every live access request, so the service joins the two once and the subjects take the id it returns.
- A cross-sprint group closes DONE and gets a successor. The programme's rule applies here: if the role request's waiting state does not land in sprint 26, what lands is recorded and the rest continues in a successor story.
- The role request's waiting state belongs to
ores.workflow. The journey says so: a request that waits on a person keeps its state as a workflow instance, and the engine has no state that means "a person decides" yet. That is a workflow decision with a workflow owner, recorded here and not assumed. - Both clients reach one operation.
ores.webandores.shellcall the same subjects, so the group carries the shell side of its journeys and does not move the disagreement to the other client. - A journey a person cannot reach from a screen is not finished. The four documents each carry a * Related journeys list, and each entry is a link on the screen. A screen that omits them has not implemented the journey.
- The screens follow the accepted contracts. The UX language, the UI design principles and the TypeScript Clean Standard bind the work. The entity specification is void and binds no screen.
7. Out of scope
- The journey extraction and the journey documents, which Extract the user journeys that replace the ores.qt screens owns, except where this group's survey proves one wrong.
- The notification that tells an administrator a request is waiting, and that tells the member the answer. The journey records it as a gap of its own.
- The approval workflow behind
system.signup_requires_authorization, which is a workflow inores.workflowand the Entry group's recorded gap. - Two-factor authentication, and the credential journeys' screens, which are the Credentials group's.
8. Documents
| Document | Kind | Purpose |
|---|---|---|
| Access journeys | knowledge | The group page: four journeys, two actors, and the chain from account to permission. |
| Know what I may do | user_journey | The member's own read, and its three gaps. |
| Change someone's access | user_journey | The administrator's grant and revoke, and its five gaps. |
| Shape the role catalogue | user_journey | The role and its permission bundle, and the write it does not have. |
| Ask for more access | user_journey | The member's request and the administrator's answer, and its seven gaps. |
| Implement the user journeys in ores.web | story | The programme this group belongs to, and the order it keeps. |
| Registration and Onboarding Defaults | knowledge | Why a default role is a floor and not a ceiling, which is what the request journey answers. |
| Journey execution | knowledge | The composition classes, and why a journey that waits on a person is a workflow instance. |
| Authorised reads | knowledge | The rule this group's reads obey: which permission check, why the self read and the privileged read are separate subjects, and where a refusal travels. |
| TypeScript Clean Standard | knowledge | The standard the screens are held to. |