CI passed at a3a4402 (amadan ci status exit 0). Not merged; waiting for review.
Review: rastrillo off the frozen path (iOS zoom-on-tap) open
On branch chore/rastrillo-path
Review request: move Docs' rastrillo imports off the frozen path. Paul approved this on 2026-09-30 (polish audit r3 SUMMARY, item 1). Recipe: Sheets' finished migration (oficina/sheets #44, main a5c17ab).
Why. Docs took rastrillo's ui, auth, sessions, db, migrate, mail and csrf from github.com/carlosframework/rastrillo, which stops at v0.23.0. Only assertion, crypto and one sessions reader came from amadan.net/rastrillo/rastrillo. So Docs had no rastrillo ui fix since 2026-08-31, including the iOS zoom-on-tap fix in tokens.css. On iOS, every text field in Docs zoomed the page on its first tap.
Pin. amadan.net/rastrillo/rastrillo at d9c28d7 (v0.26.1-0.20260908132728), not 29e4491. Docs already required d9c28d7, and teamsessionreader.go uses its sessions.FromContext. Going down to 29e4491 would have been a downgrade. d9c28d7 is 29e4491 plus three commits, all in sessions (the context-bounded lookup). It does not contain 272ca02, so auth.Config.Body is not available. Per the brief I did not bump to get it, and Body: chrome.EmailBody("Docs") is not set.
Commits
- fbd51b1, TestNoZoomOnTap (browser tag). Red on purpose. It turns on chromedp touch emulation, reloads, asserts
matchMedia('(pointer: coarse)'), and lists every visible text control under 16px. On origin/main's code it fails on the door, the list's search and new-document fields, the title field, the three toolbar comboboxes, the share page's address and published-link fields, and the open jump-to palette (12.5 to 14px). The gate now runsgo vet -tags browser ./internal/docs/, so the file can't silently stop compiling. - 5c168c6, the move. - Every import is rewritten. - The CLI is pinned as a go.mod
toolat d9c28d7. -scripts/build-release.shstampsamadan.net/rastrillo/rastrillo.BuildVersion. The existing TestReleaseBinaryReportsItsVersion goes red ("dev") if the old symbol is put back. - teamsessionreader.go no longer converts between two Session types. - One old-path import remains:presessionsin native.go, for rastrillo/native's server, which still takes the old*sessions.Sessions. The newTestNoPreMoveRastrillo(internal/lint) forbids every other old-path import, andTestNoSessionsUserIDnow bansUserIDon both paths. -go tool rastrillo doctor --fixfinds nothing on disk to check and writes nothing, because Docs serves every asset from memory. TestBusyRuleIsLinkedAndServed now also fails if a rastrillo.js, busy.js, tokens.css or picker script ever lands instatic/orbrand/. - The principal-compat probe files (testdata) open the db through the step file, so the shared main compiles against both old and new trees. I checked both builds (3ed7665 and HEAD). - 62b9595, estilo main (530cb93). This brings estilo 4fc9be3's title-field fix. It also brings the door copy nits (1a41328) and the negative-tone menu row (759a8ff). Docs' tests pass with both.
- 61d9e78, three Docs selectors that outweigh tokens.css's bare
input. Each getsmax(1rem, 1em)under(pointer: coarse): - the toolbar comboboxes and their selects (--rst-fs-sm, 12.5px); - the published-link field (12.5px); - the jump-to field (font: inherit, 14px). The editor's contenteditable is left alone. Mouse styles are unchanged. - a3a4402, nativeexchangetest.go: exchange, expiry and revocation through the router, across both sessions packages, on an https origin (the
__Host-cookie). Modelled on Sheets'.
What the upgrade changes for Docs (v0.23 to d9c28d7)
- tokens.css: text controls are 16px and
touch-action: manipulationunder a coarse pointer. Mouse geometry is unchanged: the dump of every control across 36 mouse views shows zero differences outsidetouch-action. The radio inputs on the share page also go from 13.3px to 16px on touch. - ui JS: select.js and the shim are unchanged. Docs serves estilo's shim and busy.js either way. datetime.js changed and calendar.js is new, but Docs has no date control and doesn't link calendar.js.
- Partials: field, form-foot, confirm-form, detail-list, meter, job-status and the date fields all changed, and stat is new. Of these, Docs renders only
fieldandchoice-field, on the share page, with no visible change. - Server side: the context-bounded session lookup, mail honouring its context, and
auth.Config.SubjectFor(unset in Docs). The schema and migration ledger are unchanged.
Evidence
TMPDIR=/tmp .amadan/ci.d/10-gate: gate: ok. The editor bundle and wasm match a fresh build, so neither changed.native/scripts/check-native.shwith rustup's cargo first on PATH: Native checks passed (core-only=0).- TestNoZoomOnTap is green at a3a4402. The red outputs at each stage are in polish-audit/r3/scripts/migrate-docs-zoom-red.txt: origin/main's code, then new rastrillo with the estilo bump but no Docs rules.
- New tests seen red: - polish-audit/r3/scripts/migrate-docs-native-red.txt has the native tests under four mutations of native.go: an http origin, sessions minted already expired, a minted row that resolves to someone else, and deletes ignored. - polish-audit/r3/scripts/migrate-docs-guards-red.txt has three more. TestNoPreMoveRastrillo fails 74 times on origin/main and on a stray old-path import. The busy guard fails on a stray static/rastrillo.js. The release stamp test answers "dev" with the old symbol.
- Shared chrome check (r2-docs-check.config.mjs) against this build: 591 ok, 0 FAIL.
- Release stamp:
make release(linux/arm64) and a darwin build report v0.1.0-41-ga3a4402, and the darwin binary's/api/versionanswers that version. - A database created by the old build boots on the new one. The old build seeded the documents, created a document, published a link and signed in. On the new build the old cookie gets 200, both documents list, the Millbrook text renders, and the old public link serves it. The schema and all 13 migration ledger entries are unchanged.
- Screenshots are in polish-audit/r3/shots/migrate-docs-{before,after}-*.png. They cover the door (with its sent and error states), signed-out and signed-in 404, the list, the document, the open jump-to palette, an open toolbar combobox, share, share once published, and the public page, each at 1440, 390 and 320, with a mouse and on touch (
-touch-). The script is polish-audit/r3/scripts/migrate-docs-shots.mjs. - The touch shots are viewport-sized, plus a-bottomshot for tall pages. Any capture beyond the viewport made Chromium droppointer: coarse. - No page overflows in any view, either build.
Not in this branch: moving rastrillo/native's server to the new path; rastrillo main (v0.27 CSP and time layout); auth.Config.Body (needs 272ca02).
Reviewer: Astra (GPT-6-Astra via Codex).
VERDICT: APPROVE
- No actionable findings. I found no correctness, security, migration, data-loss or mouse-layout regression requiring a change.
Reviewed the whole branch at a3a4402af94d8cffcc676fbcf6e6cc1c1571260b against freshly fetched origin/main and merge base 73a54618c84ad1465b0267935aedc0ca73307e84, following AGENTS.md and REVIEW-BRIEF.md. Read this discussion and my Sheets #44 review, including its follow-up fixes.
The session pin and authority boundaries are sound:
- The precise
29e4491..d9c28d7history is 997935b, 961863d, d9c28d7. The first is the identity-assertion merge, whose tree is identical to29e4491; it adds no content relative to that comparison point.961863daddsFromContext, routes its lookup throughQueryRowContext, and adds cancellation/parity tests and documentation.d9c28d7tightens those tests, suppresses logging only for errors matching the caller's cancellation, and cleans up the review scope. The net production change is confined to sessions. Neither ordinaryFromnor the existing lookup changes its unbounded/background-context behavior. internal/docs/team_session_reader.go:24calls the same canonical reader Docs already used, without the now-unnecessary structural conversion. It still checks for exactly one acceptable cookie first.FromContextreads the database; it does not trust a cachedCurrentsession. Cancellation refuses access without refreshing, revoking or deleting the session. The stream guard subsequently checks context expiry, resolves identity, compares the actor/Home subject, rechecks document permission, and bounds the write by the remaining lease. The migration does not turn a session subject into admission or an app person ID.- Both session packages retain the same schema, token and cookie contract: HTTPS uses
__Host-rastrillo_session, Path=/, Secure, HttpOnly, SameSite=Lax and no Domain; HTTP uses the unprefixed name. Tokens are 32 random bytes in unpadded base64url, with a hex SHA-256 stored in SQLite. Both default to 30 days, persist UTC RFC3339 timestamps, reject expiry and revoke by deleting the token-hash row. - The native bridge in
internal/docs/native.go:27is deliberate and compatible. Native exchange constructs a fresh request context, rechecks the approved browser cookie through Docs' current admission chain, independently resolves it through the legacy sessions package, then mints a distinct token. The new router tests cover HTTPS naming, pending exchange, wrong proof, identity continuity, one-use exchange, expiration before approval/after approval/after mint, and independent browser/native revocation. All pass. The team-session reader tests and upstream sessions, auth, mail, CSRF and native/server tests also pass.
Verification I ran independently:
TMPDIR=/tmp .amadan/ci.d/10-gate: gate: ok. This includes browser-tag vet, all Go tests, Rust tests, both wire directions, fresh bundle/WASM checks, formatting and the application build. Remote CI also reports passed at this exact SHA.native/scripts/check-native.sh, with rustup cargo first on PATH: Native checks passed (core-only=0), including the Apple tests.go test -tags browser ./internal/docs/ -run TestNoZoomOnTap -count=1, using Playwright Chromium 1148 throughRASTRILLO_CHROME: pass. Copied the unchanged test into a separate main worktree and supplied only its browser-test dependencies: it fails on main's door, list, title, toolbar, share address/link and jump-to fields at 12.5–14px. This checks computed styles under an asserted coarse pointer; it is not a direct Mobile Safari viewport-zoom measurement.- Shared chrome check with the supplied
r2-docs-check.config.mjs, against the reviewed release binary: 591 ok, 0 FAIL. - Deliberate mutations in a separate scratch worktree: an HTTP native-session origin makes the new exchange test fail at approval; removing the toolbar coarse-pointer rule makes the new zoom test report all three 12.5px comboboxes; an extra old-path import fails
TestNoPreMoveRastrillo; aliasedUserIDcalls failTestNoSessionsUserIDindependently on both paths. Restored code passes. - Busy-rule mutations: a copied
static/rastrillo.jsfails the disk guard. More importantly for this app, replacing the in-memorybusy.ShimJS()withui.ShimJS()failsTestBusyRuleIsLinkedAndServedon both the linked fingerprint and the served bytes. The actual layout serves Estilo's split shim and busy.js together; the new framework path does not substitute the combined shim. - The committed editor bundle and embedded WASM are unchanged from main and byte-identical to their fresh builds. Editor SHA-256:
fedd7579de35d95f263226c577d9707b51f39bf62d0db7413d471bcfeafe3606; WASM:21e982e3075e23558c0203d229cafcc35095624d667d8c715154c08c45bade26. make releasesucceeds for Linux/arm64. A Darwin/arm64 release built through the same script answers/api/versionwithv0.1.0-41-ga3a4402. The existing release-version test also passes in the gate.- Built main with its original application dependencies, booted it, signed in, seeded sample documents, created a document and published a link. Stopped that binary and booted the reviewed release over the same database. The saved old cookie still authenticates the list, sample document and created document; the old public link serves the Millbrook content. Schema and all 13 migration ledger entries are unchanged.
I inspected the supplied before/after screenshots, including narrow touch document, jump-to and published-sharing views. Pixel-compared all 36 mouse pairs: 23 are identical; the others differ in the sky, generated public-link text, or a tiny combobox rendering detail. I also compared the author's saved geometry/style dumps: all 36 mouse views agree after excluding touch-action. The three Docs overrides and Estilo's title fix are coarse-pointer-only. Touch fields grow without the inspected pages overflowing.
Estilo 0b4d92c..530cb93 changes door interpolation from printf slots to named tokens, adds copy-set email helpers, adds opt-in danger menu rows, and fixes touch title sizing. Docs uses the default English copy and does not opt into Danger; the rendered door copy is preserved and its regression tests pass. Among the changed framework partials, Docs invokes field with a map and no Primary flag; choice-field is unchanged. It has no enhanced date controls. The additional auth subject hook remains unset. Mail's substantive change is context-aware delivery with a 30-second fallback when the caller has no deadline; schema, CSRF and migration production code are unchanged after normalizing the module path. This pin does not bring the later CSP/time-storage migration.
No existing checkout was moved or edited, and no commit, push, merge or deployment was made. All three review worktrees, the fixture server and its database were removed. Disk was checked with df -h /System/Volumes/Data. Posted as the configured agent account, with this Codex session identified, never with -as-human.