feat(installer): confirm email + password, and a credentials backup file - #3
Merged
Merged
Conversation
Two things a user cannot recover from after this screen, because the installer deletes itself. Confirm email + confirm password on the admin step A typo in the ONE email that owns the install is unrecoverable from here: the password reset goes to the address that was typed wrong. Catching it costs a re-type; missing it costs the account. Validated BEFORE the download and the migration run, so nobody waits through the slow work to be told they mistyped their own address. Email comparison is case-insensitive — people retype with different capitalisation constantly and that is not a typo. Password comparison is exact, via hash_equals. Password STRENGTH stays Tiger's rule in createOwner, so there is one authority for it rather than two that can disagree. A credentials backup file The DB password afterwards lives only in local.ini above the docroot, and the agent key is shown exactly once. A user who closes this tab has lost them. The finish screen now offers one file with the admin login, database details, paths and the agent key. Served as a `data:` URI on a plain <a download>. That means no JavaScript, and — the reason it is built this way — NOTHING SENSITIVE IS EVER WRITTEN TO THE SERVER. Writing this file into the docroot would publish every secret in the install to anyone who guessed the filename, and would outlive the installer that created it. A file that never exists on disk cannot be fetched and cannot be left behind. Verified the URI round-trips, is attribute-safe, and that the decoded file carries what it claims. 29 new assertions (83 total). Mutation-tested: removing either confirmation check, making the email match case-sensitive, and dropping the db password or the agent key from the file each fail by name. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L8p9pLJ3DFstG3xZuh2QgZ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two things a user can't recover from after the finish screen, because the installer deletes itself.
Confirm email + confirm password
A typo in the one email address that owns the install is unrecoverable from that screen — the password
reset goes to the address that was typed wrong. Catching it costs a re-type; missing it costs the
account.
Validated before the download and migration run, so nobody waits through the slow work to be told
they mistyped their own address.
that isn't a typo.
hash_equals.createOwner— one authority, not two that can disagree.A credentials backup file
Afterwards the DB password lives only in
local.iniabove the docroot, and the agent key is shownexactly once. Close the tab and they're gone. The finish screen now offers one file with the admin
login, database details, paths, and the agent key.
Served as a
data:URI on a plain<a download>. No JavaScript — and, the actual reason it's builtthis way, nothing sensitive is ever written to the server. Writing this file into the docroot would
publish every secret in the install to anyone who guessed the filename, and it would outlive the
installer that created it. A file that never exists on disk can't be fetched and can't be left behind.
Verified the URI round-trips, is attribute-safe, and that the decoded file carries what it claims.
Tested
29 new assertions (83 total, CI green on PHP 8.1 and 8.5). Mutation-tested: removing either
confirmation check, making the email match case-sensitive, and dropping the DB password or the agent
key from the file each fail by name.
🤖 Generated with Claude Code
https://claude.ai/code/session_01L8p9pLJ3DFstG3xZuh2QgZ