T10.6 D13 - strip the password UI; "Forgot password?" goes to Okta

login.html/login.js: the two reset views are gone along with the reset-token
handling, and the sign-in form now says which password to type - "your Windows
password, the same one you use to sign in to your computer" - using the .hint
class the page already had, so no new CSS and no new literal.

"Forgot password?" is KEPT and points at https://primecontrols.okta.com/. An
earlier draft of this task deleted the link and I proposed a plain "contact IT"
sentence instead; Okta is the better answer, and with no app password and no
break-glass it is the only recovery path that exists.

Three details that would each have broken it:

- The old click handler on #forgot-link called preventDefault() to swap views.
  Left in place it would have silently swallowed the navigation, so the link
  would look right and do nothing. There is now deliberately no handler, and
  login.js says why so nobody adds one back.
- target="_blank" without rel="noopener noreferrer" hands the opened page a
  window.opener handle back to the login page.
- Worth recording since it was checked rather than assumed: the CSP allows
  this. form-action 'self' governs form submission, not link navigation, and no
  navigate-to directive is set - so a plain <a href> off-origin is fine and the
  nginx config needs no change.

login.js also handles 503 distinctly now. T10.2 made that mean "the directory
is unreachable or misconfigured", which is our fault - showing "invalid
password" would send people hunting for a password they no longer have while a
deploy is broken.

Also removed, because T10.3 deleted the endpoints behind them and leaving them
would have produced visible 404s rather than dead-but-harmless markup:

  auth-guard.js   the whole change-password dialog (POST /api/auth/password)
  wp-sidenav.js   the "Password / Change your password" menu entry that opened it
  users.js        the per-row "Reset password" action
  users.js        the password field in the create-account form - NewUserIn no
  users.html      longer accepts one, so the form was posting a rejected field

The self-row placeholder button pointed at a top-bar Password link that no
longer exists; it is now a plain "you" marker.

Verified: node --check passes on all four touched JS files; the only password
references left in html/ are the sign-in form and the SMTP config in admin.js,
which is unrelated and stays.

Logged BL-027 rather than acted on: the Okta URL is the first sign of an Okta
tenant on this estate, which means an OIDC flow is available in principle and
would remove the domain-lockout hazard that forced AUTH_MAX_ATTEMPTS to 2. D13
was decided and reaffirmed and T10.1-T10.4 are built, so swapping the mechanism
mid-wave is the reordering CLAUDE.md forbids. Recording is not reopening.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-21 15:30:16 -05:00
parent 8cfb4c1008
commit ab7bce9f5b
8 changed files with 66 additions and 257 deletions

View File

@@ -234,8 +234,21 @@ to read the group name off the login page.
two of them now point at endpoints that no longer exist. `auth-guard.js` has a
change-password dialog, and the user-admin UI has a "reset password" action per row.
**Do:** Remove the `#view-forgot` and `#view-reset` sections, the `#forgot-link`, and the
reset-token handling in `login.js`. Remove the change-password dialog from `auth-guard.js`
**Decided Aug 21: "Forgot password?" is KEPT and repointed at
`https://primecontrols.okta.com/`.** An earlier draft of this task removed the link, and a
plain sentence saying "contact IT" was proposed instead. Okta is the better answer — it is a
real self-service path, and with no app password and no break-glass it is the only recovery
route that exists. Note this is the first sign of an Okta tenancy on this estate; see the
new backlog entry.
Mechanics that matter: it is a plain `<a href>`, not a form post, so the `form-action 'self'`
in the CSP does not apply and no `navigate-to` directive is set — off-origin link navigation
is allowed as-is. `target="_blank"` needs `rel="noopener noreferrer"`, and there must be NO
click handler on `#forgot-link`: the old one called `preventDefault()` to swap views, and
leaving it would silently swallow the navigation.
**Do:** Remove the `#view-forgot` and `#view-reset` sections and the reset-token handling in
`login.js`, and repoint `#forgot-link` as above. Remove the change-password dialog from `auth-guard.js`
(`backlog.md:180` refers to it) and the per-row password reset from the users UI. Keep the
sign-in form, and relabel the password field's hint to say it is the Windows/domain password
— people need to know which password to type.
@@ -244,7 +257,10 @@ Keep the role-granting controls exactly as they are. That is criterion 4.
**Done when:**
- [ ] `grep -rn "forgot\|reset-password\|new-password" html/` returns nothing but unrelated matches
- [ ] `grep -rn "forgot\|reset-password\|new-password" html/` returns nothing but prose
- [ ] "Forgot password?" opens `https://primecontrols.okta.com/` in a new tab
- [ ] `#forgot-link` has NO click handler (a `preventDefault()` would swallow the navigation)
- [ ] a 503 from the login endpoint says sign-in is unavailable, not that the password is wrong
- [ ] the sign-in form still submits, and a failure still announces through `role="alert"` (`login.html` already does this correctly — do not regress it)
- [ ] the password field says which password to enter
- [ ] no dead `<a href="#">` or handler remains for a removed view