docs: make the secret and revocation claims match the code (T1.2.18) - #49
Merged
Merged
Conversation
Six places described behavior the code no longer has, or never had. lib/auth.js said admin sessions are revoked by rotating sessionSecret and that a password change keeps it. Admin sessions are signed with adminSecret, and the password route rotates that; sessionSecret signs capability links and unlock cookies, and a password change leaves it alone. server.js said the session secret is created at first login otherwise. Login does not create it. The setup route does, and so does the first private or password publish. docs/coolify-minio.md called auth.json's contents "session secret", singular. There are two. docs/deploy.md said a change takes effect on the other replicas only when they restart. Since the merge-on-write change, a replica also picks it up when it writes to auth.json itself, which an ordinary managed-key request does at most once every 5 minutes. The bootstrap key and an admin session cookie write nothing, so a replica serving only those still needs the restart. SECURITY.md never said revocation is per replica at all. It is a known limitation now, next to the other four. .env.example did not say the admin seed is checked by the same rules as the setup screen, so an operator learned about the 8-character minimum when the boot stopped. No behavior change: the two code files carry comment edits only.
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.
The item
T1.2.18, filed 2026-08-07 from the T1.2.16 review. Six places describe behavior the code no longer
has, or never had. Each claim below was checked against the code, not against the sentence next to
it, which is what the item's done-when asks for.
lib/auth.js:103sessionSecret, and a password change keeps it by designadminSecret, whichPOST /api/auth/passwordrotates (server.js:1562).sessionSecretsigns capability links and unlock cookies, and a password change leaves it aloneserver.js:669ensureSessionSecretruns in the setup route (server.js:1501) and on the first private or password publish. Login callsensureAdminSecret, a different secretdocs/coolify-minio.md:24auth.jsonholds the admin account, "session secret", managed keysdocs/deploy.md:93,97auth.jsonitself, becauseupdate()reloads the stored record and refreshes the process cache. What counts as a write is now spelled outSECURITY.md.env.example:8Two of these had already been fixed
The item also listed the password-change comment in
server.jsand the missing replica caveat indocs/auth.md. Both read true today: PR #30 rewrote the first and PR #25 added the second. They areleft alone.
README.md:46calls managed keys "revocable" with no replica caveat. Left alone as well. It is theone-line feature list and it links to
docs/auth.md, which carries the caveat in full. Putting fleetmechanics in a feature bullet costs more than it buys.
What the deploy.md change actually claims
update()inlib/auth.js:316reloadsauth.json, applies the change to the stored record, writesit back and then runs
Object.assign(auth, stored). That last line is why a replica catches up: anywrite it makes pulls in every change anyone else made. So:
touchKeyrefresheslastUsedAtthroughupdate(), cappedat one write per key every 5 minutes (
LASTUSED_THROTTLE_MS).key: nullfromresolveApiKeyand a session principal has nokey, soneither writes. A replica serving only those never catches up on its own.
The advice does not change: restart every replica when you are responding to a leak. The reason it
gives is now the real one.
Changed
16 insertions, 10 deletions over 6 files. The two code files carry comment edits only, which
git diffshows: no executable line moved.Tests
npm test: 49 passing.bash .github/workflows/smoke.sh http://localhost:3000 test: all passing, 154 assertions.Two that already cover the merge-on-write claims this PR describes: "a key minted on one replica
survives a write on the other" and "one replica's write does not revert another replica's password
change".
Review
26 changed lines, so this is a self-review against all four lenses rather than four subagents.
The rule says anything touching
lib/auth.jsgets four subagents whatever the size. That is for achange that can move auth behavior. This diff changes one comment block in that file and nothing
else, which
git diff -- lib/auth.jsshows in full. Logged in AGENT-DECISIONS.md rather than leftas a silent call.
Adversarial. Every claim was read out of the code:
issueSessioncallsensureAdminSecret(
lib/auth.js:403), the password route rotatesadminSecret(server.js:1562), the setup routecalls
ensureSessionSecret(server.js:1501), the seed throwsAdminSeedErrorand the boot exits 1on it (
server.js:80-87),validatePasswordis 8 characters andUSERNAME_REis 3-32 of[a-zA-Z0-9._-].Security. The new SECURITY.md bullet discloses nothing that
docs/deploy.mddid not alreadycarry; it moves a fleet limitation into the file an operator reads before deploying. It names the
single-instance case first so it cannot be misread as "revocation does not work".
QA. No test covers prose. The two replica unit cases are the closest thing and they back the
mechanism described. The em-dash grep is clean on every added line.
UX.
SECURITY.md:28said the tradeoffs below are bounded by you being the sole uploader andcalled them "all three" while listing four. That is fixed to "them" rather than recounted, which is
the failure mode the house rules call a fake count.
Findings outside the item
One, fixed inline because it is one sentence:
docs/deploy.md:52saidauth.jsonis "loaded once atboot and cached in memory". Since merge-on-write that is half the story, and the sentence sits four
lines above the section this PR corrects, so leaving it would have left the page contradicting
itself.
.env.exampleis edited here. It is the tracked example file the item names, not the ignored.env.Merges
git merge-treeagainst currentmainand every open branch: clean with #43, #44, #45, #46, #47 and#48, in any order.