Skip to content

Write the published demo password on every migration - #806

Merged
MBombeck merged 2 commits into
mainfrom
fix/demo-published-credentials
Aug 21, 2026
Merged

Write the published demo password on every migration#806
MBombeck merged 2 commits into
mainfrom
fix/demo-published-credentials

Conversation

@MBombeck

Copy link
Copy Markdown
Owner

The demo refresh copied password_hash straight from the source account, and
the README beside it asserted "demo login works". That only held while the
source account happened to use the password this project publishes. The source
is the operator's own instance, so once that password was rotated the demo
began rejecting the credentials the README hands to every visitor, and nothing
noticed until someone was locked out of the shop window and filed #805.

Reproduced before touching anything: POST /api/auth/login on the demo answers
401 for the published credentials.

What changed

The load now sets the demo password explicitly instead of inheriting one. Right
after the users row lands it is given the same Argon2id literal the seed script
writes, then read back and compared byte for byte; a mismatch aborts the run
rather than waiting for a stranger to find it at a login screen.

The statement travels on psql's stdin. Interpolating it into the ssh command
string would let the remote shell expand the hash's $argon2id, $v, $m,
$t and $p segments to empty strings and store something no password can
match, which is the same outage wearing a different hat.

scripts/__tests__/demo-published-password-guard.test.ts pins three things: the
literal matches the seed script's copy, the overwrite plus its verification are
present, and the hash never appears inside an ssh command string.

Proof

Both mutations were applied, confirmed applied, and confirmed red on the
dedicated test before being restored:

  • one character changed in the hash → the drift assertion fails
  • the overwrite replaced with a no-op UPDATE → the overwrite assertion fails

Full battery green: typecheck, lint, format:check, build, and 21449 unit tests
across 1886 files. One run tripped a vitest worker teardown race in
stress-score.test.ts with every test passing; a re-run of that file and of the
whole suite came back clean, so it is unrelated to this change.

Still open

This makes the next migration correct. It does not repair the running instance,
which needs the account restored by hand. The demo is also serving 1.37.12 while
the current release is 1.37.24.

Refs #805

…ing one

The edge01 demo refresh copied `password_hash` straight from the source
account, and the README beside it asserted "demo login works". That only held
while the source account happened to use the password the project publishes.
The source is the operator's own instance, so the moment that password was
rotated the demo started rejecting the credentials the README hands to every
visitor, and nothing anywhere noticed. Someone eventually filed it as a bug
(#805) after being locked out of the shop window.

The load now hands the row an explicit password: the same Argon2id literal the
seed script writes, applied right after the copy, then read back and compared
byte for byte. A mismatch aborts the run rather than waiting for a stranger to
discover it at a login screen.

The statement goes in on psql's stdin. Interpolating it into the ssh command
string would let the remote shell expand the hash's `$argon2id`, `$v`, `$m`,
`$t` and `$p` segments to empty strings and store something no password can
ever match, which is the same outage wearing a different hat. A guard test
pins that too, alongside pinning the literal to the seed script's copy so the
two cannot drift apart again.
@MBombeck

Copy link
Copy Markdown
Owner Author

Note on the red Dependency Audit: it is not this branch.

The job blocks on one advisory, deepmerge-ts <8.0.0 (GHSA-ggr8-5vv4-36mx),
reached transitively through @prisma/client > prisma > @prisma/config. Of the
twelve findings it reports, only that one is at a blocking severity.

This branch adds no dependency: the commit is a shell script, its README, and a
test file, with no package.json or lockfile change. To check rather than
assume, I re-ran the same job on main at commit 0a20925, which passed on
16 August. Against today's advisory database it now fails too. So the trunk is
red from registry drift and every branch inherits it.

Tracked separately. Bundling a dependency change into a demo-credentials fix
would only make both harder to reason about.

@MBombeck
MBombeck merged commit 5d3d512 into main Aug 21, 2026
23 checks passed
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