Skip to content

docs: show the permission gate and the decision receipts in the README - #100

Merged
HackTuah merged 1 commit into
mainfrom
docs/readme-visuals
Sep 26, 2026
Merged

HackTuah merged 1 commit into
mainfrom
docs/readme-visuals

Conversation

@HackTuah

@HackTuah HackTuah commented Sep 26, 2026 •

Copy link
Copy Markdown
Member

Two screenshots from a running build, near the top of the README, because what this project is about is easier to see than to read about. Deliberately two, not a gallery.

The approval card. The tool, the exact arguments it will be passed, the WRITE risk tier, the pattern offered for "always allow", and the four decisions.

The receipts page for that same call. Both halves on the signed chain: the gate asking (basis=default outcome=ask) and the owner allowing (basis=approval outcome=allow).

Together they are the whole argument in two images: it asks before it acts, and the answer is evidence afterwards.

The script is included so the assets can be regenerated

scripts/dev_demo_approval.sh is the slice 021 screenshot script with two changes, both found by it failing:

  • The tool timeout is raised from the suite's 2s. Two seconds is right for tests and impossible for a person: an approval that waits on a human always expires and the turn records the tool as timed out.
  • Migrations run before the application starts, not after. Oban is a supervised child and its tables must exist by the time it boots. The old ordering only ever appeared to work because a previous run had left a migrated file behind; on a fresh database it fails outright at failed to start child: Oban.

No GIF, and why

A GIF of the full sequence is what was wanted, and it is not in this PR because the sequence does not reliably complete. Driving the real browser, the session intermittently never leaves tool_wait after the approval is requested, so the decision that follows is postponed forever and the call ends at the tool timeout reporting error: the tool timed out for something the owner explicitly allowed:

run 3:   after card: t=0s status=approval_wait     -> resumed, receipt written 20ms after the click
run 4:   after card: t=0s status=tool_wait
         after card: t=1s status=tool_wait
         ...                                        (unchanged through t=9s and beyond)

That is slice 126, opened with the reproduction. The suite is green on it because every approval test calls collect(id, &match?({:state, :approval_wait}, &1)) before clicking, which is a synchronisation the product does not have. Clicking on the :requested broadcast instead, which is what the card actually renders on, the approval row ends as {"allowed", "once", consumed_at: nil}: granted, never consumed.

The GIF follows once that is fixed. Shipping one now would mean either filming a broken flow or cutting away before it breaks.

mix gate ; echo "EXIT=$?"
prod_check: PASS
trinity.names: OK over 647 tracked files
trinity.reuse: OK. Every commentable tracked file carries an SPDX header
Result: 821 passed (14 properties, 807 tests), 18 excluded
trinity.coverage: 042 80.31% vs 005 80.31%: OK
EXIT=0

Two screenshots from a running build, near the top, because the thing this
project is actually about is easier to see than to read about.

The first is the approval card: the tool, the exact arguments it will be passed,
the WRITE risk tier, the pattern offered for "always allow", and the four
decisions. The second is the receipts page for the same call, showing both
halves written to the signed chain: the gate asking, with basis=default
outcome=ask, and the owner allowing, with basis=approval outcome=allow.

`scripts/dev_demo_approval.sh` is the script that produces them, added here so
the assets can be regenerated rather than being screenshots nobody can reproduce.
It is the slice 021 screenshot script with two changes: the tool timeout is
raised from the suite's 2s, which no person can answer an approval inside, and
migrations run before the application starts rather than after, because Oban is
a supervised child whose tables must exist by the time it boots. The old
ordering only appeared to work because a previous run had left a migrated file
behind; on a fresh database it fails outright.

No GIF yet. Capturing the full sequence needs the approval to resume the call
reliably, and it does not: see slice 126.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
@HackTuah
HackTuah merged commit 033d056 into main Sep 26, 2026
8 checks passed
@HackTuah
HackTuah deleted the docs/readme-visuals branch September 26, 2026 13:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant