docs(security): the Local pathway after Amendment A: enrol before rotating, TOTP first, the generated-credential lock exception (BACKLOG #1133) - #1820
Merged
Conversation
added 3 commits
September 29, 2026 17:34
…ating, TOTP first, the generated-credential lock exception BACKLOG #1133 (ASVS 6.1.3, ninth re-read). The number is here and not in the subject because the claim gate refused the commit: #1133 is unclaimed and an isolated Builder cannot take a claim. The ninth 6.1.3 re-read held the cell at partial on eight sentences that engine PR 1770 left stale. Under the shipped require_mfa a covered local account with no TOTP enrols TOTP before it may rotate, a passkey cannot be its first factor, TOTP cannot be removed, and a generated credential arms no sign-in lock. SECURITY.md and CONFIGURATION.md now say so, with the Kerberos audit sentence, the file-secret warning and stale comments fixed. The console's enrol-first notice now offers TOTP alone to a covered account, matching the service's refusal of a first passkey. Guards: tests/test_docs_security_pathways.py, ninth-sweep pair.
BACKLOG #1133 (ASVS 6.1.3). Number kept out of the subject for the same claim-gate reason as the previous commit. The console password page redirects to enrolment rather than showing the refusal detail; the generated credential comes from an administrator's account creation and both resets, not the first-Administrator command; the factor reset is a third route to set_password under a lock; the TOTP-first rule is scoped to accounts the requirement covers; /ui/mfa's handling of an enrol-first session is disclosed. The guards gain the missing lockout arm, the uncovered disable_mfa branch and a sturdier item 1 needle.
BACKLOG #1133 (ASVS 6.1.3). Number kept out of the subject for the claim-gate reason given in the first commit of this branch. /ui/mfa's POST refuses any code for an account with no TOTP rather than checking one; a pending covered passkey-only session is sent to enrolment by the console password page, unaudited, while POST /me/password answers X-MFA-Required; the factor reset writes no password on a directory account; both administrator resets refuse a self-reset.
Collaborator
Author
|
QA line: code-review xhigh, two rounds. Round 1: 11 findings, 9 applied, 1 partly, 1 declined (settings.py env-only policy comments). Round 2: 4 findings (1 wrong /ui/mfa sentence, 1 narrow console-vs-JSON contradiction, 2 nits), all applied as doc corrections; the _factor_first code reorder declined as out of scope and listed as a follow-up. The round-2 fix commit 43849ea is unreviewed and small. Guard asserts red on main and per-item red on single reverts. Local: ruff and mypy clean; 430 passed on the 8 targeted files after round 2. |
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.
BACKLOG #1133 (ASVS 6.1.3). Docs, comments, guard tests, and one console notice text fix.
The ninth vault re-read of 6.1.3 (vault PR 2091) held the cell on 8 sentences that engine PR 1770 (ADR 0197 Amendment A wave 1) made false. Under the shipped
require_mfa, a covered local account with no TOTP must enrol TOTP before it may change its password, and its first factor must be TOTP. A generated credential arms no sign-in lock, and a combined sign-in owes nothing more.Fixed
_ENROL_FIRST_ROUTESand the order prove, enrol, rotate.require_mfarow.auth/service.py,api/auth_routes.pyand the web console./ui/account?m=enroll_firstno longer offers a passkey where the code refuses one. It shows exactly whenmust_enrol_before_rotatingis true. The test is red on main and green here. A line was added under Unreleased in the console package CHANGELOG.Guard tests (
tests/test_docs_security_pathways.py)lockout_armsarms, the_login_localcombined assignment, and on a real store thatchange_passwordand passkey registration refuse a covered no-factor account whiledisable_mfarefuses to remove covered TOTP.Follow-ups for the ledger (code, not in this PR)
POST /ui/mfa(routes/core.pyui_mfa_submit) should redirect a must-change enrol-first session instead of charging a ceremony attempt.routes/account.py_factor_first: for a covered, passkey-only pending session, the console answers "enrol first" (303, unaudited) where the JSON plane answersX-MFA-Required(403, audited). A reorder would make them agree. The docs now state the difference.QA line: two xhigh review rounds.
_factor_firstcode reorder was declined as out of scope and is listed above.Local:
-n 8, all in untouched files and all passing alone.