See the story of a request prototype

Table of Contents

Item Where
Prototype the prototype
Gemini review none
Group Access prototypes

1. Summary

One request writes to six tables – approval_request, role_grant_request, role_grant_request_role, approval_decision, account_role and notification – and every screen the journey has answers from one of them at a time. This prototype puts all thirteen rows on one screen, newest first, in the order the store wrote them, and asks whether that is the right shape the way a code review shows a pull request.

It is one file of mock HTML, CSS and JavaScript. It calls no service, needs no build and no session, and carries three variants and two readers as query parameters.

Variant A was accepted on 2026-10-08, and is being built: one merged stream, newest first, in the request screen. The row on the group page still says none for its review, because a review is a generated alternative kept beside the agreed design, and none was commissioned.

2. Detail

2.1. The verdict

Accepted on 2026-10-08, on variant A: one merged stream, newest first. Variants B and C are kept in the page and stay unbuilt.

The screen reads the story from two new operations rather than from the reads that already exist, and the reason is entitlement rather than taste. The entity read of approval requests and the generic history read both gate on the administrator's permission, so the person who raised a request cannot read their own request's versions; and the only place a granted role is tied to the request that asked for it is the junction row IAM marks applied, which the roles read did not carry. inbox.v1.ops.get_approval_history answers the request's own versions to the person who raised it, and iam.v1.ops.get_request_roles now answers each role with when it was asked for and when it was applied. The BFF merges the two with the answers given on the request and the notices the reader was given.

The hole the prototype drew is drawn on the screen as well: the decisions another person took are not the asker's to read, so a member's story leaves them out and says that it has.

2.2. The question

The journey is finished, and the record of it is spread across the screens that wrote it. The administrator who answers a request never sees the whole of what they set in motion: the request is in the queue, the roles asked for are on the detail screen, the decision is on the decision row, the grant lands on the member's own access, and the notices are in two different inboxes. Nobody can read what happened in the order it happened.

The prototype asks whether the order is the thing worth drawing, and it asks the question a second time as a second axis, because the first one cannot be answered without it: who is reading. The administrator may open every row. The member may not read the decisions taken on their own request, so their copy of the same story has a hole in it exactly where the answer was given.

2.3. What it argues

The journey today This prototype Why
One screen per table One stream, newest first, every table in it What happened next is the question, and only one view answers it
A state code at each end The state change drawn as a field difference, from one value to the next "waiting" then "approved" hides that anything happened between
The reader sees what their screens read The reader axis is drawn, and the member's copy says what it does not have An entitlement rule is a design decision, not a hole to be papered over
A history panel per record, with a revert A revert only where a write exists to serve it – the asker's own words and the deadline A decision is an act, not an edit; offering to undo it would be a lie

It reads the trail from what the components already keep. Every row above is a version with an actor and a time, so no new store is proposed; the read is across the histories the components already have, and the reader's entitlement decides which of them answer.

2.4. What the prototype settled

Two things were decided while it was being built, and they are the reason it is worth keeping.

The difference widget is the record screens' own. A changed value splits into what stayed, what changed, and what stayed after it, and the middle is marked on the old line in red and on the new line in green. The same widget draws the history panel today, so the trail needs no new way of showing a change.

There is almost nothing here to revert, and the screen that was built offers none. A revert makes sense on a commit because a commit is a diff, but most of this journey is not: a decision is an act with a reason and an actor, and a state is what the acts left behind rather than a field somebody set. What is left is the asker's own words and the deadline they take, and no operation writes either of those on a request: the entity verbs that could are the administrator's surface and this module does not use them. So the honest answer is no button rather than one that cannot work, and the finding stands until a write exists to serve it. Taking a request back is a different act with a different operation, inbox.v1.ops.withdraw_approval, and the person who raised it already has it.

2.5. What is real and what is not

The rows, their order and their field differences are mock, invented to look like what a real request writes. The entity names and their columns are the model's own. The two readers are real rules: the member may read their own request, the roles it asks for and their own notices, and may not read the decisions other people took.

Nothing here is wired to a service, and the prototype proposes no read that exists today. A screen built from it would need one, and that read does not exist yet.

2.6. Where the code lives

doc/prototypes/access/see-the-story-of-a-request/index.html: one file, plain HTML, CSS and JavaScript, no framework and no build step. The site build copies the directory through ores-deploy-prototypes, beside the other prototypes.

Open it with see-the-story-of-a-request/?variant=a&who=admin; the bar along the bottom switches both.

Variants
a one merged stream, b one section per table, c one lane per table on a shared time axis
Readers
admin, who may open every row, and member, who may not

3. See also

  • Ask for more access — the journey this prototype answers to, and the tables it draws.
  • Access screens prototype — the screens the journey has today, whose history panel supplies the difference widget.
  • Approval requests — the record that holds the waiting, and the rule that answers one.
  • Prototypes — the index of every prototype, and where to open each one.

Emacs 29.3 (Org mode 9.6.15)