Story: Land the role request journey

Table of Contents

This page documents a story in Sprint 27. It captures the goal, current status, acceptance criteria, and the tasks that compose it.

1. Goal

The fourth Access journey runs in ores.web: the member asks for a role beyond the one registration gave them, and the tenant administrator answers.

The journey was designed around a workflow_instance that waits on a person. It was landed a different way, by Complete the ores.inbox approvals and notifications: an approval request is its own record with a state and an answer, and the role grant is its first kind. That story built the request, the four-eyes guard, the grant, the two notifications and both screens. Four of the journey's seven gaps closed there, and a fifth was answered by the change of design.

What remained was what no screen could yet say: which roles a member may ask for, and what becomes of a request that nobody answers. Both are built. A role now says whether it may be asked for, and a request carries a deadline, closes as expired when it passes, and tells the person who asked. The journey document has been rewritten around the design all of this landed, and it marks every one of its seven gaps.

This story was split from Implement the access journeys in ores.web when that story was reworded to the three journeys it delivered and closed DONE at the sprint 26 close on 2026-10-05; the task Land the role request moved here.

2. Status

Field Value
State DONE
Parent sprint Sprint 27
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-10-08

3. Acceptance

  • An approval request of kind iam.role_grant carries the ask, the four-eyes guard and the grant, and the shell reaches the same subjects as the screens.
  • The waiting state the request needs is a state of the request's own record, and the journey records why ores.workflow is not the holder.
  • The member's ask screen and the administrator's queue run in ores.web against the real server.
  • A tenant can say which of its roles a member may ask for.
  • A request that nobody answers closes on its own.
  • The journey's remaining documented gaps are closed, and the document describes the design that was built.

4. Tasks

Task State Start End Description
Land the role request DONE 2026-10-05 2026-10-06 The request, the four-eyes guard and the grant, and the member's ask screen and the administrator's queue. Landed by the inbox story, whose two tasks own the work.
Say which roles may be asked for DONE 2026-10-07 2026-10-07 The is_requestable flag on the role row, and the ask operation and the screens reading it.
Give the role request a deadline DONE 2026-10-07 2026-10-08 The role request kind's deadline, and the sweep that closes a request nobody answers.
Describe the design the journey landed DONE 2026-10-08 2026-10-08 Rewrite the journey document around the approval-request design that was built, and mark which of its seven gaps are closed.

5. Decisions

  • A request is a record, not a waiting workflow. The journey put the request in ores.workflow as an instance that suspends and resumes. The workflow engine cannot wait on a person, and extending it to do so would serve this one journey. The request is instead a row of its own with a state, a raiser and an answer, and the states are waiting, held, approved, refused, withdrawn and expired. Recorded in Approval requests.
  • The journey's five request subjects were not built. They named IAM as the holder of the queue and the decision. The queue is generic across kinds, so it belongs to ores.inbox, and IAM keeps only the detail of a role grant. See Role requests.
  • Four eyes is a rule of the store, not of the screen. The decisions table refuses a decision by the person who asked, so a screen cannot be the only guard.
  • An approval is not a grant. IAM reconciles approved requests into role assignments exactly once, rather than granting at the moment of the decision.

6. Out of scope

  • The notification that tells an administrator a request is waiting, and that tells the member the answer. Built by the inbox story, not here.

7. Result

The journey is done, and the document that describes it says what was built rather than what was intended.

Four tasks. The request, the four-eyes guard, the grant and both screens landed under the inbox story. This story added the two things no screen could yet say: a role states whether it may be asked for (PR #2754), and a request carries a deadline it takes from its kind, closes as expired when it passes, and tells the person who asked (PR #2784). The fourth task rewrote Ask for more access around the design all of that landed (PR #2785).

Six of the journey's seven gaps are closed and the seventh is half closed. Two of the six were closed by changing the design rather than by building what the gap asked for: the request became a record of its own, so the workflow engine was never the holder and needed no waiting state, and the queue became a read of a table rather than a projection over an instance's payload. That is recorded in the document itself, in a table with a state per gap, because it is the part a future reader would otherwise have to reconstruct.

What is left of the seventh gap — a reminder before a request lapses, rather than the close after it does — is captured as "nobody reminds a decider that a request is about to lapse". It is a different behaviour from the deadline, with its own timing and its own audience, and it was deliberately not built here.

Four decisions this story made are in the * Decisions above. The one worth repeating: work that recurs is the component's to declare and the installation's to schedule. The sweep is the first thing to take that shape, and the pattern is written up on Approval request expiry.

Emacs 29.3 (Org mode 9.6.15)