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 ae820a5db6 feat: GET /enroll/csr/schema field map (mint still 501)
Schema-only CSR contract for future live PKI; no fake crypto.
2026-10-13 23:08:58 -04:00
docs feat: GET /enroll/csr/schema field map (mint still 501) 2026-10-13 23:08:58 -04:00
public feat: enroll panel proxyHeadersSeen chips on login/app 2026-10-13 21:18:29 -04:00
src feat: GET /enroll/csr/schema field map (mint still 501) 2026-10-13 23:08:58 -04:00
test feat: GET /enroll/csr/schema field map (mint still 501) 2026-10-13 23:08:58 -04:00
.gitignore feat: 2026 brand staff IAM — TOTP gate, enroll/status, UI kit 2026-10-13 21:11:59 -04:00
ENROLL.md feat: GET /enroll/csr/schema field map (mint still 501) 2026-10-13 23:08:58 -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 feat: GET /enroll/csr/schema field map (mint still 501) 2026-10-13 23:08:58 -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 docs: ENROLL.md refresh and TOTP.md for staff 2FA and device-cert status 2026-10-13 21:46:31 -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
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): GET /enroll/status + GET /enroll/csr/schema (fields only); POST /enroll/csr → 501; proxy headers only — no fake PKI
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

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 only. GET /enroll/status returns updatedAt, state (not_enrolled | pending_proxy | enrolled | enforce_on), nextSteps[], proxyHeadersSeen (verify/verifyOk/dn/pem/any), and proxy probe. GET /enroll/csr/schema = future body fields only; POST /enroll/csr → 501. Enforce only with STAFF_MTLS_ENFORCE=1 and mtlsEnrolled: true. No device-cert mint — proxy headers only. 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, iam-admin, billing-admin, cs, sales, accounting, operator, viewer. Permissions are listed on /roles.

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 chips) — proxy/PKI only; no mint in this app

Contributing

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

License

UNLICENSED © George Lambert