Commit Graph

6 Commits

Author SHA1 Message Date
Vantz Stockwell
3cb714a792 fix: Resolve 500/404 cascade — JWT tenant context, wipe routes, changelog stub
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
Root cause: super_admin JWT returned early with no license_id, causing
@CurrentTenant() to pass undefined to every tenant-scoped service query.

- jwt.strategy: Move license lookup before super_admin early return so
  admins who own licenses get their license_id in the JWT payload
- CurrentTenant decorator: Throw 401 with clear message when license_id
  is undefined instead of letting undefined cascade into TypeORM queries
- Wipe store: Fix 6 wrong routes (/profiles → /wipes/profiles, etc.)
  and remove redundant manual license_id guards
- Changelog module: Add stub controller/service returning empty array
  to eliminate 404 on /api/changelog
- ChangelogView: Handle both array and {entries} response shapes
- AGENTS.md: Streamlined 3-tier roster (Opus/Sonnet/Haiku)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 22:11:41 -05:00
Vantz Stockwell
e849d7803c fix: JWT tokens expire instantly + double /api prefix in analytics
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
- Auth service used flat env var names (JWT_SECRET, JWT_ACCESS_EXPIRY_SECONDS)
  but @nestjs/config nests them under jwt.* — configService.get() returned
  undefined, so expiresIn was 0 and tokens expired on issue (iat === exp)
- JWT strategy had same bug for secretOrKey
- AnalyticsView passed /api/analytics/... to useApi which already prepends /api,
  resulting in /api/api/analytics/... (404)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 21:40:32 -05:00
Vantz Stockwell
2ad6a658ca fix: Add missing maps module and scope gitignore rules
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
maps/ gitignore rule was catching backend-nest/src/modules/maps/.
Scoped to /maps/ (root only) so runtime data is still ignored
but source code isn't.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 21:35:47 -05:00
Vantz Stockwell
d20493d533 feat: Complete NestJS backend scaffold — 22 modules, 39 entities, WebSocket gateway
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
Full backend rewrite from Rust/Axum to NestJS/TypeScript.
- 22 feature modules (auth, servers, wipes, maps, plugins, players, console,
  chat, team, notifications, settings, schedules, analytics, alerts, status,
  store, webstore, admin, setup, migration, users, licenses)
- 39 TypeORM entities matching PostgreSQL schema (12 migrations)
- Common infrastructure: JWT/RBAC guards, decorators, exception filter
- NATS service with pub/sub/request-reply
- Socket.IO WebSocket gateway with NATS bridge
- Docker: NestJS Dockerfile + updated docker-compose.yml
- Zero compile errors (npx tsc --noEmit clean)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 21:29:25 -05:00
Vantz Stockwell
0f8d0dd14f fix: Align NestJS entity columns with service expectations
Resolved 12 TypeScript compilation errors caused by mismatched column names between TypeORM entities and service layer.

Entity changes:
- NotificationsConfig: Renamed email_alerts_enabled → email_enabled, added email_address, standardized notification event column names (notify_on_start, notify_on_stop, notify_on_crash, etc.)
- ScheduledTask: Renamed is_active → is_enabled, added last_run timestamp
- TeamMember: Renamed accepted_at → joined_at to match service expectations
- Role: Added description column for custom role metadata

Service changes:
- JwtStrategy: Updated to reference joined_at instead of accepted_at

All services now compile cleanly against updated entity schemas.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 21:28:20 -05:00
Vantz Stockwell
8cd792eb75 feat: Implement NestJS Auth, Users, and Licenses modules
Complete authentication system with JWT, refresh tokens, and TOTP 2FA.
Auto-generates license keys on registration (CORR-XXXX-XXXX-XXXX format).
JwtStrategy enriches payload with license_id and permissions from roles.
Multi-tenant isolation enforced at license access layer.

Auth Module:
- 9 REST endpoints (login, register, refresh, 2FA setup/verify, profile, password reset)
- Argon2 password hashing, TOTP with QR code generation
- Public endpoints: login, register, forgot-password, reset-password, validate-key
- Authenticated endpoints require JWT Bearer token

Users Module:
- Admin CRUD for user management (requires users.view permission)
- Password fields excluded from all responses

Licenses Module:
- License lookup with owner authorization
- Public key validation endpoint for plugin verification
- License key generation via random hex parts

All DTOs use class-validator, all controllers documented via Swagger.
Custom decorators: @Public(), @CurrentUser(), @RequirePermission().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 21:13:57 -05:00