Skip to content

v0.4.5 — settings, sessions, and event admin

Pre-release
Pre-release

Choose a tag to compare

@solarssk solarssk released this 24 Jun 16:27
v0.4.5
9ed5ed9

[0.4.5] - 2026-06-24

Added

  • MFA enrollment split into three steps: TOTP QR/setup-key confirm → dedicated backup-codes page → full session; new backup_codes_required session stage and DB migration
  • POST /mfa/enroll/backup-codes route and handleTotpBackupCodesComplete API endpoint; session promoted to FULL only after backup-codes acknowledgment
  • 6-digit centered OTP input field with auto-focus, paste support, keyboard navigation, and backup-recovery-code toggle
  • GET / smart redirect: authenticated users land on /admin (or /operator), unauthenticated users on /login
  • Admitto favicon set: SVG, 32 × 32 PNG, Apple touch icon, and ICO fallback served from /favicon.*
  • SSO button label per identity provider (login_button_label); default falls back to "Continue with SSO"
  • Admin sidebar: checkmark brand mark (correct admitto-mark.svg), All events + Settings items always pinned to footer
  • Settings sub-navigation: horizontal tab bar (General · Identity providers · Cloudflare Access) rendered on both SPA and SSR settings pages
  • Identity-provider and Cloudflare Access admin pages rendered with full sidebar shell matching the SPA layout (sticky layout, design-system CSS tokens)
  • Event card: date icon, location pin icon, attendee count stat with user icon; hover lift effect
  • Event overview landing page at /admin/events/:id/overview with quick stats and navigation links to live admin sections
  • Shared admin shell (StaffShell): sidebar with independent scroll, slim topbar, optional settings subnav, and mobile drawer navigation
  • Staff topbar: mailer status indicator (configured dot + provider label), role badge (SA/AD/OP), icon-only sign out
  • Sidebar footer: Users & roles link for org admins and superadmins (page ships in a follow-up PR)
  • Dev-only demo bar (import.meta.env.DEV) to trigger sample toasts from the admin shell
  • Admin check-in v2: split layout with scan bar, connection banner, stats/progress sidebar, color-dot recent scans, and fullscreen camera overlay with QR viewfinder
  • Create event UI: POST /api/admin/events, New event modal (title, slug, date, location), redirect to attendees after create
  • Events picker visual polish: active status badge, responsive 2/3-column grid, empty state with Create event CTA
  • Attendees v2: rsvp_status migration, wider list table (STATUS/MAIL/CHECK-IN/actions), manual POST /attendees, full attendee detail page with activity log, Add attendee modal
  • Event settings page at /admin/events/:id/settings: edit title, date, location, capacity; superadmin PII CSV export; archive/unarchive from danger zone; capacity field on Event

Changed

  • GET /api/admin/me includes mailer_status (provider presence only — no credentials); /api/auth/me unchanged for operator sessions
  • Toast stack position: top-right below the staff topbar (--topbar-h) instead of bottom-right
  • Admin check-in: keyboard wedge inputMode="none", auto-submit for long tokens, Esc to clear result state
  • README: local dev onboarding (Run locally), Node engines alignment, infra/ vs deploy/ distinction; new apps/admin/README.md
  • Admin Vite dev proxy: forward /mfa to @admitto/web so MFA enrollment works on :5173
  • Login page <title> fixed to "Admitto"; added application-name, og:site_name, and description meta tags for password-manager naming
  • MFA page heading changed from <h1> to <p class="auth-page-action"> to preserve correct document semantics; Admitto brand uses <h1>
  • CSRF fix: Nginx forwards $http_host (with port) in Host and X-Forwarded-Host headers so 127.0.0.1:8080 logins no longer return 403
  • Superadmin instance settings at /admin/settings with branding panel — live theme preview, anti-lockout guards, and links to OIDC / Cloudflare Access admin pages (#96)
  • Settings → Mail transport panel: configure provider, masked secrets, env-locked fields, and test send (#99)
  • Settings → Sessions and Security panels: list/revoke staff sessions, bulk operator revoke, session TTL and MFA policy; GET/PATCH /api/admin/system-settings (#112)
  • Event archiving: Event.archived_at hides completed events from default lists; superadmin archive/unarchive; archived events read-only on admin mutating APIs; Active/Archived tabs; check-in stays available (ADR 0022) (#116)
  • Admin shell layout: single main scroll region (subnav + page content), 100dvh viewport, Overview in live event sidebar segments; events picker opens archived tab when no active events remain; active event cards are fully clickable
  • MFA enrollment and verify: step progress indicator (Step X of 3), no OTP autofocus on the QR step, auto-submit after six digits, and submit loading state on auth forms
  • Settings horizontal subnav uses consistent styling across SPA and SSR; Identity providers and Cloudflare Access open via full-page navigation to SSR admin pages
  • Admin sidebar chrome trimmed: redundant context labels and duplicate Instance settings header action removed
  • @admitto/ui design system: Spinner, EmptyState, Skeleton, and ToastProvider / useToast (#120)
  • Admin app root wrapped with ToastProvider; recoverable ErrorBoundary on render errors (#97, #120)
  • Admin UX micro-fixes: import column reference table and CSV template download; delivery log purpose filter; compose dirty-state guard; attendee drawer discard confirmation; check-in stats admitted/total (#121)
  • POST /mfa/enroll/download-codes — backup codes as .txt during enrollment (#117)
  • Check-in: NoteModal replaces window.prompt for attendee notes (#114)
  • Runtime upgraded to Node 24 LTS; React 18 → 19 across admin and web (#111, #110)
  • Login, MFA, and superadmin identity-provider HTML pages aligned with Admitto design tokens (#117)
  • OIDC group mapping role picker uses a select; provider list supports inline enable/disable (#117)
  • Cloudflare Access admin form shows status badge, fall-through explanation, and enable warning (#117)
  • Requirements and Communication panels use ConfirmDialog instead of native window.confirm (#97)

Fixed

  • Guest ticket page now prints correctly (white background, no wallet buttons, no shadows)
  • Export: sanitize dynamic attribute column headers against formula injection (#97)
  • Local dev: login/MFA CSRF when Origin/Referer absent (Safari); admin SPA dist path after npm run build -w @admitto/admin (#115)
  • Admin page shell document title uses event name prefix without regressing the visible h1 (#118)
  • SSO failure on /login shows a dedicated fallback banner; removed placeholder “SSO coming soon” when no IdP is configured (#117)
  • Check-in card coloured left border per scan status (#114)
  • Login page title and heading: “Sign in to Admitto” (#114)
  • Sidebar Overview section shows “Soon” until built (v1.0) (#114)
  • Settings subnav active tab uses path prefix matching instead of exact pathname equality
  • Sidebar “Soon” badges render with correct styling (.nav-item--soon, .nav-item__badge)
  • Global link hover underline no longer appears on sidebar brand, navigation items, or button-styled links (SPA and SSR settings shell)
  • OIDC admin form: URL fields use type="url"; group→role mapping rows can be added/removed; scope type select; SSO button live preview on provider form; failed save re-renders submitted mapping drafts
  • Cloudflare Access settings: clearer operator copy and field hints; test action labeled “Test connection”
  • Events picker: search by title/location; content width capped at 1100px; grid capped at three columns on wide screens
  • Check-in camera: removed fullscreen toggle (browser instability); debounce repeated ZXing decodes; extract ticket token from QR URLs with trailing slash or query (packages/tickets)
  • Check-in invalid/revoked scans show dedicated feedback card instead of silent failure
  • Requirements: @admitto/ui Switch missing thumb restored; item table uses name + auto-generated key; drawer layout cleanup
  • Event picker cards: removed hover lift/underline noise
  • Vercel Git deploys disabled via root vercel.json (self-hosted Docker only)

Security

  • Branding font_family_name allowlist on save and ticket-page render (blocks CSS/HTML injection via custom fonts) (#96)
  • deploy/validate-env.sh pre-flight for deploy/.env; production boot fails fast when REDIS_URL is missing, unauthenticated, or ENCRYPTION_KEY is invalid
  • PENtest hardening: structured audit events for rate limits, MFA, OIDC login, logout, admin 403, and settings changes — ISO ts on each event (#123)
  • Production BASE_URL must use https:// (except localhost / 127.0.0.1 smoke) (#123)
  • OIDC ID token verification restricts JWT algorithms to RS/ES/PS family (no none) (#123)
  • Deploy Redis requires REDIS_PASSWORD; compose wires authenticated REDIS_URL (#123)
  • Nginx proxy baseline security headers (HSTS, nosniff, frame deny); Docker bridge gateway for RealIP behind NPM (#123)
  • /healthz and /readyz responses include baseline security headers (#123)
  • GitHub Releases for v0.x.y are pre-release until v1.0.0; publish-container sets the flag automatically (#123)
  • PENtest follow-up: rate limits on MFA enroll, /healthz, admin import/template preview, and OIDC provider discover/test; OIDC outbound fetch resolves DNS before connect; malformed X-Forwarded-For falls back to socket IP (no shared unknown bucket)
  • docs/SECURITY-CONTROLS.md: rate-limit matrix, TRUST_PROXY trust model, SSRF/DNS-rebind guards, PEN retest checklist for operators

Deploy

  • Container image: ghcr.io/solarssk/admitto:0.4.5 (rolling :0.4)
  • Migrations apply automatically on container start (with pre-migration backup when pending). No manual migrate deploy.

Full changelog