Skip to content

docs: chapter 2/6 + install page follow-ups (csrf regex, posts migration rename, headless brew)#2398

Merged
bpamiri merged 1 commit intodevelopfrom
claude/fresh-vm-batch-f-doc-fixes
May 1, 2026
Merged

docs: chapter 2/6 + install page follow-ups (csrf regex, posts migration rename, headless brew)#2398
bpamiri merged 1 commit intodevelopfrom
claude/fresh-vm-batch-f-doc-fixes

Conversation

@bpamiri
Copy link
Copy Markdown
Collaborator

@bpamiri bpamiri commented May 1, 2026

Summary

Three carry-over findings from the 2026-05-01 fresh-VM tutorial run that survived the recent doc sweeps in #2395 and #2396.

F8 — chapter 6 csrf scrape regex matches the wrong attribute order

The "known-working signup smoke test" used:

grep -oE 'name="csrf-token" content="[^"]+"'

…but vendor/wheels/view/miscellaneous.cfc:404 deliberately sorts attributes alphabetically before emitting (the comment says: "since the order of a struct can differ we sort the attributes in alphabetical order before placing them in the HTML tag (we could just place them in random order in the HTML but that would complicate testing for example)"). So the actual emit is content="..." name="csrf-token". The old regex returned an empty TOKEN and POSTs silently failed with Wheels.InvalidAuthenticityToken.

Fix: swap regex to match the actual order. Patching $tag's emit order would have been cleaner from the chapter's perspective but would break visual baselines and downstream tests across the entire view layer for one tutorial recipe — wrong scope.

F7 — chapter 2 "feel free to keep the generator's timestamp" is a hidden footgun

Sounds permissive but breaks chapter 7. Chapters 5/6 hardcode migration timestamps 20260419130000, 20260419140000, 20260419150000 for comments / users / add_user_to_posts. If the posts migration sorts after them (e.g. a May-2026 timestamp from a current-day generator), the dev DB still works because migrations apply incrementally as files land — but the test DB in chapter 7 runs all four from scratch in timestamp order, hits add_user_to_posts before posts exists, and bails out. Result: posts table missing from the test DB, controller specs run against an empty schema.

Fix: rename is now mandatory with a <Aside type="caution"> explaining the dependency chain.

F1 — install page didn't cover headless Homebrew install

The official curl | bash installer requires a TTY: it shells out to sudo -n true which always prompts even when the user is an admin (peter here is in the admin group, but sudo -n returns non-zero without a password). Setting NONINTERACTIVE=1 doesn't help — the sudo gate still fires. This is a hard wall for any non-interactive context (CI, agent shells, packer, provisioning scripts).

Fix: added a <Aside type="caution" title="Headless / non-interactive installs"> callout with three concrete options:

  • User-prefix git clone install (officially "unsupported" but works; trade-off is no bottles)
  • Pre-bake the image (Vagrant / Packer / Tart / Anka)
  • Provisioning frameworks (Ansible's community.general.homebrew module)

Plus a recommendation: for fresh agent/CI VMs, the user-prefix git clone is the path of least resistance.

Files changed

  • web/sites/guides/src/content/docs/v4-0-0-snapshot/start-here/installing.mdx — F1 callout
  • web/sites/guides/src/content/docs/v4-0-0-snapshot/start-here/tutorial/02-first-model.mdx — F7 mandatory rename
  • web/sites/guides/src/content/docs/v4-0-0-snapshot/start-here/tutorial/06-authentication.mdx — F8 regex + explanatory paragraph

Notes

  • F9 (curl --data-urlencode "[email protected]" mangling) was already addressed by #2395 — chapter 6 now uses raw --data with %40/%5B/%5D pre-encoding. Dropped from this PR.
  • This is a follow-up batch to the 16-finding fresh-VM run; the framework-side bug from the same run (F6 — SQLite datetime quote-wrapping) shipped in #2397.

Test plan

  • All three changes are prose-only — no compile-tested code blocks touched
  • CI matrix green
  • Re-run fresh-VM tutorial post-merge to confirm the three findings no longer surface

🤖 Generated with Claude Code

…eadless brew install

Three follow-ups from the 2026-05-01 fresh-VM tutorial run that survived the
recent doc sweeps (#2395, #2396).

F8 — chapter 6's "known-working signup smoke test" regex assumed
`name="csrf-token" content="..."` attribute order, but Wheels'
`vendor/wheels/view/miscellaneous.cfc:404` `$tag` helper sorts attributes
alphabetically for deterministic test output, so the actual emit is
`content="..." name="csrf-token"`. The old regex returned an empty TOKEN
and POST silently failed with `Wheels.InvalidAuthenticityToken`. New regex
matches the actual order, plus an explanatory note so future readers know
to check attribute order if the scrape ever returns empty.

F7 — chapter 2 said "feel free to keep the generator's timestamp instead"
of renaming to `20260419120000`. That sounds permissive but is actually a
footgun: chapters 5/6 hardcode timestamps `20260419130000`,
`20260419140000`, `20260419150000` for comments / users / add_user_to_posts.
If the posts migration sorts after them (e.g. May 2026 from a current-day
generator), the dev DB still works because migrations apply incrementally
as files are added — but the test DB in chapter 7 runs them all from
scratch in timestamp order, hits `add_user_to_posts` before `posts` exists,
and bails. Now the rename is mandatory with a callout explaining the
dependency chain.

F1 — the install page only documented the interactive Homebrew installer.
That installer's `sudo -n true` precheck always fails in a non-interactive
context (CI, agents, packer, provisioning scripts), even with
`NONINTERACTIVE=1` set. Added a "Headless / non-interactive installs"
caveat with three concrete options (user-prefix `git clone`, pre-baked
image, Ansible's homebrew module) and a recommendation for the common
agent/CI VM case.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bpamiri bpamiri merged commit 4f54b3b into develop May 1, 2026
10 checks passed
@bpamiri bpamiri deleted the claude/fresh-vm-batch-f-doc-fixes branch May 1, 2026 17:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant