From 5922dc704b8dccd4a9ad5315bcde9de404ca8052 Mon Sep 17 00:00:00 2001 From: George Lambert Date: Wed, 14 Oct 2026 04:34:25 -0400 Subject: [PATCH] docs: PR body for feature/staff-role-switcher Add docs/PR-staff-role-switcher.md covering role interface, TOTP/enroll, and links to ENROLL, TOTP, and PKI READY packs (PROD-CA cutover, AuthZ enroll design, CRL/OCSP deploy). Link from README Docs table. --- README.md | 1 + docs/PR-staff-role-switcher.md | 95 ++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 docs/PR-staff-role-switcher.md diff --git a/README.md b/README.md index 8f4763a..bf12b4d 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ Open `http://127.0.0.1:3028/login`. Persist store with `STAFF_IAM_PATH`. Login i | [TOTP.md](./TOTP.md) | Authenticator 2FA + **`STAFF_TOTP_REQUIRED`** enroll path; how login / app UI use flags | | [NATS.md](./NATS.md) | NATS notes (if used) | | [SUMMARY.md](./SUMMARY.md) | One-line service summary | +| [docs/PR-staff-role-switcher.md](./docs/PR-staff-role-switcher.md) | PR body for `feature/staff-role-switcher` (IAM + UI companion) | ## Seed lab users diff --git a/docs/PR-staff-role-switcher.md b/docs/PR-staff-role-switcher.md new file mode 100644 index 0000000..42def56 --- /dev/null +++ b/docs/PR-staff-role-switcher.md @@ -0,0 +1,95 @@ +# PR: feature/staff-role-switcher (verae-staff-iam) + +**Repo:** `verae-staff-iam` +**Branch:** `feature/staff-role-switcher` → `main` +**Forgejo:** https://git.georgelambert.org/marchon/verae-staff-iam +**Companion PR:** `verae-staff-ui` same branch (`docs/PR-staff-role-switcher.md`) + +Paste this body (or link this file) when opening the Forgejo pull request. + +## Summary + +Staff IAM gains an **active role interface** (`currentRole` on session), product **roles catalog** for edge dual-staff, first-login **mustChangePassword** + optional/required **TOTP**, and an honest **device-cert enroll** surface: default `POST /enroll/csr` → **501**, opt-in **LAB ONLY** mint via `LAB_CA_ENABLE=1` + `lab-test-ca.sh` (refused when `NODE_ENV=production`). Production CA mint is **not** shipped; ops kits are **READY packages** only. + +## Why + +- Multi-role staff need one signed-in session and a switchable interface (CS / sales / operator / …) without re-login. +- Edge dual-staff impersonate needs a public starter/ender/admin catalog and per-user roles lookup. +- Security gates (password change, TOTP, mTLS status) must be real in software while production PKI stays external. + +## What landed (vs `main`) + +### Role interface switcher +- Session store carries `currentRole`; `GET /me`, `GET /interfaces`, `POST /session/role` +- `GET /roles/catalog` → `{ roles: ["starter","ender","admin"] }` (public) +- `GET /users/:idOrUsername/roles` → roles-only (no secrets); unknown/inactive → 404 +- App UI: Interface dropdown when capabilities ≥ 2; People & roles for admins + +### First login + TOTP +- New accounts: `mustChangePassword=true`; doors gated `403 must_change_password` until `POST /password/change` +- Optional TOTP (`/2fa/setup`, `/2fa/enable`); `STAFF_TOTP_REQUIRED=1` forces enroll path +- `POST /2fa/skip` denied under required policy; `POST /admin/mark-must-change` for invite re-mark +- Login UI + My security / enroll-2fa / change-password pages (2026 brand kit) + +### Enroll / PKI (no production mint) +- `GET /enroll/status` — state, nextSteps, `csrSchemaUrl`, `csrPostStatus`, `labCa`, `proxyHeadersSeen` +- `GET /enroll/csr/schema` — fields-only (`mint: false`) +- `POST /enroll/csr` — PEM shape gate (**400** invalid); default **501** `not_implemented`; lab **201** + `X-Lab-CA: 1` only when lab ready and non-prod +- `scripts/lab-test-ca.sh` — `init` / `sign` / `crl` / `warn` (LAB ONLY) +- Audit `csr_attempt` without storing PEM + +### Docs +- Operator: [ENROLL.md](../ENROLL.md), [TOTP.md](../TOTP.md) +- Refuse matrix: [PRODUCTION-PKI-REFUSE.md](./PRODUCTION-PKI-REFUSE.md) +- Design: [TEST-CA-DESIGN.md](./TEST-CA-DESIGN.md), [CRL-OCSP-DESIGN.md](./CRL-OCSP-DESIGN.md), [PKI-MINT-BACKLOG.md](./PKI-MINT-BACKLOG.md) +- **PKI READY packs** (ops kits; no mint code): see below + +## Link: ENROLL · TOTP · PKI READY packs + +| Pack | Path | Role | +|------|------|------| +| **ENROLL** | [ENROLL.md](../ENROLL.md) | Device cert mTLS: status, CSR schema, default 501, lab 201 contract | +| **TOTP** | [TOTP.md](../TOTP.md) | Authenticator 2FA + `STAFF_TOTP_REQUIRED` enroll path | +| **PROD-CA cutover (READY)** | [PROD-CA-CUTOVER-RUNBOOK.md](./PROD-CA-CUTOVER-RUNBOOK.md) | Production CA mint/renew/revoke cutover (external CA; IAM does not become CA) | +| **AuthZ enroll (READY)** | [AUTHZ-ENROLL-DESIGN.md](./AUTHZ-ENROLL-DESIGN.md) | Design before dropping default 501 for a real AuthZ mint path | +| **CRL/OCSP deploy (READY)** | [CRL-OCSP-DEPLOY-CHECKLIST.md](./CRL-OCSP-DEPLOY-CHECKLIST.md) | Production CRL/OCSP proxy/CA deploy checklist | +| Refuse matrix | [PRODUCTION-PKI-REFUSE.md](./PRODUCTION-PKI-REFUSE.md) | Lab-only 201 vs production 501; prod never lab | +| Backlog | [PKI-MINT-BACKLOG.md](./PKI-MINT-BACKLOG.md) | What live production mint still requires | + +**Invariants held (do not merge if broken):** +- Default `POST /enroll/csr` → **501** +- `LAB_CA_ENABLE` default **off** +- `NODE_ENV=production` **refuses** lab mint even if flag set +- No PKCS#12 / private key return; no demo “real” staff cert from IAM + +## Test plan + +```sh +cd verae-staff-iam +npm install +npm test +# expect: 19/19 pass (health PKI/lab matrix, password-totp, roles/currentRole) +``` + +Manual smoke (optional lab): + +```sh +npm start # :3028 +# login admin / admin-dev-key → change-password if marked → Interface dropdown if multi-role +# GET /roles/catalog ; GET /enroll/status ; POST /enroll/csr → 501 +# LAB ONLY: ./scripts/lab-test-ca.sh init --dir ./lab-pki && LAB_CA_ENABLE=1 npm start +``` + +## Merge notes + +- Merge **with** `verae-staff-ui` `feature/staff-role-switcher` (shared chrome / review template brand). +- Edge dual-staff: set `STAFF_IAM_URL` and use catalog + `/users/:id/roles` (see edge `IMPERSONATE-IAM-ROLES.md` when present). +- Production PKI cutover is **human/ops** via READY packs — not enabled by this merge. +- Seed passwords are lab-only; rotate before any shared environment. + +## Out of scope (explicit) + +- Live production device-cert mint/renew/revoke inside staff-iam +- Dropping default 501 without a real Signer + AuthZ path +- Production CRL/OCSP served from this process +- Customer portal accounts / `xVerae-` token issue (staff_session only)