0.1.0a7: the page stopped being a report and became where you decide - #17
Merged
Conversation
Five items since `0.1.0a6`, and they are one thing seen from four angles. The read-only page told an operator that two items had been waiting twenty-one hours and gave them no way to do anything about it — on an instance whose own operator was looking at it. ## What changed **Two buttons on an item waiting for a decision** — *let the agent try it* and *I will take this one* — and the state machine chose which two: `LEGAL[WAITING_APPROVAL]` does not contain `REJECTED`, because that state means a reviewer closed a pull request and it feeds a tally keyed by the label they used. Calling this "reject" would have filed a decision about *whether to attempt* into the count of *review* decisions, and the number would have drifted with nobody able to see why. **The read URL gains no authority.** It is a bearer credential in a path — a saved page, a screenshot, a forwarded link — so it keeps reading everything and can spend nothing. Acting needs a second credential that never appears in a URL: `hullwork password`, once, and then a login a browser's password manager fills in. Sessions are rows, so ending them all is a `DELETE` rather than a key rotation that happens to log everybody out. **This reverses a decision `approve` argued for in writing** — *"an approval endpoint would be a permanent attack surface for something done by one person a handful of times"* — and the ground it stood on had moved. "The operator already has the host" now means ssh, `docker compose exec` and a CLI, from a page read on a laptop. **The page answers before it reports.** One sentence in the largest type, then the items **by name** rather than a count, then the machine's figures as a subordinate row, then everything an evaluator wants behind native `<details>`. The old board put the operator's own queue in the second of six identical cards, so finding it meant reading six labels. **And it now shows what this instance has proved** — found, tried, merged, held, came back — in figures, because a page for a self-hosted product is also the only shop window it has. The motif is the product's own mechanism: a red-to-green rule under the header, once, and nowhere else. ## Two secure designs that were not usable The credential behind those buttons changed twice before this release, and both earlier attempts were sound and unusable. A stored key had to be pasted into a form. A one-time link had to be fetched from the host every twelve hours — open the page, ssh, run a command, copy a link, open it, come back, reload: eight steps, against the single command the whole exercise set out to improve on. The reason given for skipping the obvious answer was wrong, and it cost a milestone: a chosen password was said to need scrypt or argon2 and therefore a new dependency in the half of Hullwork that listens on a network. `hashlib.scrypt` is in the standard library — 37 ms per attempt at `n=2**14`, which is the work factor and most of the answer to online guessing, with a ten-try lockout for the rest. ## What is not shown **Nobody has pressed either button.** The instance logs `decided from the page` when it happens and has zero of them. Everything here is verified against the code — the read token cannot decide, a wrong CSRF token cannot, the lockout closes and reopens on its own, both themes render — and none of that is the claim. The claim is that an operator can decide from a browser in two steps, and the only instrument that can measure it is an operator. Each of the five items now carries that as its gate. [`docs/status.md`](docs/status.md) is unchanged in its list of what nobody has shown, and it is still the section that matters. Signed-off-by: Javier Miralles Rancaño <68760931+FlagshipDev@users.noreply.github.com>
FlagshipDev
enabled auto-merge (squash)
August 7, 2026 12:43
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Five items since
0.1.0a6, and they are one thing seen from four angles. The read-only page told anoperator that two items had been waiting twenty-one hours and gave them no way to do anything about it
— on an instance whose own operator was looking at it.
What changed
Two buttons on an item waiting for a decision — let the agent try it and I will take this one —
and the state machine chose which two:
LEGAL[WAITING_APPROVAL]does not containREJECTED, becausethat state means a reviewer closed a pull request and it feeds a tally keyed by the label they used.
Calling this "reject" would have filed a decision about whether to attempt into the count of review
decisions, and the number would have drifted with nobody able to see why.
The read URL gains no authority. It is a bearer credential in a path — a saved page, a screenshot,
a forwarded link — so it keeps reading everything and can spend nothing. Acting needs a second
credential that never appears in a URL:
hullwork password, once, and then a login a browser's passwordmanager fills in. Sessions are rows, so ending them all is a
DELETErather than a key rotation thathappens to log everybody out.
This reverses a decision
approveargued for in writing — "an approval endpoint would be apermanent attack surface for something done by one person a handful of times" — and the ground it
stood on had moved. "The operator already has the host" now means ssh,
docker compose execand a CLI,from a page read on a laptop.
The page answers before it reports. One sentence in the largest type, then the items by name
rather than a count, then the machine's figures as a subordinate row, then everything an evaluator wants
behind native
<details>. The old board put the operator's own queue in the second of six identicalcards, so finding it meant reading six labels.
And it now shows what this instance has proved — found, tried, merged, held, came back — in figures,
because a page for a self-hosted product is also the only shop window it has. The motif is the product's
own mechanism: a red-to-green rule under the header, once, and nowhere else.
Two secure designs that were not usable
The credential behind those buttons changed twice before this release, and both earlier attempts were
sound and unusable. A stored key had to be pasted into a form. A one-time link had to be fetched from
the host every twelve hours — open the page, ssh, run a command, copy a link, open it, come back,
reload: eight steps, against the single command the whole exercise set out to improve on.
The reason given for skipping the obvious answer was wrong, and it cost a milestone: a chosen password
was said to need scrypt or argon2 and therefore a new dependency in the half of Hullwork that listens on
a network.
hashlib.scryptis in the standard library — 37 ms per attempt atn=2**14, which is thework factor and most of the answer to online guessing, with a ten-try lockout for the rest.
What is not shown
Nobody has pressed either button. The instance logs
decided from the pagewhen it happens and haszero of them. Everything here is verified against the code — the read token cannot decide, a wrong CSRF
token cannot, the lockout closes and reopens on its own, both themes render — and none of that is the
claim. The claim is that an operator can decide from a browser in two steps, and the only instrument
that can measure it is an operator. Each of the five items now carries that as its gate.
docs/status.mdis unchanged in its list of what nobody has shown, and it is stillthe section that matters.
Signed-off-by: Javier Miralles Rancaño 68760931+FlagshipDev@users.noreply.github.com