Repository navigation
Complete authentication system across Go backend, React frontend, and PostgreSQL.
Backend (dashboard_backend/)
- JWT access tokens (8h) + refresh tokens (30d) via
SPREADARA_JWT_SECRET userstable with invite-based activation flow (no self-registration)requireAuthmiddleware with role-based access: admin / trader / viewer- Role-restricted endpoints: config, calibration run, backtest run → admin only; all others → any authenticated user;
/api/v5/statusand/api/snapshotremain public - Auth routes:
POST /api/auth/login,/refresh,/logout,/accept-invite - Admin routes:
GET/POST /api/admin/users,DELETE /api/admin/users/:id - Startup seeds first admin from
SPREADARA_ADMIN_EMAILif no users exist; logs invite URL to stdout - Invite emails via Resend REST API (
SPREADARA_RESEND_API_KEY,SPREADARA_APP_URL) - Auth is opt-in: when
SPREADARA_JWT_SECRETis unset all routes pass through (dev/internal mode) - 9 new tests: login success/fail, user enumeration resistance, missing/valid/expired token, admin-only 403, invite flow, refresh token
Frontend (dashboard/)
auth.ts: in-memory token store (not localStorage),setTokens,refreshTokens,logoutLogin.tsx: split layout — animated live candlestick SVG on left, sign-in form on rightAcceptInvite.tsx: password setup with strength validation (min 8, uppercase, digit)AdminUsers.tsx: user table with invite modal and delete; admin-only sidebar entry- All API calls now send
Authorization: Bearerheader with automatic 401 → refresh → retry - Protected routes redirect to
/loginwhen unauthenticated;/admin/usersrequires admin role - Sidebar gains Users link (admin only), Sign out button, and current user email display
New environment variables
SPREADARA_JWT_SECRET=<random 32+ char string>
SPREADARA_RESEND_API_KEY=<from resend.com>
SPREADARA_APP_URL=https://app.spreadara.com
SPREADARA_ADMIN_EMAIL=admin@spreadara.com