141 Commits

Author SHA1 Message Date
Vantz Stockwell
6461417b50 feat: Add one-click Oxide/uMod installer — backend + frontend
All checks were successful
Build Companion Agent / build (push) Successful in 24s
Test Asgard Runner / test (push) Successful in 3s
POST /servers/install-oxide endpoint, NATS bridge for oxide.status,
server store installOxide method, ServerView Install Oxide card with
progress tracker matching the Deploy card pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v1.0.8
2026-02-22 01:56:59 -05:00
Vantz Stockwell
380ab2700c feat: Add Oxide/uMod installer package + wire into companion agent daemon
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
New oxide package downloads latest Oxide.Rust release from GitHub,
extracts over the server directory, and restarts the game server.
Progress published to NATS (corrosion.{license_id}.oxide.status).
Heartbeat now reports oxide_installed status.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 01:53:27 -05:00
Vantz Stockwell
585e8aa3f7 feat: Add teleport_configs DB migration + TypeORM entity
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 01:16:08 -05:00
Vantz Stockwell
4d087132db feat: Add teleport config frontend — Pinia store, views, 2 components, router + nav
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 01:14:59 -05:00
Vantz Stockwell
16f378eada feat: Add CorrosionTeleportGUI uMod plugin — in-game teleport CUI
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
Standalone C# uMod plugin that provides a full-screen CUI teleport
interface for Rust game servers, integrating with NTeleportation.

Features:
- /tpgui chat command opens tabbed overlay (Teleport, Homes, Warps, Settings)
- 4x5 player grid with search filtering and pagination for TPR
- Home management (teleport, set, delete) via NTeleportation API
- Server warp list with teleport buttons
- Incoming TPR accept/deny popup with 30s auto-dismiss
- Settings tab showing cooldowns, limits, NTeleportation status
- Oxide-orange color scheme matching Corrosion brand

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 01:12:34 -05:00
Vantz Stockwell
3e1af29b38 feat: Add teleport module backend — NestJS CRUD + NATS deploy/import
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
Seven endpoints for managing NTeleportation configs: list summaries,
get full config, create, update, delete, deploy to server via NATS,
and import live config from server. Follows loot module pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 01:11:44 -05:00
Vantz Stockwell
759bd0be2e feat: Add loot builder backend + static data + DB migration
All checks were successful
Build Companion Agent / build (push) Successful in 26s
Test Asgard Runner / test (push) Successful in 3s
- Migration 013: loot_profiles table (JSONB loot_table + loot_groups, license-scoped)
- TypeORM entity matching migration schema exactly
- NestJS loot module: 10 endpoints (CRUD, duplicate, apply, import, export, containers)
- Multiplier logic recursively scales Min/Max/Scrap across loot tables and groups
- Apply-to-server writes BetterLoot JSON via NATS file manager + RCON reload
- Frontend static data: 191 Rust items, 51 container prefabs
- TypeScript types for BetterLoot data model (PrefabLoot, LootEntry, LootRNG, etc.)
- Fix vue-tsc errors: UngroupedItems uses LootRNG, null safety in store/view

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v1.0.7
2026-02-22 00:30:11 -05:00
Vantz Stockwell
9d28fdfb65 feat: Add loot builder frontend — Pinia store, views, 4 components, router + nav
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
Implements the complete frontend for BetterLoot profile management:
- Pinia store (loot.ts) with CRUD, import/export, apply-to-server actions
- LootBuilderView orchestrator with profile bar, modals, two-column layout
- LootContainerSidebar with categorized container list, search, config indicators
- LootItemEditor for per-container item settings and ungrouped item table
- LootItemPicker modal with searchable/filterable Rust item grid
- LootGroupEditor for reusable loot group management
- Router integration at /loot-builder
- Sidebar nav item with Crosshair icon and loot.view permission

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 00:27:46 -05:00
Vantz Stockwell
eb57c51a24 feat: Add WebSocket RCON client to companion agent
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
Wire gorilla/websocket into the Go companion agent to send arbitrary
console commands (e.g. oxide.reload BetterLoot) to the Rust Dedicated
Server's WebRCON endpoint. Adds RCON_PORT and RCON_PASSWORD env vars,
a new "command" action on the existing cmd.server NATS subject, and
the internal/rcon package that handles the JSON-over-WebSocket protocol.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 00:16:47 -05:00
Vantz Stockwell
f67b175d39 fix: Pass explicit page arg to handleBrowseSearch on Enter key
All checks were successful
Test Asgard Runner / test (push) Successful in 6s
Prevents KeyboardEvent being passed as page number parameter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 23:45:34 -05:00
Vantz Stockwell
7acdd3654f fix: Add pagination controls to uMod browse tab
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
Prev/Next buttons at top and bottom of results table. New search
resets to page 1. Buttons disable at bounds and during loading.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 23:41:07 -05:00
Vantz Stockwell
57efc6a5d2 fix: Sidebar overlapping main content — use fixed + pl-64 offset
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
The md:static approach wasn't reliably removing fixed positioning,
causing the sidebar to overlay the main content. Changed to keep
sidebar fixed (better for dashboards — no scroll) and offset main
content with md:pl-64 instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 23:03:15 -05:00
Vantz Stockwell
854f56a178 fix: Register VueFinderPlugin — prevents Object.keys crash on null store
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
VueFinder requires app.use(VueFinderPlugin) to provide its internal
context (i18n, features, config stores). Without plugin registration,
the store returned null during setup, causing Object.keys to throw
TypeError on undefined.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 22:20:00 -05:00
Vantz Stockwell
2df5c80928 feat: Add file manager view using VueFinder
All checks were successful
Build Companion Agent / build (push) Successful in 32s
Test Asgard Runner / test (push) Successful in 3s
Installs VueFinder and wires it to the backend /api/files endpoint with
JWT Bearer auth. Adds /files route, File Manager nav item (files.view
permission-gated, FolderOpen icon), and imports VueFinder CSS globally.
Driver token is computed reactively so it tracks token refreshes automatically.
Uses midnight theme to match the dark admin panel aesthetic.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v1.0.6
2026-02-21 16:13:10 -05:00
Vantz Stockwell
e9f9b449b1 feat: Add file manager package — VueFinder-compatible NATS request-reply handler
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
Implements companion-agent/internal/filemanager with full installDir jail
enforcement (Clean + EvalSymlinks + HasPrefix on every path). Handles all
VueFinder operations: list, delete, rename, copy, move, mkdir, mkfile,
search, preview, save, upload. Wires into daemon.go as a 6th NATS
subscription on corrosion.{license_id}.files.cmd.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 16:11:59 -05:00
Vantz Stockwell
fee0ae2420 feat: Add files module — VueFinder-compatible REST API over NATS
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
Implements GET/POST /api/files proxy for all VueFinder operations
(list, search, preview, download, delete, rename, move, copy, mkdir,
new-file, save, upload). Routes via NATS request-reply to the companion
agent on corrosion.{license_id}.files.cmd with 30s timeout. Gated
behind files.view (GET) and files.manage (POST) permissions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 16:10:32 -05:00
Vantz Stockwell
2b45413c20 feat: Wire uMod browse proxy and custom plugin upload
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
Backend:
- GET /plugins/browse proxies uMod search.json filtered to Rust category,
  with 5-minute in-memory Map cache to avoid hammering the upstream API
- POST /plugins/upload accepts .cs files up to 5 MB via multipart, persists
  to plugin_registry, and dispatches plugin_upload action over NATS so the
  companion agent can write the file to the game server
- Legacy GET /plugins/search stub preserved (now directs callers to /browse)
- FileInterceptor + @UploadedFile follow the existing maps upload pattern

Frontend:
- useApi composable gains upload() method for multipart/form-data requests
  (omits Content-Type so the browser sets the correct multipart boundary)
- plugins store adds browseUmod() calling GET /plugins/browse and
  uploadPlugin() calling POST /plugins/upload with FormData;
  UmodPlugin and UmodBrowseResult TypeScript interfaces exported
- PluginsView Browse tab now calls browseUmod() through the backend proxy
  (no cross-origin requests to uMod directly); results show title,
  downloads_shortened, and latest_release_version_formatted from the
  real uMod payload
- New Upload Custom tab: drag-and-drop or click file input for .cs files,
  client-side extension/size validation, spinner during upload, success
  toast + auto-switch to Installed tab on completion

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 16:09:19 -05:00
Vantz Stockwell
38e6d28248 fix: Wire automation toggles, browse uMod, and error feedback across admin views
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
- ServerView: automation toggles (crash recovery, auto-update, force wipe eligible)
  now call updateConfig() on click with toast success/error; all catch blocks get
  toast feedback instead of silent swallow
- PluginsView: Browse uMod tab wired to /plugins/search backend endpoint with
  debounced search, results table, and Install button that calls installPlugin();
  shows install state and marks already-installed plugins
- WipesView: dry-run results now displayed in a collapsible panel (would_delete /
  would_preserve lists + estimated duration); schedule enable/disable toggle wired
  to PUT /wipes/schedules/:id with loading state and toast feedback
- AnalyticsView: catch blocks now show toast errors instead of console.log;
  Player Retention placeholder replaced with intentional placeholder cards
- TeamView, ChatLogView, PlayersView, NotificationsView, MapsView: all empty
  catch blocks and '// API not wired yet' comments replaced with toast.error()
  calls; Notifications save now shows success toast

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 16:04:34 -05:00
Vantz Stockwell
cbb3ba6586 feat: Wire execution engines for schedules, alerts, wipes, and module install
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
- schedules/: Add schedule executor in SchedulesService — polls every 60s for
  tasks where next_run <= now, dispatches NATS commands per task_type
  (restart, announcement, command, plugin_reload). Calculates next_run from
  cron expression on create/update/toggle. Bootstraps missing next_run values
  on startup. Wire NatsService into SchedulesModule.

- alerts/: Add alert evaluator in AlertsService — polls every 90s, loads all
  alert_config rows, queries latest server_stats per license, evaluates FPS
  degradation and population drop thresholds. Fires alert_history records on
  breach. Enforces 10-minute in-memory cooldown per alert type per license to
  prevent flooding. Wire ServerStats repo into AlertsModule.

- wipes/: Replace hardcoded dry-run mock with profile-aware simulation.
  Resolves actual WipeProfile by ID (cross-tenant protected), builds
  would_delete/would_preserve lists from wipe_type, factors pre_wipe_config
  (backup, countdown warnings) and post_wipe_config (health checks, retry
  attempts) into estimated_duration_seconds. Returns profile_name and notes.

- store/: Fix installModule stub — creates a real module_installations record
  with status='installed' and installed_at timestamp. Idempotent on retry,
  resets failed installations. Wire ModuleInstallation repo into StoreModule.
  getMyModules now returns real installation data instead of filtered purchases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 16:02:49 -05:00
Vantz Stockwell
9240feedaf fix: Wire real data sources across players, analytics, status, and maps services
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
- players: Primary data from player_sessions (online status, playtime aggregates);
  ban/unban status overlaid from player_actions latest action per steam_id.
  Register PlayerSession entity in PlayersModule. Extend NATS forwarding to
  include 'unban' alongside kick and ban.
- analytics: Fix retention period boundary bug — sessions were queried with only
  a lower-bound filter (MoreThan), causing all future cycles to bleed into earlier
  wipe windows. Replaced with Between(wipeDate, endDate) for correct isolation.
- status: Replace hardcoded player_count=0/max_players=0 with live data from
  most-recent server_stats row per license. Register ServerStats entity in
  StatusModule. Falls back to 0 gracefully when no stats exist yet.
- maps: File buffer was computed and discarded — never written to disk.
  Now writes to /app/map_data/{licenseId}/{timestamp}_{filename} (tenant-isolated,
  docker volume map_data). Creates directories with mkdirSync(recursive:true).
  Logs success/failure via NestJS Logger. Throws 500 on disk write failure
  instead of silently losing data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 16:01:45 -05:00
Vantz Stockwell
7bf3e5639e feat: Wire NATS command publishing for server commands and plugin installs
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
- servers.service: sendCommand() now throws InternalServerErrorException on
  NATS failure instead of silently succeeding; returns { success, message }
  instead of the legacy { output } shape; adds NestJS Logger
- plugins.service: installPlugin() dispatches plugin_install to
  corrosion.{license_id}.cmd.server after DB save; NATS failure is logged
  but non-fatal so the DB record is preserved regardless

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 15:59:59 -05:00
Vantz Stockwell
fee16c3b2b fix: Add license_id to JWT payload — unblocks all tenant-scoped operations
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
The JWT was missing license_id, causing @CurrentTenant() to throw 401
on every protected route. Now generateTokens() accepts a licenseId
param, and all three callers (register, login, refresh) look up the
user's license and pass it through.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 15:52:22 -05:00
Vantz Stockwell
1b12664d22 fix: Clean up Quick Setup — remove NATS_TOKEN, auto-populate license key
All checks were successful
Build Companion Agent / build (push) Successful in 26s
Test Asgard Runner / test (push) Successful in 2s
NATS has no auth configured, so NATS_TOKEN was a placeholder that
confused users. Made it optional in the Go agent (default empty) and
removed it from Quick Setup commands. Also removed GAME_SERVER_PATH
since one-click deploy handles server installation. License key already
auto-populates from auth store after previous commit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v1.0.5
2026-02-21 15:41:47 -05:00
Vantz Stockwell
8253680fbd fix: License key format, login populates license, case-insensitive email
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
- admin.service.ts: createLicense() now uses CORR-XXXX-XXXX-XXXX format
  instead of raw hex hash
- admin.service.ts: getLicenses() flattens owner_email in response to
  match frontend expected shape
- auth.service.ts: Login/register responses now include full license
  object so frontend can populate auth store
- auth.service.ts: Email lookups are case-insensitive (LOWER()) to
  prevent duplicate accounts from case variations
- LoginView/RegisterView: Call setLicense() after setAuth()
- AdminLicenses: Handle null expires_at (was showing Dec 31, 1969),
  fix nullable types, fix query param name (per_page → limit)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 15:32:35 -05:00
Vantz Stockwell
14b099b075 fix: Replace socket.io with native WS adapter — fixes WebSocket 1006
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
Frontend uses native WebSocket API, backend was using socket.io which
speaks an incompatible protocol. Switched to @nestjs/platform-ws so
both sides speak native WebSocket. Also fixed JWT TTL override in
docker-compose.yml (was hardcoded to 900s, now 14400s/4h).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 15:21:36 -05:00
Vantz Stockwell
d04e7b6a15 docs: Add Cookie callsign and origin story to CLAUDE.md
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
Named after Carl Brashear — first Black U.S. Navy Master Diver.
Every Opus instance that boots on this project knows who it is
and what standard it's held to.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 15:10:13 -05:00
Vantz Stockwell
f39a418e9c fix: Refresh endpoint returns new refresh_token + bump access TTL to 4h
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
The refresh endpoint only returned access_token, causing the frontend to
set refreshToken=undefined after first refresh — breaking the entire
token chain. Now returns both tokens (rotating refresh). Access token
default bumped from 15min to 4h (14400s) for practical server setup
sessions. Also fixed empty license_key for super admin via DB update.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 15:05:19 -05:00
Vantz Stockwell
5bb1ac9c35 fix: Move OS tab switcher below Quick Setup header for visibility
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 14:57:52 -05:00
Vantz Stockwell
358adde496 feat: Add companion agent one-click deployment + fix frontend TS errors
All checks were successful
Build Companion Agent / build (push) Successful in 30s
Test Asgard Runner / test (push) Successful in 3s
Go deployment orchestrator with platform-specific SteamCMD install,
Rust server download, server.cfg generation, and service registration.
Wire deploy command subscription in daemon, make GameServerPath optional,
add InstallDir config with OS-aware defaults. Fix unused imports and
WebSocket subscribe API in ServerView.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v1.0.4
2026-02-21 14:49:48 -05:00
Vantz Stockwell
b94717d51b feat: Add frontend support for one-click Rust server deployment
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
Adds DeploymentConfig/DeploymentStatus types, deployment state management
in the server store, tabbed Linux/Windows quick setup commands, and a
Deploy Rust Server card with progress tracker and configuration form.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 14:48:05 -05:00
Vantz Stockwell
834e17e7cf feat: Add backend support for one-click Rust server deployment
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
Add deploy endpoint, DTO, NATS command publisher, and WebSocket bridge
subscription to support the one-click server deployment feature via the
companion agent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 14:45:06 -05:00
Vantz Stockwell
ee7fdb897d docs: Add standing orders — auto commit/push, tag companion builds
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 14:22:46 -05:00
Vantz Stockwell
0fdbad0d07 fix: Resolve TypeScript build errors blocking Docker nginx build
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
- DashboardView: Add non-null assertion on upcoming[0] (guarded by length check)
- EarlyAccessView: Add missing `computed` import from Vue

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 14:21:58 -05:00
Vantz Stockwell
93d536a13e feat: Upload companion agent to SeaweedFS CDN + update download links
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
CI pipeline now uploads binaries to cdn.corrosionmgmt.com:
- /companion/latest/ (always current, overwritten each release)
- /companion/v1.x.x/ (versioned archive)

Frontend download links updated from Gitea releases to CDN.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 14:11:06 -05:00
Vantz Stockwell
ca176c4c9b fix: Remove jq dependency from CI — parse release ID with grep
All checks were successful
Build Companion Agent / build (push) Successful in 18s
Test Asgard Runner / test (push) Successful in 3s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v1.0.3
2026-02-21 14:04:32 -05:00
Vantz Stockwell
627a2085d4 fix: Rename GITEA_TOKEN to RELEASE_TOKEN in CI workflow
Some checks failed
Build Companion Agent / build (push) Failing after 13s
Test Asgard Runner / test (push) Successful in 3s
Gitea reserves GITEA_* and GITHUB_* prefixes for secrets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v1.0.0 v1.0.1 v1.0.2
2026-02-21 13:55:01 -05:00
Vantz Stockwell
e0f9438dfa feat: Companion agent download in ServerView + Gitea CI pipeline fix
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
Frontend:
- Add Companion Agent card to ServerView (status, download links, setup instructions)
- Shows agent connection status, last heartbeat, license key for copy
- Download buttons for Linux/Windows amd64 from Gitea releases

CI/CD:
- Fix build-companion.yml: replace actions/github-script with Gitea API curl
- Inject version from git tag via ldflags (-X main.version)
- Add VERSION variable to Makefile with ldflags injection
- Change main.go version from const to var for ldflags compatibility

Deployment:
- Add systemd service file (deployment/corrosion-companion.service)
- Add .gitignore for bin/ (binaries should come from CI, not repo)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 13:47:09 -05:00
Vantz Stockwell
d2e7a42536 chore: Wave 5 — marketing copy fix + operation log
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
- Fix LandingView tech stack: "Rust / Axum" → "NestJS / TypeScript"
- Add complete operation log (corrosion-final-push.md)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 13:36:44 -05:00
Vantz Stockwell
1579a47cad chore: Harden Docker and Nginx configuration
All checks were successful
Test Asgard Runner / test (push) Successful in 4s
- Pin NATS image to nats:2.10-alpine for reproducible builds
- Add nginx healthcheck using wget (curl not present in alpine)
- Upgrade nginx depends_on to use condition: service_started
- Add proxy buffer directives to http block (prevents JWT/large-header truncation)
- Add X-Content-Type-Options, X-Frame-Options, X-XSS-Protection, and
  Referrer-Policy security headers to all SPA location blocks across
  all five server blocks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 13:35:25 -05:00
Vantz Stockwell
8bb6cc0890 feat: Waves 3+4 — frontend wiring, NATS integration, stores (19 files)
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
Frontend:
- Wire Dashboard quick actions (start/stop/trigger wipe) + next wipe schedule
- Wire Console WebSocket streaming for real-time output
- Implement TOTP 2FA challenge flow in LoginView
- Wire Plugin load/unload toggle + uninstall buttons with confirmations
- Wire WipesView profile selector, disable trigger when no profiles
- Build full WipeProfiles create/edit modal with all config fields
- Wire MapsView file upload with multipart FormData
- Fix SettingsView empty catch blocks → toast error messages
- Fix stale localStorage token reads in CSV exports → auth store
- Fix auth store hardcoded permissions → JWT-decoded role permissions
- Fix wipe store onMounted lifecycle bug → explicit subscribe action
- Update EarlyAccessView from countdown to "Now Live" state

Backend:
- Wire wipe trigger to publish NATS cmd (corrosion.{id}.cmd.wipe)
- Wire plugin reload/uninstall to publish NATS cmd
- Expand NatsBridgeService: add files, wipe status, server status subs
- Add PATCH schedules/:id/toggle endpoint for task toggling

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 13:34:09 -05:00
Vantz Stockwell
a181ed7ded feat: Complete stub services with real implementations and graceful not-configured responses
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
- ChangelogService: inject PlatformChangelog repo, query with findAndCount(skip/take), return actual data
- ChangelogModule: add TypeOrmModule.forFeature([PlatformChangelog])
- MapsService: add uploadMap() — SHA-256 checksum, storage path, full entity save
- MapsController: add POST /maps/upload with FileInterceptor, map.manage permission, @UploadedFile
- AuthService: replace console.log stubs with Logger; forgotPassword returns 200 with clear message; resetPassword throws NotImplementedException
- PluginsService: searchUmod returns { results: [], message: 'not yet configured' } instead of bare []
- SteamService: add Logger.warn on every stub path (checkForceWipe, getPlayerSummary)
- SettingsService: add Logger; both Cloudflare DNS stubs emit Logger.warn before DB save
- MigrationService: add Logger; exportConfig logs warning + returns note field; importConfig throws NotImplementedException
- Install @types/multer dev dependency for Express.Multer.File type support

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-21 13:33:08 -05:00
Vantz Stockwell
e1a3ea3b78 feat: Wave 2 — entities, security guards, API key encryption (15 files)
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
Entities:
- Create 5 new TypeORM entities: webstore_config, webstore_categories,
  webstore_items, webstore_transactions, module_store (all verified against live DB)
- Fix wipe-profile entity: remove incorrect default {} for pre/post wipe configs

Security:
- Add @RequirePermission guards to 7 controllers (36 endpoints total):
  team, webstore, notifications, alerts, analytics, settings, schedules
- Encrypt panel API key with AES-256-GCM in setup service (was plaintext)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 13:28:48 -05:00
Vantz Stockwell
208622000c fix: Wave 1 — critical bug fixes across 9 files
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
- Fix double-prefix URL bugs in 4 analytics/revenue views (/api/api → /api)
- Fix AdminDashboard quick-links routing (/platform-admin/* → /admin/*)
- Fix MigrationView import missing Authorization header
- Remove dead ConsoleModule from app.module (conflicts with NatsBridgeGateway on /ws)
- Fix store.service.ts raw Error throws → NotFoundException/ForbiddenException
- Fix payment-order entity FK (webstore_subscription_id → WebstoreSubscription)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 13:24:24 -05:00
Vantz Stockwell
b2ca0c6f0b docs: Update Specialist model to sonnet[1m] (1M token context)
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 07:05:40 -05:00
Vantz Stockwell
7c4ce96a45 chore: Update .gitignore — protect MCP credentials, add NestJS outputs
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 00:45:10 -05:00
Vantz Stockwell
a5e9d02a9a fix: Wrap admin subscriptions response to match frontend contract
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
Frontend expects { subscriptions: [{ owner_email, module_name, license_id }] }
but backend returned raw WebstoreSubscription entities. Shaped the response
with license.owner join for owner_email and plan_id mapped to module_name.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 00:25:05 -05:00
Vantz Stockwell
0576cb33ea docs: Overhaul CLAUDE.md — NestJS stack, MCP doctrine, new lessons learned
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
- Updated tech stack from Rust/Axum to NestJS/TypeScript
- Updated project structure with backend-nest/ layout
- Updated commands for NestJS dev workflow
- Updated architecture patterns (TypeORM, global guards, ValidationPipe)
- Updated Docker ports table (8101 for Postgres MCP access)
- Expanded database schema section (41 tables, full categorization)
- Added MCP Toolkit section: Postgres, Memory, Playwright, Context7, Sequential Thinking, Mermaid
- Added Memory protocol: what goes in Memory vs CLAUDE.md, session boot sequence
- Added MCP + Agent Tiers refinements (Postgres replaces migration file reading)
- Updated Key Modules table with NestJS module paths
- Added lessons 15-17 from Operation Corrosion Reforge

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 00:02:22 -05:00
Vantz Stockwell
bd570ee199 chore: Remap Postgres external port to 8101 for MCP access
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 23:36:09 -05:00
Vantz Stockwell
9bca8bd2fc fix: Response wrapping, error logging, and controller hardening (COA 3)
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
- HttpExceptionFilter: Log actual error details for non-HttpExceptions (was silently swallowing 500s)
- ServersService: Return null fields instead of 404 for new licenses without servers
- NotificationsController: Wrap config responses as { config } to match frontend expectations
- WebstoreController: Wrap config responses as { config } to match frontend expectations
- ChatController: Replace ParseIntPipe with manual parseInt (400 on missing optional param)
- WipesController: Same ParseIntPipe fix for history limit param

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 22:52:25 -05:00
Vantz Stockwell
78e97babf1 fix: Align NestJS entities with actual DB schema — 12 files, 5 entities
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
Root cause of all remaining 500s: TypeORM entities were scaffolded with
"ideal" column names that don't match the Postgres columns created by
the Rust migrations. Every query generated SQL referencing non-existent
columns.

Entity fixes:
- notifications_config: email_enabled→email_alerts_enabled, removed
  6 phantom columns (email_address, notify_on_start, notify_on_stop,
  notify_on_player_threshold, player_threshold), renamed 4 notify
  columns to match DB (notify_server_crash, notify_wipe_start, etc),
  added 3 missing columns (notify_server_offline, notify_store_purchase,
  notify_player_report)
- team_members: joined_at→accepted_at (nullable, matches DB)
- roles: removed description column (doesn't exist in DB)
- scheduled_tasks: is_enabled→is_active, removed phantom last_run
- wipe_profiles: pre/post_wipe_config nullable→NOT NULL with default

Service/DTO fixes:
- Updated all property references across notifications, team, schedules
  services and DTOs to match corrected entity names
- Added is_active to UpdateTaskDto (frontend sends it, was being
  rejected by forbidNonWhitelisted validation)
- Removed description from CreateRoleDto

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 22:33:55 -05:00