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

Merged opened this in answer to

Check · Review · Land · Live done — Landed and live in production.

Merged

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

opened this

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.ts holds 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/preview with {sha} calls it, and the route has an OpenAPI entry and a line in docs/APPS.md.
  • Git refs: exactRefOid and moveRefLeased are in git/branches.ts.
  • PageOptions.frameSrc: this loosens the Content-Security-Policy, so reviewers should read it. It adds one origin to frame-src for the page that sets it and relaxes nothing else. Jay's version let any string through. Mine accepts only a bare scheme://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. parseFrom already lives in tell_from.ts on 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: notesIntent needs git/builds.ts, and frameSrc and the two ref functions have no caller yet. They arrive with the pins pull and the Iterations pull.
  • Left absent: the demo environment, refs/demo and the reserved arcade slug.
  • Not taken: the dev-UI wording rewrites in env_words.ts and runtime.ts. I kept only the build <sha> label in env_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

Closes #9041

commented

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.ts holds 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/preview with {sha} calls it, and the route has an OpenAPI entry and a line in docs/APPS.md.
  • Git refs: exactRefOid and moveRefLeased are in git/branches.ts.
  • PageOptions.frameSrc: this loosens the Content-Security-Policy, so reviewers should read it. It adds one origin to frame-src for the page that sets it and relaxes nothing else. Jay's version let any string through. Mine accepts only a bare scheme://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. parseFrom already lives in tell_from.ts on 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: notesIntent needs git/builds.ts, and frameSrc and the two ref functions have no caller yet. They arrive with the pins pull and the Iterations pull.
  • Left absent: the demo environment, refs/demo and the reserved arcade slug.
  • Not taken: the dev-UI wording rewrites in env_words.ts and runtime.ts. I kept only the build <sha> label in env_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

commented

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/preview with {"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 requested — before the latest push

Changes needed (none are security-high; all are list misses):

  1. Dead code: frameSrc/frameSources (web/layout.ts), moveRefLeased and exactRefOid (git/branches.ts) have no caller. "A function nobody can call is not done." The relaxed CSP frame-src in particular ships with no user. Drop them and their tests from build-core.test.ts; bring them in with the pull that uses them.
  2. 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.
  3. Scope: the actions/tell.ts body change and test/tell-body.test.ts are unrelated to build previews. Split into their own small pull (direction: small single-purpose pulls).
  4. 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.
  5. 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.
  6. 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.

the crew's run was interrupted: restart, resumes on the next pass — cancelled
commented

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 b key, in src/tui/screens/deploys.ts. It asks for a full 40-character commit id and calls previewBuild, 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.md is new. It covers the terminal key, the API and the limit.
  • test/tui-deploys-build.test.ts is 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_MS in src/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.ts works.
  • The limit gives rate_limited from 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.ts gains 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, exactRefOid and frameSrc, the tell fix, test/build-core.test.ts and test/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: the POST /alice/show/builds/preview web-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

commented

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 b binding now comes last in the list, after X, and its label is shortened to "preview a commit". docs/features/build-preview.md and my own test use the new wording.
  • Checks: tui-appmembers, tui-deploys-build and all 47 tests in test/tui-deploy*.test.ts pass. bun x tsc --noEmit and bun scripts/gate.ts are 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.

Approved

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.

commented

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.).

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs