How does the dashboard write back — what makes a GO/Cancel button actually work?
a — Cloudflare Pages Function + GitHub API · 2026-07-25T00:00:00.000Z
Context
What already works
Reading is solved. /m/<slug> renders the full spec as HTML, the task graph with
every task’s live state and reason, acceptance criteria in drawers, run history,
and budget against cap. dash-mobile is sitting there now in planning.
What is missing is only the write: a tap that changes a file.
Why a button is not trivial here
The dash is a static Astro build on Cloudflare Pages. There is no server to POST to. Every piece of state is a file in git, and a page rendered from those files cannot edit them — which is the property that makes the whole system auditable, and also the reason this needs a deliberate answer rather than a quick fix.
The distinction that matters for (a)
brain__cloudflare-deploy records that the scheduled sandbox cannot reach
api.cloudflare.com, which is why the D1-backed dashboard was abandoned and
why state is files and git.
That constraint does not rule out (a). It says the loop’s sandbox cannot manage
Cloudflare resources. A Pages Function is different in both direction and
location: it runs on Cloudflare’s edge and makes an outbound call to
api.github.com. Nothing in the sandbox is involved, and nothing new stores
state — the commit is still the source of truth, git is still the transaction
log, and the dash is still a render of files.
It is worth being precise about that, because CLAUDE.md says not to reintroduce
a runtime datastore without solving the sandbox problem first. This is not a
datastore. It is a write path. But it is the first runtime code in a repo whose
selling point is having none, and that deserves saying out loud rather than
sliding past.
What each answer costs
(a) One tap, stays on the dash, works from a phone lock screen. Costs: a
fine-grained GitHub token living in Pages env vars, a functions/ directory, and
a new failure mode — if the token expires, buttons silently stop working. Needs
Access JWT verification so the endpoint is not open to anyone who guesses the
URL. Roughly a day of work including the race handling: the loop pushes to the
same files, so a stale-SHA 409 has to retry rather than clobber.
(b) One tap, but it opens the GitHub app rather than acting in place. No secrets anywhere in Cloudflare. The Action needs write permission to the repo, which it already has. Cheapest real button, and the ugliest — a decision card that answers itself by filing an issue is a strange artifact to leave behind, and the issue list becomes a shadow log of decisions that the graph already records properly.
(c) Zero new anything. It is three steps on mobile: tap to copy, switch to Claude, paste. Honest, and probably fine at four cards a week — but the whole point of the brief is a ten-minute morning, and three steps per decision is where that budget goes.
The thing to weigh
This is a convenience decision, not a correctness one. Nothing is broken under (c); the loop runs, the cards get answered, the state stays consistent. The question is whether one tap is worth this repo’s first piece of runtime code and its first stored secret.
If the answer is yes, it should be yes deliberately — the reason there is no backend today is a previous attempt that failed for exactly the sort of reason that is obvious in hindsight.
Note on GO / Cancel specifically
Missions currently start in status: planning and nothing dispatches until that
becomes running. Whichever option wins, GO flips planning → running and
Cancel flips it to cancelled — a status the mission type does not have yet and
would need adding. The same endpoint covers approving a lane-2 task sitting in
review, which is the other button worth having and by then costs nothing extra.