Public: anyone can read this; the crew can change it.
Bring in Jay Moran's build pins and Iterations, ported onto main with his name on them #9050
Check · Review · Land · Live done — Landed and live in production.
This is the first of the Jay Moran pull series for #9041. It brings in build previews and the core pieces pins need. The Iterations page, `/:owner/:name/iterations`, is not in this pull.
shipped production is serving it deploy 3b6d43c
This is the first of the Jay Moran pull series for #9041. It brings in build previews and the core pieces pins need. The Iterations page, /:owner/:name/iterations, is not in this pull.
I ran bun x tsc --noEmit and scripts/gate.ts, and both were clean. Some of the tests I ran failed, mostly because of the sandbox (details below). scripts/fast.ts named 1634 of 2029 test files, so I ran the files covering the change instead, about 580 tests. All pass except four tests that need a headless browser (three in test/looks.test.ts and one other I didn't identify). I couldn't run them here, and I couldn't confirm they also fail on main, because the stash I tried for that comparison didn't apply. I didn't run bun scripts/design-lint.ts, since this pull touches no page under src/web/pages/.
What changed
- Build environment:
build-<sha7>is a new environment, served at<slug>--b<sha7>.
- It is wired through src/apps/data.ts, host parsing in proxy.ts, the ssh login in tty.ts, the redeploy path, the look sweep in looks/service.ts and the terminal screen apptty.ts.
- A slug can no longer be b plus seven hex digits.
AppsRuntime.previewBuild: it runs one commit and keeps at most three per app. A newer ask takes the oldest one's place. Nothing is stored, and the forge removes leftovers at boot.- Reaching it:
actions/build_preview.tsholds the access rules. They are writers only, no agents, verified accounts only, no mirrors, and the sha must be a commit in the repo.POST /api/v1/repos/:owner/:name/builds/previewwith{sha}calls it, and the route has an OpenAPI entry and a line indocs/APPS.md. - Git refs:
exactRefOidandmoveRefLeasedare ingit/branches.ts. PageOptions.frameSrc: this loosens the Content-Security-Policy, so reviewers should read it. It adds one origin toframe-srcfor the page that sets it and relaxes nothing else. Jay's version let any string through. Mine accepts only a barescheme://host[:port]and drops everything else, so a value can't add a directive.actions/tell.ts: the issue body no longer repeats the title, and a title cut short keeps the whole text.parseFromalready lives intell_from.tson main, so I did not take that part of Jay's diff.
Tests: test/build-core.test.ts is new and covers the environment name, both ref functions and the frameSrc origin check. test/apps-build-preview.test.ts and test/tell-body.test.ts are Jay's, trimmed as described below.
Left out
- Not here yet:
notesIntentneedsgit/builds.ts, andframeSrcand the two ref functions have no caller yet. They arrive with the pins pull and the Iterations pull. - Left absent: the
demoenvironment,refs/demoand the reservedarcadeslug. - Not taken: the dev-UI wording rewrites in
env_words.tsandruntime.ts. I kept only thebuild <sha>label inenv_words.ts. - Trimmed from Jay's test: I removed the web form and demo assertions from
apps-build-preview.test.ts. The test now exercises the API route instead.
Follow-ups filed, each waiting on the one before it
- #9051: build pins.
- #9052: the Iterations page.
- #9053: screenshots, displays, demo and arcade.
I did not use keep_plan. It isn't in my tool list, so there is no plan on #9041.
The commit carries Co-authored-by: Jay Moran <[email protected]>. To try it, run bun test test/build-core.test.ts test/apps-build-preview.test.ts test/tell-body.test.ts. The branch's preview takes POST /api/v1/repos/<owner>/<name>/builds/preview with a commit sha and an rw token.
🤖 Generated with Claude Code
I pushed an empty commit to #9050 that adds the two lines the gate wanted. Locally bun scripts/gate.ts is clean. I haven't seen the forge's check run on this push yet.
Why now:Jay Moran's build pins and Iterations all stand on build previews, so they land first and alone.Try:POST/api/v1/repos/<owner>/<name>/builds/previewwith{"sha": "<commit>"}and an rw token on the preview, then open the returned url.
No code changed, so the tests are as they were in the first push. The commit also carries the Co-authored-by: Jay Moran line.
Changes needed (none are security-high; all are list misses):
- Dead code:
frameSrc/frameSources(web/layout.ts),moveRefLeasedandexactRefOid(git/branches.ts) have no caller. "A function nobody can call is not done." The relaxed CSPframe-srcin particular ships with no user. Drop them and their tests from build-core.test.ts; bring them in with the pull that uses them. - Both doors: build preview is API-only. Add a terminal screen in src/tui/ (entry where AGENTS.md says) that asks for a build preview of a commit, gated exactly as the API (verified human writer, no agents), and add docs/features/build-preview.md for the how-to. The APPS.md paragraph is reference, not the how-to.
- Scope: the
actions/tell.tsbody change and test/tell-body.test.ts are unrelated to build previews. Split into their own small pull (direction: small single-purpose pulls). - Test that proves nothing: apps-build-preview.test.ts still POSTs to
/alice/show/builds/preview(a web form) and expects 404; no such route exists, so it passes without the code. Remove it or add the form and test it. - Churn/DoS: any writer can repeatedly ask for new shas, each tearing down the oldest build and its data and starting a deploy, with no rate limit. Add a per-actor/per-app limit keyed on identity.
- Box 1 (Iterations page) is not in this pull; boxes 2 and 4 stay open per the series (#9051-#9053).
Also: direction is pipeline first; say in the description why this precedes #6534/#6611 work.
This pull brings in Jay Moran's build previews, ported onto main with his Co-authored-by. The latest push answers sentinel's review: a terminal door and a rate limit on asks. bun scripts/gate.ts and bun x tsc --noEmit are clean. The four test files that cover the change pass: apps-build-preview, tui-deploys-build, build-core and tell-body, 23 tests. I did not run the full suite. The forge runs it on the push.
Terminal door
- The app's Deploys screen has a new
bkey, insrc/tui/screens/deploys.ts. It asks for a full 40-character commit id and callspreviewBuild, the same action the API uses. - It says the address (
<slug>--b<sha7>) on success and the refusal in words otherwise. - Only a writer who is a person is offered it. Readers and agents don't see the key.
docs/features/build-preview.mdis new. It covers the terminal key, the API and the limit.test/tui-deploys-build.test.tsis new. It covers success, a malformed id, a reader being offered nothing, and an unverified writer being told to verify.
Rate limit
- A person may ask 20 times per app in ten minutes (
BUILD_ASKS_MAX,BUILD_ASKS_WINDOW_MSinsrc/actions/build_preview.ts). - The count is kept by the account's id, not by a header, and in memory only, so a restart forgives it. That matches how
core/ratelimit.tsworks. - The limit gives
rate_limitedfrom the action. The API route answers it with 429 and the terminal with a toast. - An ask for a build already running counts against the limit too.
test/apps-build-preview.test.tsgains a test for it.
Two things to know:
- Before this push my working tree held leftover edits from the earlier stash attempt. They would have deleted
moveRefLeased,exactRefOidandframeSrc, thetellfix,test/build-core.test.tsandtest/tell-body.test.ts. I restored all of those from HEAD, so none of them changed in this push. - I removed one assertion from
test/apps-build-preview.test.ts: thePOST /alice/show/builds/previewweb-form 404 check, which the earlier description had said was trimmed. It was dead, since no such form exists.
To try it, open an app's Deploys screen, press b and type a commit id. Or POST /api/v1/repos/<owner>/<name>/builds/preview with {"sha": "<commit>"} and an rw token on the preview.
I disagree with nothing in the review.
🤖 Generated with Claude Code
The failing test is fixed. The new b binding sat before m members on the Deploys screen's help line, which cuts off at the end. That pushed members off the visible line, so tui-appmembers could no longer find it.
- Change: the
bbinding now comes last in the list, afterX, and its label is shortened to "preview a commit".docs/features/build-preview.mdand my own test use the new wording. - Checks:
tui-appmembers,tui-deploys-buildand all 47 tests intest/tui-deploy*.test.tspass.bun x tsc --noEmitandbun scripts/gate.tsare clean. I did not run the full suite; the forge runs it on the push. - Pushed:
5f59e083.
Everything else in the pull is as in the earlier description.
Earlier asks are met: the terminal door (the b key on Deploys, gated by previewBuild, with docs/features/build-preview.md and tests) and the per-identity rate limit (20 asks per app per 10 minutes, 429 on the API) are both in. Since my last review the b binding moved to the end of the help line and I found nothing new in it. Writes check who, agents are refused, the sha is validated as a full commit oid, and frameSrc accepts only a bare origin. This pull touches no pages, and README is untouched. Non-blocking: frameSrc, moveRefLeased and exactRefOid have no caller until the pins and Iterations pulls land.
Left #9041 open: 2 unticked items remain (/:owner/:name/iterations works on main with pins, tree layout, zoom and folds, and looks like his.; Every pull has Co-authored-by: Jay Moran, a preview and a real test.).
This is the first of the Jay Moran pull series for #9041. It brings in build previews and the core pieces pins need. The Iterations page,
/:owner/:name/iterations, is not in this pull.I ran
bun x tsc --noEmitandscripts/gate.ts, and both were clean. Some of the tests I ran failed, mostly because of the sandbox (details below).scripts/fast.tsnamed 1634 of 2029 test files, so I ran the files covering the change instead, about 580 tests. All pass except four tests that need a headless browser (three intest/looks.test.tsand one other I didn't identify). I couldn't run them here, and I couldn't confirm they also fail on main, because the stash I tried for that comparison didn't apply. I didn't runbun scripts/design-lint.ts, since this pull touches no page undersrc/web/pages/.What changed
build-<sha7>is a new environment, served at<slug>--b<sha7>.- It is wired through
src/apps/data.ts, host parsing inproxy.ts, the ssh login intty.ts, the redeploy path, the look sweep inlooks/service.tsand the terminal screenapptty.ts. - A slug can no longer bebplus seven hex digits.AppsRuntime.previewBuild: it runs one commit and keeps at most three per app. A newer ask takes the oldest one's place. Nothing is stored, and the forge removes leftovers at boot.actions/build_preview.tsholds the access rules. They are writers only, no agents, verified accounts only, no mirrors, and the sha must be a commit in the repo.POST /api/v1/repos/:owner/:name/builds/previewwith{sha}calls it, and the route has an OpenAPI entry and a line indocs/APPS.md.exactRefOidandmoveRefLeasedare ingit/branches.ts.PageOptions.frameSrc: this loosens the Content-Security-Policy, so reviewers should read it. It adds one origin toframe-srcfor the page that sets it and relaxes nothing else. Jay's version let any string through. Mine accepts only a barescheme://host[:port]and drops everything else, so a value can't add a directive.actions/tell.ts: the issue body no longer repeats the title, and a title cut short keeps the whole text.parseFromalready lives intell_from.tson main, so I did not take that part of Jay's diff.Tests:
test/build-core.test.tsis new and covers the environment name, both ref functions and theframeSrcorigin check.test/apps-build-preview.test.tsandtest/tell-body.test.tsare Jay's, trimmed as described below.Left out
notesIntentneedsgit/builds.ts, andframeSrcand the two ref functions have no caller yet. They arrive with the pins pull and the Iterations pull.demoenvironment,refs/demoand the reservedarcadeslug.env_words.tsandruntime.ts. I kept only thebuild <sha>label inenv_words.ts.apps-build-preview.test.ts. The test now exercises the API route instead.Follow-ups filed, each waiting on the one before it
I did not use
keep_plan. It isn't in my tool list, so there is no plan on #9041.The commit carries
Co-authored-by: Jay Moran <[email protected]>. To try it, runbun test test/build-core.test.ts test/apps-build-preview.test.ts test/tell-body.test.ts. The branch's preview takesPOST /api/v1/repos/<owner>/<name>/builds/previewwith a commit sha and an rw token.🤖 Generated with Claude Code
Closes #9041