Internal staff users, roles, and permissions
  • JavaScript 67.4%
  • HTML 32.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
George Lambert 5922dc704b 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.
2026-10-14 04:34:25 -04:00
docs docs: PR body for feature/staff-role-switcher 2026-10-14 04:34:25 -04:00
public feat: enroll panel proxyHeadersSeen chips on login/app 2026-10-13 21:18:29 -04:00
scripts docs: CRL-OCSP-DESIGN + lab-test-ca crl subcommand 2026-10-14 01:16:53 -04:00
src feat: restore mustChangePassword first-login gate (pki software-complete) 2026-10-14 01:59:03 -04:00
test feat: restore mustChangePassword first-login gate (pki software-complete) 2026-10-14 01:59:03 -04:00
.gitignore feat: lab-test-ca.sh openssl lab CA (not wired to enroll) 2026-10-14 01:00:38 -04:00
ENROLL.md docs: PKI READY packages — prod CA cutover, AuthZ enroll, CRL/OCSP deploy 2026-10-14 04:20:24 -04:00
NATS.md Initial import of verae-staff-iam from zapier monorepo 2026-09-11 19:55:17 -04:00
package-lock.json feat: 2026 brand staff IAM — TOTP gate, enroll/status, UI kit 2026-10-13 21:11:59 -04:00
package.json feat: 2026 brand staff IAM — TOTP gate, enroll/status, UI kit 2026-10-13 21:11:59 -04:00
README.md docs: PR body for feature/staff-role-switcher 2026-10-14 04:34:25 -04:00
SUMMARY.md docs: ENROLL.md refresh and TOTP.md for staff 2FA and device-cert status 2026-10-13 21:46:31 -04:00
TOTP.md feat: GET /roles/catalog and /users/:id/roles for starter/ender/admin 2026-10-14 00:55:27 -04:00

verae-staff-iam

standard-readme compliant

Internal staff user management: named accounts, roles, permissions, audit.

Forgejo: https://git.georgelambert.org/marchon/verae-staff-iam

Port :3028. UI: sign-in, people, roles, audit. Source of truth for who may use CS, sales, and other back-office doors. Not customer portal accounts.

Table of Contents

Install

git clone ssh://git@git.georgelambert.org:2223/marchon/verae-staff-iam.git
cd verae-staff-iam
npm install

Usage

npm start
# optional gates:
# STAFF_TOTP_REQUIRED=1 npm start
# STAFF_MTLS_ENFORCE=1 npm start
# LAB ONLY (never production): init lab-pki then:
# ./scripts/lab-test-ca.sh init --dir ./lab-pki
# LAB_CA_ENABLE=1 npm start   # POST /enroll/csr → 201 + X-Lab-CA:1
npm test

Open http://127.0.0.1:3028/login. Persist store with STAFF_IAM_PATH. Login is rate-limited (8 failures / 10 minutes / IP+username). JSON APIs return 401/403; HTML doors 302 to /login.

Docs

Doc Topic
ENROLL.md Device cert (mTLS): status + CSR schema; default POST /enroll/csr → 501; opt-in LAB ONLY LAB_CA_ENABLE=1 → 201 + X-Lab-CA:1 (never production)
docs/TEST-CA-DESIGN.md Lab CA script + gated HTTP path; production mint still backlog
docs/PKI-MINT-BACKLOG.md Live production PKI checklist
docs/PROD-CA-CUTOVER-RUNBOOK.md READY: production CA mint/renew/revoke cutover (ops; no IAM CA)
docs/AUTHZ-ENROLL-DESIGN.md READY: AuthZ design before dropping default 501
docs/CRL-OCSP-DEPLOY-CHECKLIST.md READY: production CRL/OCSP proxy/CA deploy checklist
docs/PRODUCTION-PKI-REFUSE.md Refuse matrix: default 501 vs lab 201; prod never lab
docs/CRL-OCSP-DESIGN.md Revocation architecture (design only)
TOTP.md Authenticator 2FA + STAFF_TOTP_REQUIRED enroll path; how login / app UI use flags
NATS.md NATS notes (if used)
SUMMARY.md One-line service summary
docs/PR-staff-role-switcher.md PR body for feature/staff-role-switcher (IAM + UI companion)

Seed lab users

Username Password Roles
admin admin-dev-key owner (all)
cs cs-dev-key cs
sales sales-dev-key sales
accounting acct-dev-key accounting
operator fleet-dev-key operator

Override with IAM_OWNER_PASSWORD, IAM_CS_PASSWORD, etc.

Staff security gates

Gate Behavior
TOTP Optional per user by default. POST /2fa/setup → enable {code} while signed in. When totpEnabled, login returns 401 {error:"totp_required"} until a valid 6-digit totpCode is sent. UI: My security + setup QR/secret. Full ops: TOTP.md.
TOTP required STAFF_TOTP_REQUIRED=1 — seeds stay totpEnabled: false; after password login full app access is 403 {error:"totp_enrollment_required"} until /2fa/setup + /2fa/enable. /me, /2fa/*, /logout, /enroll/status still work. Disable refused while policy is on.
mTLS Copy + status + optional lab mint. GET /enroll/status returns state, nextSteps[], csrSchemaUrl, csrPostStatus (501 default; 201 when lab CA ready), labCa probe, proxyHeadersSeen, proxy. GET /enroll/csr/schema = fields only. Default POST /enroll/csr → 501. LAB ONLY: LAB_CA_ENABLE=1 + lab-pki → shell-out lab-test-ca.sh → 201 + X-Lab-CA: 1 (refused when NODE_ENV=production). Enforce with STAFF_MTLS_ENFORCE=1 and mtlsEnrolled: true. Production mint still external PKI. ENROLL.md.
Session Cookie / Bearer staff_session only. Never issues customer xVerae- tokens.

Wire other doors

STAFF_IAM_URL=http://127.0.0.1:3028
STAFF_AUTH=1   # department HTML still redirects if check fails

GET /check?permission=cs.credit — cookie or Authorization: Bearer. Cookie name remains staff_session. Multi-host: STAFF_COOKIE_DOMAIN.

Roles

owner, admin, iam-admin, billing-admin, cs, starter, ender, sales, accounting, operator, viewer. Full permission map: GET /roles.

Product catalog (edge dual-staff)

GET /roles/catalog
→ { "roles": ["starter", "ender", "admin"] }

Public, no auth. Edge (STAFF_IAM_URL) uses this catalog when dual-staff impersonate is on. Per-user roles:

GET /users/:usernameOrId/roles
→ { "id", "username", "active", "roles": ["ender", …] }

Roles-only (no secrets). Unknown/inactive → 404 { error, roles: [] }. Assign starter / ender / admin on people like any other role id.

Active role interface

Sessions carry capabilities (assigned roles) and currentRole (active interface).

  • GET /me / GET /interfaces — capabilities, currentRole, door URLs
  • POST /session/role { "role": "sales" } — switch active role (must be assigned); returns navigate url
  • Staff UIs show a top-right Interface dropdown when a user has two or more capabilities
  • Admins (owner / iam-admin) manage assignments under People & roles on this host

CORS allows credentialed calls from *.zapier.georgelambert.org so department doors can call IAM directly.

First login

New staff accounts are created with mustChangePassword=true (invite OTP is one-time). After /login the session cannot use staff doors (GET /check returns 403 must_change_password) until the user completes:

  1. GET /change-password → POST /password/change { currentPassword, newPassword }
  2. Optional GET /enroll-2fa → POST /2fa/setup → POST /2fa/enable { code }, or POST /2fa/skip (skip denied when STAFF_TOTP_REQUIRED)

When authenticator is enabled, subsequent logins require totpCode (or 401 totp_required).

Admin: POST /admin/mark-must-change { usernames?: string[] } (defaults to the seven owner invites) re-marks accounts so their invite OTP cannot skip the change-password step.

Account security UI

Signed-in Security tab covers:

  • Change password (/change-password)
  • Authenticator enrollment (/enroll-2fa, /2fa/*) — required when STAFF_TOTP_REQUIRED=1
  • Browser client certificate (mTLS) status from GET /enroll/status (state, nextSteps, updatedAt, proxyHeadersSeen, labCa chips) — default no mint; lab opt-in only via LAB_CA_ENABLE=1

Contributing

Questions: open an issue at https://git.georgelambert.org/marchon/verae-staff-iam/issues. Pull requests are accepted.

License

UNLICENSED © George Lambert