Lock bootstrap admin token until password is changed #6

Merged
Ghost merged 1 commits from fix/helix-2-bootstrap-lock into master 2026-08-31 22:57:37 -05:00

Closes #2.

  • Bootstrap lock: login with the well-known default password issues a JWT with bootstrap=true. Mutating admin API other than POST /api/login and POST /api/users/me/password returns 403 until a non-default password is stored. Reads stay allowed so the UI can prompt for a change. After change-password, default-password login fails (401) and leftover bootstrap tokens stay locked.
  • Non-dev first boot requires ADMIN_PASSWORD (cannot be the well-known default); otherwise the process refuses to start. Development may boot with an empty password for bootstrap tests; CI/dev tests set ADMIN_PASSWORD so they do not leave the default password as a working admin.
  • Admin listener defaults to loopback (127.0.0.1). Override with ADMIN_HOST. Sample compose no longer publishes :81.

JWT secret persist is unchanged. Proxy/nginx behavior is unchanged. Not merged.

Closes #2. - Bootstrap lock: login with the well-known default password issues a JWT with `bootstrap=true`. Mutating admin API other than `POST /api/login` and `POST /api/users/me/password` returns 403 until a non-default password is stored. Reads stay allowed so the UI can prompt for a change. After change-password, default-password login fails (401) and leftover bootstrap tokens stay locked. - Non-dev first boot requires `ADMIN_PASSWORD` (cannot be the well-known default); otherwise the process refuses to start. Development may boot with an empty password for bootstrap tests; CI/dev tests set `ADMIN_PASSWORD` so they do not leave the default password as a working admin. - Admin listener defaults to loopback (`127.0.0.1`). Override with `ADMIN_HOST`. Sample compose no longer publishes `:81`. JWT secret persist is unchanged. Proxy/nginx behavior is unchanged. Not merged.
Ghost added 1 commit 2026-08-31 22:54:25 -05:00
Lock bootstrap admin token until password is changed.
Format / gofmt (push) Successful in 7s
CI / Build (push) Successful in 14s
Format / gofmt (pull_request) Successful in 7s
CI / Build (pull_request) Successful in 13s
CI / Go Tests (push) Successful in 50s
CI / Go Tests (pull_request) Successful in 48s
13070a275d
Closes #2: bootstrap JWTs cannot mutate admin APIs except change-password, production requires ADMIN_PASSWORD on first boot, admin binds loopback.

Reviewed against #2.

Bootstrap claim + middleware lock, leftover bootstrap JWTs stay mutating-403 after change-password, production first-boot refuses without ADMIN_PASSWORD and rejects the well-known default, admin bind is loopback, compose no longer publishes :81. Tests actually cover the lock, not just login. CI green. Merging.

Nit for next time, not blocking: testLoginPassword / testAdminPassword live in bootstrap.go and ship in the production binary. Put test helpers in _test.go.

Reviewed against #2. Bootstrap claim + middleware lock, leftover bootstrap JWTs stay mutating-403 after change-password, production first-boot refuses without ADMIN_PASSWORD and rejects the well-known default, admin bind is loopback, compose no longer publishes :81. Tests actually cover the lock, not just login. CI green. Merging. Nit for next time, not blocking: `testLoginPassword` / `testAdminPassword` live in `bootstrap.go` and ship in the production binary. Put test helpers in `_test.go`.
Ghost merged commit 097906f5b5 into master 2026-08-31 22:57:37 -05:00
Sign in to join this conversation.