T10.7 - close four more done-when boxes offline; token_version was mis-specified

I had said all six remaining boxes needed the live environment. Four did not,
and saying so was lazy scoping. ldap_auth_check now covers them (32/32):

  a just-provisioned account appears in GET /api/auth/users, the request the
  Admin console makes - without which nobody could grant a JIT account access

  granting admin through POST /api/auth/users/{id}/role, the request users.js
  sends, with the role verified to have actually changed. D13 criterion 4 was
  until now only asserted for role PRESERVATION, never for role GRANTING.

  no AD error-49 sub-code appears in any response body, while _err49 does parse
  one out of a real AD message - the log gets the detail, the caller does not

  token_version invalidates a cookie already issued, and leaves other sessions
  alone

That last box was wrong as written. It asked to exercise token_version "by a
role change", and nothing in app.py bumps it on a role change - or on a
deactivation. Neither needs to: get_current_user re-reads the account from the
database every request, so both take effect on the next request regardless.
T10.3's note that "role changes and deactivation should bump it" described an
intention rather than the code, and I repeated it without checking.

What token_version actually is now: a mechanism whose only trigger is the bump
manage_users makes on disable, which is belt-and-braces since is_active already
refuses the request. It works, and it is tested - but nothing much triggers it.
Logged as BL-030 rather than resolved here, because whether to wire it to
something (a "sign out everywhere" control is the usual shape) or remove it is
a session-handling design question, not an auth-wave bug.

Two boxes remain open, and both genuinely need your environment: member_of
against a real NESTED group, and the in-container openssl certificate check.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-24 09:51:58 -05:00
parent 24fff382c8
commit eecd724e02
3 changed files with 128 additions and 5 deletions

View File

@@ -623,3 +623,25 @@ deliberately deferred.
- **Why not now:** drive-by fixes to the token system are what `CLAUDE.md` forbids, and
this one needs the C4 exception interpreted rather than guessed.
- **Suggested wave or follow-up:** next housekeeping pass, with `C4` re-read first.
### BL-030 — `token_version` is now near-vestigial; decide whether it earns its place
- **Found during:** `T10.7` (D13), closing the done-when that assumed a role change bumps it
- **Where:** `server/models.py` (`User.token_version`), `server/auth.py` (`create_token`,
`get_current_user`), `server/manage_users.py` (`_set_active`)
- **What:** `token_version` existed to invalidate live sessions when a password changed.
D13 removed passwords, and **nothing in `app.py` bumps it any more** — not
`set_user_role`, not `set_user_active`. Nor do they need to: `get_current_user` loads
the account from the database on every request, so a role change or a deactivation
takes effect on the next request regardless. `T10.3`'s note that "role changes and
deactivation should bump it" describes an intention, not the code.
- **Its one remaining trigger** is the bump added to `manage_users._set_active` in
`T10.9`, which is belt-and-braces rather than load-bearing — `is_active` alone already
refuses the request.
- **The question:** is there still a case for invalidating a live cookie *without* also
disabling the account? If yes, wire it to something (a "sign out everywhere" control is
the usual shape) and say so. If no, the column, the claim, and the check are three
places carrying a mechanism nothing triggers.
- **Why not now:** it is a design question about session handling, not an auth-wave bug,
and the mechanism works correctly — it is exercised in `ldap_auth_check`.
- **Suggested wave or follow-up:** next housekeeping pass.