Skip to content

Fix dev build tooling, auto-migrate on startup, port fallback, and dev admin auth bypass#27

Merged
loganlanou merged 5 commits into
mainfrom
fix/dev-tooling-migrations-auth-bypass
May 27, 2026
Merged

Fix dev build tooling, auto-migrate on startup, port fallback, and dev admin auth bypass#27
loganlanou merged 5 commits into
mainfrom
fix/dev-tooling-migrations-auth-bypass

Conversation

@loganlanou
Copy link
Copy Markdown
Collaborator

Summary

Restores a working make dev and adds several dev-quality-of-life features, all reused from sibling repos rather than reinvented.

  • go tool tooling (fixes the build): templ, sqlc, goose are pinned in go.mod via the tool directive and invoked as go tool <name> everywhere. This locks the generator version to the runtime and fixes the undefined: templ.ResolveAttributeValue build break caused by version drift. Module bumped to Go 1.26.
  • Auto-migrate on startup: internal/database.New applies embedded goose migrations on boot (migrations/embed.go), fixing no such table: site_settings on un-migrated DBs.
  • Port fallback + startup URLs: binds the next free port if PORT is busy (internal/portutil, mirrored from gopherguides/hype) and logs clickable localhost + TAILSCALE_HOSTNAME access URLs.
  • Dev-only auth bypass: under -tags dev, loopback-only GET /auth/dev/login / POST /auth/dev/logout let us reach Clerk-gated admin pages for testing. Compiled out of production builds; loopback-gated (RemoteAddr + Host); init() fatals under ENV=production. Documented in CLAUDE.md + new AGENTS.md.
  • CI fixes: derive Go from go.mod (was pinned to 1.23, couldn't build the 1.26 module — the actual cause of the recent red CI), generate via go tool, add dev-tag build/test steps. Cleared pre-existing lint blockers (deferred Close/Quit, dead funcs) so golangci-lint passes.

Test plan

  • go build ./... and go build -tags dev ./... both succeed
  • go test -race ./... and go test -race -tags dev ./... pass
  • golangci-lint run ./... → 0 issues
  • Fresh DB auto-migrates on startup (migrated database to version: 5)
  • Port fallback verified (3999 busy → binds 4000)
  • /auth/dev/login → 302, /admin → 200; spoofed Host → 403
  • Home page + admin dashboard render correctly (stylesheet loads) via Chrome DevTools

🤖 Generated with Claude Code

loganlanou and others added 4 commits May 26, 2026 21:28
Tool dependencies (templ, sqlc, goose) are now pinned in go.mod via the
`tool` directive and invoked as `go tool <name>` in .air.toml, the Makefile,
and CI. This keeps the generator version locked to the runtime version and
fixes the build failure caused by drift (a globally-installed templ generator
emitting `templ.ResolveAttributeValue`, undefined in the older go.mod runtime).

- go.mod: add tool directive (templ v0.3.1020, sqlc v1.31.1, goose v3.27.1);
  bump module to go 1.26.
- .air.toml / Makefile: invoke generators via `go tool`; slim `setup`/`setup-ci`
  (only air + golangci-lint need global installs); add `make templ-update`.
- CI: derive Go version from go.mod (was pinned to 1.23, which couldn't build
  the 1.26 module), generate via `go tool`, drop the global tool installs, and
  add dev-tag build/test steps.
- Clear pre-existing lint blockers so CI's golangci-lint passes: check deferred
  Close/Quit errors (smtp.go, admin_api.go) and remove dead functions
  (cmd/build/main.go).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
internal/database.New now runs all pending goose migrations from an embedded
filesystem (migrations/embed.go) on boot, so a fresh or out-of-date database
is brought to schema without a separate `make migrate` step. This fixes the
"no such table: site_settings" errors that occurred when the DB had never
been migrated. `make migrate` remains for manual/CLI use.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
If the configured PORT is in use, the server now binds the next available
port (internal/portutil.FindAvailable, mirrored from gopherguides/hype) and
logs a warning. It also logs clickable access URLs at startup: localhost and,
when TAILSCALE_HOSTNAME is set, the Tailscale magic-DNS host (reachable from
any tailnet device).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Under `-tags dev` (which `make dev` builds via .air.toml), register
loopback-only GET /auth/dev/login and POST /auth/dev/logout so admin pages
can be tested without Clerk. RequireAdminAccess honors the dev session cookie
before any Clerk verification.

Safety (cannot run in production):
- //go:build dev gates auth_dev.go; auth_dev_stub.go (!dev) is a no-op.
- make build / build-static omit -tags dev, compiling it out entirely.
- Loopback-only: both RemoteAddr and Host must be loopback (defeats
  X-Forwarded-For spoofing and reverse-proxy bypass).
- init() fatals under ENV/ENVIRONMENT=production.
- auth_dev_prod_test.go asserts no /auth/dev/* routes in production builds.

Documents the workflow in CLAUDE.md and a new AGENTS.md so Claude/Codex know
how to test admin/dashboard pages going forward.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
rowe-tech Ready Ready Preview, Comment May 27, 2026 2:46am

v2.1.6 is built with go1.24 and refuses to lint a module targeting go 1.26
("language version (go1.24) ... lower than targeted (1.26.0)"). v2.10.1 is
built with go1.26.1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@loganlanou loganlanou merged commit e3bc0c2 into main May 27, 2026
2 of 3 checks passed
@loganlanou loganlanou deleted the fix/dev-tooling-migrations-auth-bypass branch May 27, 2026 02:34
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