T10.9: rollback-aware deploy runbook for the Okta cutover

New DEPLOY-runbook-2026-09-03.md, separate from the 2026-08-04 runbook.
Names the five new OKTA_* env vars, treats the pre-deploy backup as the
only way back once 1d60a608bb51 (drop_local_password) commits since its
downgrade() restores the column but not the data, and splits Rollback
into the fixable case (Okta app integration misconfigured, fix and
redeploy api, no data at risk) versus the severe case (abandoning Okta
for local-password code, which only a destructive backup restore can
reach). States D16's no-break-glass posture plainly.

D17 records the decision and why: staged-deploy-sequence docs and
backlog-only were both considered and declined in favor of the runbook.

Logged to backlog.md rather than fixed here: okta_auth.describe() has
no caller (BL-028), users.failed_attempts/locked_until are vestigial
(BL-029), DEPLOY-login-portal.md is fully stale (BL-030).
This commit is contained in:
2026-09-03 14:25:18 -07:00
parent d7d1e93dd8
commit d6eae0d846
4 changed files with 471 additions and 0 deletions

View File

@@ -594,3 +594,49 @@ deliberately deferred.
and pinned; the systematic guard is its own small task, not a hotfix rider.
- **Suggested wave or follow-up:** next housekeeping pass, paired with BL-026
(both are "deploys should be boring" work).
### BL-028 — `okta_auth.describe()` is never called
- **Found during:** T10.9 (writing the deploy runbook's live-verification step)
- **Where:** `server/okta_auth.py` (`describe()`), `server/app.py` (no caller anywhere)
- **What:** `describe()` exists specifically to shout `"*** FAKE OKTA PROVIDER
ACTIVE..."` or report missing config at a glance, and both
`server/.env.example` and `server/README.md` tell an operator to "check the
startup log line" for it. Nothing prints it. `app.py` never imports or calls
`describe()` at process start, so that log line does not exist and an operator
following the docs will not find it.
- **Why not now:** a runbook is documentation, not server code; wiring a
startup log call is a real (if small) change to `app.py` and wants its own
diff and its own verification, not a rider on T10.9.
- **Suggested wave or follow-up:** next housekeeping pass. One call
(`logger.info(okta_auth.describe())` near startup) plus updating
`DEPLOY-runbook-2026-09-03.md` Step 4 to check the log line once it exists.
### BL-029 — `users.failed_attempts` / `users.locked_until` are vestigial
- **Found during:** T10.6
- **Where:** `server/models.py` (`User.failed_attempts`, `User.locked_until`)
- **What:** both columns exist to support local-password lockout, which T10.4
removed. They are still reset to `0`/`None` on every Okta sign-in but nothing
increments them anymore — dead columns, not a bug, but schema drift from the
D15 cutover.
- **Why not now:** T10.6 is documentation scope; dropping columns is a migration
and belongs with the rest of the local-password cleanup, not folded into a
docs task.
- **Suggested wave or follow-up:** next housekeeping pass, alongside any other
post-cutover schema tidy-up.
### BL-030 — `DEPLOY-login-portal.md` is fully stale
- **Found during:** T10.9
- **Where:** `DEPLOY-login-portal.md` (repo root)
- **What:** the original username/password login rollout doc. References
`bcrypt`, `create-admin --password`, `AUTH_SECRET_KEY` as the only secret,
and a login form — none of which describe the app since T10.4/T10.5. Someone
handed this to IT today would be told to do things that no longer work.
- **Why not now:** no task currently owns deploy-doc cleanup as a category;
deleting or archiving a doc is a product/records call (`CLAUDE.md`'s "removed
fields are hidden, not deleted" spirit likely applies to docs too, but that is
worth confirming rather than assuming).
- **Suggested wave or follow-up:** next housekeeping pass — needs Nick on
whether to delete, archive, or rewrite it as historical record.