Files
corrosion-admin-panel/docs/corrosion-architecture.md
2026-02-15 12:07:19 -05:00

54 KiB
Raw Blame History

Corrosion — Platform Architecture & Specification

Product: Corrosion — Rust Server Management Platform Domain: corrosionmgmt.com Author: Vantz Stockwell — Vigil Cyber LLC Version: 1.0 Date: February 14, 2026


Executive Summary

Corrosion is a hosted SaaS platform that gives Rust server administrators a complete management interface — from wipe automation to plugin management to community storefronts — without requiring any technical infrastructure on their end. Customers install a single uMod plugin, register online, and manage everything from the web.

The platform eliminates the complexity that keeps casual server owners from running professional communities. One plugin. One dashboard. Everything works.


Product Vision

One sentence: A Rust server admin installs one plugin, registers online, and never has to SSH into their box, edit a config file, or babysit a wipe again.

The problem: Running a Rust server well requires juggling multiple tools, editing JSON configs over SFTP, manually timing wipes, hand-installing plugins, and being online when things break. The barrier to entry is high, and even experienced admins waste hours on operational tasks instead of building their community.

The solution: Corrosion moves all server administration to a hosted web platform. The game server runs a lightweight plugin that communicates with Corrosion's cloud via NATS. Everything else — configuration, plugin management, wipe automation, player moderation, community websites, item stores — happens in the browser.


Business Model

Licensing

Tier Price What They Get
Base License $50 one-time (CodeFling) Core platform access: server management, auto-wiper, plugin installer, public site, analytics, RBAC, all Phase 1-3 features
Module Store $9.99$24.99 per module Add-on modules (loot manager, event plugins, etc.) tied to their license key
Webstore Add-on $10/month Integrated item store with PayPal processing
Cloud Backup $X/month Off-server backup storage on Corrosion infrastructure
Site License (B2B) $XXX/month Hosting company integration — bulk licensing for all their Rust customers

License Rules

  • One license = one server = one subdomain
  • Multi-admin with unlimited team members per license (RBAC)
  • License key validated on plugin startup and periodic check-in
  • Module purchases are tied to the license key and unlocked instantly
  • License is transferable (server owner sells their server, license goes with it)

Platform Architecture

High-Level Overview

┌─────────────────────────────────────────────────────────────┐
│                    CORROSION CLOUD                           │
│                                                             │
│  ┌─────────────┐  ┌─────────────┐  ┌────────────────────┐  │
│  │  Web App     │  │  REST API   │  │  NATS Cluster      │  │
│  │  (Vue 3)     │  │  (Rust/Axum)│  │  (JetStream)       │  │
│  │             │  │             │  │                    │  │
│  │  Dashboard   │  │  Business   │  │  Real-time comms   │  │
│  │  Public sites│  │  Logic      │  │  Command delivery  │  │
│  │  Module store│  │  License    │  │  Stats streaming   │  │
│  │  Status page │  │  Billing    │  │  Health monitoring  │  │
│  └──────┬──────┘  └──────┬──────┘  └─────────┬──────────┘  │
│         │                │                    │             │
│  ┌──────┴────────────────┴────────────────────┴──────────┐  │
│  │                    PostgreSQL                          │  │
│  └───────────────────────────────────────────────────────┘  │
│                                                             │
│  ┌───────────────┐  ┌──────────────┐  ┌────────────────┐   │
│  │  Cloudflare   │  │  Nginx       │  │  File Storage  │   │
│  │  DNS API      │  │  Reverse     │  │  (Maps, Backups│   │
│  │  (Subdomains) │  │  Proxy       │  │   Modules)     │   │
│  └───────────────┘  └──────────────┘  └────────────────┘   │
└─────────────────────────────────────────────────────────────┘
                              │
                    NATS (outbound from customer)
                              │
          ┌───────────────────┼───────────────────┐
          │                   │                   │
   ┌──────┴──────┐    ┌──────┴──────┐    ┌──────┴──────┐
   │  Customer A │    │  Customer B │    │  Customer C │
   │             │    │             │    │             │
   │  Rust Server│    │  Rust Server│    │  Rust Server│
   │  + Plugin   │    │  + Plugin   │    │  + Plugin   │
   │  + Companion│    │  (AMP)      │    │  (Ptero)    │
   │  (Bare Metal│    │             │    │             │
   └─────────────┘    └─────────────┘    └─────────────┘

Connection Model

All connections are outbound from the customer's server to the Corrosion cloud. No inbound ports need to be opened on the customer's firewall.

Panel users (AMP / Pterodactyl):

  • uMod plugin connects outbound to Corrosion NATS cluster
  • Customer provides panel API credentials in the dashboard
  • Corrosion API calls the panel API directly for server control and file operations

Bare metal users:

  • uMod plugin connects outbound to Corrosion NATS cluster
  • Companion agent (pre-configured binary downloaded from dashboard) connects outbound to Corrosion NATS cluster
  • Companion handles server process control and filesystem operations locally

In both cases: The customer's dashboard experience is identical. The connection method is an implementation detail they configure once during setup and never think about again.


Technology Stack

Corrosion Cloud — Backend (Rust)

Component Crate Purpose
Web Framework axum HTTP API, built on Tokio async runtime
Database sqlx Compile-time verified PostgreSQL queries
Messaging async-nats NATS client with JetStream support
Middleware tower-http CORS, authentication, rate limiting, logging
Password Hashing argon2 Secure credential storage
JWT Auth jsonwebtoken Session and API token management
2FA totp-rs TOTP-based two-factor authentication
Email lettre Transactional email (verification, alerts, backup codes)
Serialization serde / serde_json JSON serialization/deserialization
Scheduling tokio-cron-scheduler Cron-based scheduled tasks (wipes, restarts, etc.)
HTTP Client reqwest Panel API calls, Cloudflare API, Steam API, PayPal webhooks
Encryption aes-gcm Encrypt sensitive stored data (API keys, webhook URLs)
URL Signing hmac / sha2 Signed URLs for file downloads

Corrosion Cloud — Frontend (Vue 3 + TypeScript)

Component Library Purpose
Build Tool Vite Fast dev server and production builds
Routing Vue Router SPA client-side routing
State Pinia Reactive state management
Styling Tailwind CSS Utility-first CSS
Charts Apache ECharts Analytics and monitoring visualizations
Real-time NATS WebSocket Live server data in dashboard
Icons Lucide Clean icon set

Game Server — uMod Plugin (C#)

Component Library Purpose
Framework Oxide/uMod Rust game server plugin API
Messaging NATS.Client Outbound NATS connection to Corrosion cloud
JSON Newtonsoft.Json Payload serialization
HTTP RestSharp REST API calls (license validation, file downloads)

Game Server — Companion Agent (Go)

Component Purpose
NATS Client Outbound connection to Corrosion cloud
Process Manager Start/stop/restart Rust server process
File System Read/write/delete server files, map swaps, config edits
Steam Update Trigger SteamCMD updates
Self-Update Pull new versions from Corrosion API

Infrastructure

Service Purpose
PostgreSQL 16 Primary data store (multi-tenant)
NATS Cluster (JetStream) Real-time messaging, command delivery, stats streaming
Nginx Reverse proxy, subdomain routing, static file serving
Cloudflare DNS management (subdomain provisioning via API), SSL, CDN, DDoS protection
Object Storage (S3-compatible) Map library, cloud backups, module distribution

Multi-Tenant Data Architecture

Every customer record is scoped by license_id. All queries filter by license. No customer can ever see another customer's data.

Database Schema

licenses

Column Type Notes
id UUID PK
license_key VARCHAR(64) Unique, generated on CodeFling purchase
status VARCHAR(20) 'active', 'suspended', 'expired', 'revoked'
owner_user_id UUID FK → users (the purchaser)
server_name VARCHAR(100) Display name for this server
subdomain VARCHAR(63) Unique subdomain on corrosionmgmt.com
custom_domain VARCHAR(255) Optional CNAME domain
modules_enabled TEXT[] List of module slugs activated on this license
webstore_active BOOLEAN Default false
webstore_subscription_id VARCHAR(100) PayPal subscription ID if active
created_at TIMESTAMPTZ
expires_at TIMESTAMPTZ Nullable — lifetime licenses have no expiry

users

Column Type Notes
id UUID PK
email VARCHAR(255) Unique, verified
username VARCHAR(50) Unique display name
password_hash TEXT Argon2 hashed
totp_secret TEXT Encrypted, nullable
totp_enabled BOOLEAN Default false
backup_codes TEXT[] Encrypted
email_verified BOOLEAN Default false
created_at TIMESTAMPTZ
last_login_at TIMESTAMPTZ

team_members

Column Type Notes
id UUID PK
license_id UUID FK → licenses
user_id UUID FK → users
role_id UUID FK → roles
invited_by UUID FK → users
accepted_at TIMESTAMPTZ Nullable until accepted
created_at TIMESTAMPTZ

roles

Column Type Notes
id UUID PK
license_id UUID FK → licenses (null for system defaults)
role_name VARCHAR(50) e.g., "Owner", "Head Admin", "Moderator"
is_system_default BOOLEAN True for built-in roles
is_cloned_from UUID FK → roles, nullable
permissions JSONB Permission flags (see below)
created_at TIMESTAMPTZ

Default system roles:

{
  "owner": {
    "server.*": true,
    "wipe.*": true,
    "plugins.*": true,
    "players.*": true,
    "team.*": true,
    "billing.*": true,
    "store.*": true,
    "settings.*": true,
    "public_site.*": true
  },
  "head_admin": {
    "server.*": true,
    "wipe.*": true,
    "plugins.*": true,
    "players.*": true,
    "team.view": true,
    "team.invite": true,
    "store.*": true,
    "settings.server": true,
    "public_site.*": true
  },
  "moderator": {
    "server.view": true,
    "server.console": true,
    "players.kick": true,
    "players.ban": true,
    "players.chat_log": true,
    "wipe.view": true,
    "store.view": true
  },
  "viewer": {
    "server.view": true,
    "players.view": true,
    "wipe.view": true,
    "store.view": true
  }
}

server_connections

Column Type Notes
id UUID PK
license_id UUID FK → licenses
connection_type VARCHAR(20) 'amp', 'pterodactyl', 'bare_metal'
panel_api_endpoint TEXT Nullable (not used for bare metal)
panel_api_key_encrypted TEXT Nullable
panel_server_identifier VARCHAR(255) Panel-specific server ID, nullable
companion_agent_token VARCHAR(128) Auth token for companion agent, nullable
companion_last_seen TIMESTAMPTZ Last heartbeat from companion
plugin_last_seen TIMESTAMPTZ Last heartbeat from uMod plugin
server_ip VARCHAR(45)
server_port INTEGER
game_port INTEGER
connection_status VARCHAR(20) 'connected', 'degraded', 'offline'
created_at TIMESTAMPTZ
updated_at TIMESTAMPTZ

server_config

Column Type Notes
id UUID PK
license_id UUID FK → licenses
server_name VARCHAR(255) In-game server name
max_players INTEGER
world_size INTEGER
current_seed INTEGER
current_map_id UUID FK → map_library, nullable
server_description TEXT
server_url TEXT
server_header_image TEXT
tags TEXT[] Server tags
auto_restart_enabled BOOLEAN Default false
auto_restart_cron VARCHAR(100) Cron expression for scheduled restarts
auto_restart_timezone VARCHAR(50)
crash_recovery_enabled BOOLEAN Default true
crash_recovery_max_attempts INTEGER Default 3
crash_recovery_cooldown_minutes INTEGER Default 10
force_wipe_eligible BOOLEAN Default true
auto_update_on_force_wipe BOOLEAN Default true
config_overrides JSONB Additional server.cfg key-value pairs
created_at TIMESTAMPTZ
updated_at TIMESTAMPTZ

game_admins

Column Type Notes
id UUID PK
license_id UUID FK → licenses
steam_id VARCHAR(20) Steam64 ID
display_name VARCHAR(100)
admin_level VARCHAR(20) 'owner', 'admin', 'moderator'
permissions JSONB Oxide permission flags
added_by UUID FK → users
created_at TIMESTAMPTZ

wipe_profiles

Column Type Notes
id UUID PK
license_id UUID FK → licenses
profile_name VARCHAR(100)
description TEXT
pre_wipe_config JSONB Pre-wipe sequence settings
post_wipe_config JSONB Post-wipe verification settings
created_at TIMESTAMPTZ
updated_at TIMESTAMPTZ

pre_wipe_config JSONB structure:

{
  "enabled": true,
  "backup_before_wipe": true,
  "countdown_warnings": [30, 15, 5, 1],
  "countdown_unit": "minutes",
  "countdown_messages": {
    "30": "Server wipe in 30 minutes! Prepare yourselves!",
    "15": "Server wipe in 15 minutes!",
    "5": "Server wipe in 5 minutes! Wrapping up...",
    "1": "Server wipe in 1 minute! See you on the other side!"
  },
  "kick_players_before_wipe": true,
  "kick_message": "Server is wiping. Be back shortly!",
  "run_final_save": true,
  "discord_pre_announce": true,
  "pushbullet_notify": true,
  "custom_commands_before": []
}

post_wipe_config JSONB structure:

{
  "enabled": true,
  "verify_server_started": true,
  "verify_correct_map": true,
  "verify_plugins_loaded": true,
  "verify_player_slots_open": true,
  "max_restart_attempts": 3,
  "health_check_timeout_seconds": 120,
  "discord_post_announce": true,
  "pushbullet_notify": true,
  "rollback_on_failure": true,
  "post_wipe_commands": []
}

wipe_schedules

Column Type Notes
id UUID PK
license_id UUID FK → licenses
wipe_profile_id UUID FK → wipe_profiles
schedule_name VARCHAR(100)
wipe_type VARCHAR(20) 'map', 'blueprint', 'full'
cron_expression VARCHAR(100)
timezone VARCHAR(50)
wipe_blueprints BOOLEAN Default false
is_active BOOLEAN Default true
next_scheduled_run TIMESTAMPTZ
created_at TIMESTAMPTZ

map_library

Column Type Notes
id UUID PK
license_id UUID FK → licenses
filename VARCHAR(255)
display_name VARCHAR(255)
storage_path TEXT Path in object storage
file_size_bytes BIGINT
map_type VARCHAR(20) 'custom' or 'procedural'
seed INTEGER Nullable
world_size INTEGER Nullable
thumbnail_path TEXT Nullable
checksum VARCHAR(64) SHA-256
uploaded_at TIMESTAMPTZ

map_rotations

Column Type Notes
id UUID PK
license_id UUID FK → licenses
map_id UUID FK → map_library
rotation_order INTEGER
is_active BOOLEAN Default true

plugin_registry

Column Type Notes
id UUID PK
license_id UUID FK → licenses
plugin_name VARCHAR(255)
plugin_version VARCHAR(50)
source VARCHAR(20) 'umod', 'corrosion_module', 'manual'
umod_slug VARCHAR(255) Nullable, for uMod-sourced plugins
is_installed BOOLEAN
is_loaded BOOLEAN Current runtime state from plugin report
config_json JSONB Plugin config (editable from dashboard)
data_path TEXT Relative path to plugin data
wipe_on_map BOOLEAN Default false
wipe_on_bp BOOLEAN Default false
wipe_on_full BOOLEAN Default false
never_wipe BOOLEAN Default false
installed_at TIMESTAMPTZ
updated_at TIMESTAMPTZ

wipe_history

Column Type Notes
id UUID PK
license_id UUID FK → licenses
wipe_schedule_id UUID FK → wipe_schedules, nullable
wipe_profile_id UUID FK → wipe_profiles
wipe_type VARCHAR(20)
trigger_type VARCHAR(20) 'scheduled', 'manual', 'force_wipe'
status VARCHAR(20) 'pending', 'pre_wipe', 'wiping', 'post_wipe', 'success', 'failed', 'rolled_back'
started_at TIMESTAMPTZ
completed_at TIMESTAMPTZ
map_used VARCHAR(255)
plugins_wiped TEXT[]
plugins_preserved TEXT[]
backup_reference TEXT Storage path to pre-wipe backup
error_message TEXT
execution_log JSONB Step-by-step log
created_at TIMESTAMPTZ

scheduled_tasks

Column Type Notes
id UUID PK
license_id UUID FK → licenses
task_type VARCHAR(30) 'restart', 'announcement', 'command', 'plugin_reload'
task_name VARCHAR(100)
cron_expression VARCHAR(100)
timezone VARCHAR(50)
task_config JSONB Task-specific configuration
is_active BOOLEAN Default true
next_run TIMESTAMPTZ
created_at TIMESTAMPTZ

notifications_config

Column Type Notes
id UUID PK
license_id UUID FK → licenses
discord_webhook_url TEXT Encrypted
discord_enabled BOOLEAN Default false
pushbullet_api_key TEXT Encrypted
pushbullet_enabled BOOLEAN Default false
email_alerts_enabled BOOLEAN Default true
notify_wipe_start BOOLEAN Default true
notify_wipe_complete BOOLEAN Default true
notify_wipe_failed BOOLEAN Default true
notify_server_crash BOOLEAN Default true
notify_server_offline BOOLEAN Default true
notify_store_purchase BOOLEAN Default true
notify_player_report BOOLEAN Default false
created_at TIMESTAMPTZ

chat_logs

Column Type Notes
id UUID PK
license_id UUID FK → licenses
steam_id VARCHAR(20) Player Steam64 ID
player_name VARCHAR(100)
channel VARCHAR(20) 'global', 'team', 'server'
message TEXT
flagged BOOLEAN Default false
flagged_by UUID FK → users, nullable
flag_reason TEXT Nullable
created_at TIMESTAMPTZ Indexed

player_actions

Column Type Notes
id UUID PK
license_id UUID FK → licenses
steam_id VARCHAR(20)
player_name VARCHAR(100)
action_type VARCHAR(20) 'kick', 'ban', 'unban', 'warn', 'note'
reason TEXT
duration_minutes INTEGER Nullable (for timed bans)
performed_by UUID FK → users
created_at TIMESTAMPTZ

server_stats

Column Type Notes
id UUID PK
license_id UUID FK → licenses
player_count INTEGER
max_players INTEGER
fps FLOAT
entity_count INTEGER
uptime_seconds INTEGER
memory_usage_mb INTEGER
recorded_at TIMESTAMPTZ Indexed, partitioned by time

server_stats_hourly

Column Type Notes
id UUID PK
license_id UUID FK → licenses
hour TIMESTAMPTZ Truncated to hour
avg_players FLOAT
max_players INTEGER
avg_fps FLOAT
min_fps FLOAT
avg_entities INTEGER
uptime_percentage FLOAT

public_site_config

Column Type Notes
id UUID PK
license_id UUID FK → licenses
site_enabled BOOLEAN Default true
show_on_status_page BOOLEAN Default false
steam_connect_url VARCHAR(255)
motd TEXT
public_mods TEXT[] Curated list of plugins to show
header_image_url TEXT
theme_color VARCHAR(7) Hex color
custom_css TEXT Nullable
discord_invite_url TEXT
show_player_count BOOLEAN Default true
show_wipe_schedule BOOLEAN Default true
show_wipe_countdown BOOLEAN Default true
show_mod_list BOOLEAN Default true
created_at TIMESTAMPTZ

webstore_config

Column Type Notes
id UUID PK
license_id UUID FK → licenses
is_active BOOLEAN Default false
paypal_client_id TEXT Encrypted
paypal_secret TEXT Encrypted
paypal_mode VARCHAR(10) 'sandbox' or 'live'
store_name VARCHAR(100)
store_description TEXT
currency VARCHAR(3) Default 'USD'
created_at TIMESTAMPTZ

webstore_categories

Column Type Notes
id UUID PK
license_id UUID FK → licenses
category_name VARCHAR(100)
display_order INTEGER
is_active BOOLEAN Default true

webstore_items

Column Type Notes
id UUID PK
license_id UUID FK → licenses
category_id UUID FK → webstore_categories
item_name VARCHAR(100)
description TEXT
price DECIMAL(10,2)
image_url TEXT
item_type VARCHAR(20) 'kit', 'rank', 'currency', 'custom_command'
delivery_config JSONB Commands to execute on delivery
is_active BOOLEAN Default true
created_at TIMESTAMPTZ

webstore_transactions

Column Type Notes
id UUID PK
license_id UUID FK → licenses
item_id UUID FK → webstore_items
buyer_steam_id VARCHAR(20)
buyer_name VARCHAR(100)
amount DECIMAL(10,2)
currency VARCHAR(3)
paypal_transaction_id VARCHAR(100)
status VARCHAR(20) 'pending', 'paid', 'delivered', 'failed', 'refunded'
delivered_at TIMESTAMPTZ Nullable
created_at TIMESTAMPTZ

migration_exports

Column Type Notes
id UUID PK
license_id UUID FK → licenses
export_type VARCHAR(20) 'full', 'config_only', 'store_only'
storage_path TEXT Path to export archive
file_size_bytes BIGINT
created_by UUID FK → users
expires_at TIMESTAMPTZ Auto-delete after 7 days
created_at TIMESTAMPTZ

platform_changelog

Column Type Notes
id UUID PK
version VARCHAR(20)
title VARCHAR(200)
body TEXT Markdown
category VARCHAR(20) 'feature', 'bugfix', 'module', 'security'
published_at TIMESTAMPTZ

module_store

Column Type Notes
id UUID PK
module_slug VARCHAR(50) Unique identifier
module_name VARCHAR(100) Display name
description TEXT
long_description TEXT Markdown
price DECIMAL(10,2) One-time price
price_type VARCHAR(20) 'one_time' or 'monthly'
monthly_price DECIMAL(10,2) Nullable
version VARCHAR(20)
download_path TEXT
thumbnail_url TEXT
screenshots TEXT[]
category VARCHAR(50)
is_active BOOLEAN Default true
created_at TIMESTAMPTZ
updated_at TIMESTAMPTZ

NATS Subject Architecture

All subjects are namespaced by license ID for multi-tenant isolation.

Core Subjects

Subject Direction Payload Purpose
corrosion.{license_id}.heartbeat Plugin → Cloud { timestamp, status, player_count, fps } Plugin health check (every 30s)
corrosion.{license_id}.companion.heartbeat Companion → Cloud { timestamp, status, disk_free, cpu } Companion health check (every 30s)
corrosion.{license_id}.stats Plugin → Cloud { players, fps, entities, uptime, memory } Server metrics (every 60s)
corrosion.{license_id}.players.event Plugin → Cloud { event, steam_id, name, ip } Player join/leave/death events
corrosion.{license_id}.chat Plugin → Cloud { steam_id, name, channel, message } Chat messages for logging
corrosion.{license_id}.console Plugin → Cloud { line, level, timestamp } Server console output stream

Command Subjects (Cloud → Game Server)

Subject Direction Payload Purpose
corrosion.{license_id}.cmd.server Cloud → Companion { action: start/stop/restart } Server process control
corrosion.{license_id}.cmd.console Cloud → Plugin { command } Execute server command
corrosion.{license_id}.cmd.console.response Plugin → Cloud { command, output } Command result
corrosion.{license_id}.cmd.announce Cloud → Plugin { message } In-game broadcast
corrosion.{license_id}.cmd.kick Cloud → Plugin { steam_id, reason } Kick player
corrosion.{license_id}.cmd.ban Cloud → Plugin { steam_id, reason, duration } Ban player
corrosion.{license_id}.cmd.plugin Cloud → Plugin { action: load/unload/reload, name } Plugin management
corrosion.{license_id}.cmd.deliver Cloud → Plugin { steam_id, commands[] } Webstore item delivery

Wipe Subjects

Subject Direction Payload Purpose
corrosion.{license_id}.wipe.prepare Cloud → Plugin { wipe_id, countdown_config } Start pre-wipe countdown
corrosion.{license_id}.wipe.status Plugin → Cloud { wipe_id, step, progress, message } Wipe progress updates
corrosion.{license_id}.wipe.health Plugin → Cloud { map, seed, plugins[], fps, slots } Post-wipe health report

File Operation Subjects (Cloud → Companion)

Subject Direction Payload Purpose
corrosion.{license_id}.files.get Cloud → Companion { path } Read file from server
corrosion.{license_id}.files.put Cloud → Companion { path, download_url } Write file to server
corrosion.{license_id}.files.delete Cloud → Companion { path } Delete file from server
corrosion.{license_id}.files.list Cloud → Companion { path } List directory contents
corrosion.{license_id}.files.response Companion → Cloud { request_id, data/status } File operation result
corrosion.{license_id}.update.steam Cloud → Companion { validate: bool } Trigger SteamCMD update

JetStream Streams

Stream Subjects Retention Purpose
HEARTBEATS corrosion.*.heartbeat, corrosion.*.companion.heartbeat Limits (1 hour) Connection monitoring
STATS corrosion.*.stats Limits (24 hours) Raw metrics for aggregation
EVENTS corrosion.*.players.event Limits (7 days) Player events for analytics
CHAT corrosion.*.chat Limits (30 days) Chat log retention
COMMANDS corrosion.*.cmd.* WorkQueue Reliable command delivery
WIPE_EVENTS corrosion.*.wipe.* Limits (30 days) Wipe audit trail

Wipe Execution Sequence

CRITICAL DESIGN PRINCIPLE: All file system operations are performed by the Corrosion Cloud API — either via the Panel API (AMP/Pterodactyl) or via the Companion Agent (bare metal) — while the server is stopped. The C# plugin handles only in-game operations and post-restart verification.

WIPE SEQUENCE
│
├── 1. PRE-WIPE [Plugin — server is RUNNING]
│   ├── Cloud sends wipe.prepare with countdown config
│   ├── Plugin broadcasts in-game countdown warnings
│   ├── Cloud sends Discord/Pushbullet pre-wipe notification
│   ├── Plugin executes custom pre-wipe commands
│   ├── Plugin kicks all players with configured message
│   ├── Plugin confirms all players disconnected
│   ├── Cloud triggers final server save (via console command)
│   └── Cloud stops server (via Panel API or Companion)
│
├── 2. WIPE EXECUTION [Cloud — server is STOPPED]
│   ├── Create backup (via Panel API or Companion file ops)
│   ├── Delete selected plugin data files per wipe settings
│   ├── Preserve protected plugin data (never_wipe = true)
│   ├── Handle blueprint wipe if configured
│   ├── Rotate to next map in rotation
│   │   ├── Custom map: transfer from Corrosion storage to server
│   │   └── Procedural: update seed/size values
│   ├── Update server.cfg with new map settings
│   └── Log every action to wipe_history
│
├── 3. SERVER RESTART [Cloud]
│   ├── If force wipe: trigger SteamCMD update first
│   ├── Start server (via Panel API or Companion)
│   └── Wait for plugin heartbeat on NATS (confirms server is up)
│
├── 4. POST-WIPE VERIFICATION [Plugin — server is RUNNING]
│   ├── Plugin publishes health report via NATS
│   ├── Cloud evaluates health against expected state
│   ├── Retry up to max_restart_attempts on failure
│   └── If all retries fail + rollback enabled:
│       └── Cloud executes rollback (stop → restore backup → start)
│
├── 5. POST-WIPE NOTIFICATION [Cloud]
│   ├── Update wipe_history record
│   ├── Discord/Pushbullet: wipe complete or failed
│   ├── Send in-game announcement via plugin
│   └── Log final status
│
└── DONE

Steam Update Watcher

Background service in the Corrosion Cloud API that monitors for Rust Dedicated Server updates.

STEAM UPDATE WATCHER
│
├── Poll Steam Web API every 60 seconds
│   └── Check buildid for app 258550 (Rust Dedicated Server)
│
├── On buildid change detected:
│   ├── For each license with auto_update_on_force_wipe = true:
│   │   ├── If force_wipe_eligible: trigger full wipe sequence
│   │   └── If not: trigger update + restart only
│   └── Send notifications to all affected license holders
│
└── Store detected force wipe dates for calendar display

Customer Onboarding Flow (Setup Wizard)

REGISTRATION & SETUP
│
├── 1. REGISTER
│   ├── Customer visits panel.corrosionmgmt.com/register
│   ├── Enters: email, username, password, license key
│   ├── Email verification sent
│   ├── License key validated against CodeFling purchase
│   └── Account created, redirected to setup wizard
│
├── 2. SETUP WIZARD — Step 1: Name Your Server
│   ├── Server display name
│   └── Choose subdomain: _______.corrosionmgmt.com
│       └── Cloudflare API creates DNS record immediately
│
├── 3. SETUP WIZARD — Step 2: How Is Your Server Hosted?
│   ├── Option A: Game Hosting Panel (AMP)
│   │   └── Enter AMP API endpoint + credentials → test connection
│   ├── Option B: Game Hosting Panel (Pterodactyl)
│   │   └── Enter Pterodactyl API endpoint + credentials → test connection
│   └── Option C: Bare Metal / Other
│       └── Download pre-configured companion agent
│
├── 4. SETUP WIZARD — Step 3: Install the Plugin
│   ├── Download WipeManager.cs (pre-configured with license token)
│   ├── Instructions: "Copy to oxide/plugins/ and restart your server"
│   └── Dashboard shows "Waiting for plugin connection..."
│       └── Plugin connects → green checkmark → "Server Online!"
│
├── 5. SETUP WIZARD — Step 4: Server Template (Optional)
│   ├── What kind of server are you running?
│   │   ├── Vanilla
│   │   ├── 2x Modded
│   │   ├── 5x Modded
│   │   ├── 10x Modded
│   │   ├── PvE
│   │   ├── Creative/Build
│   │   └── Custom (skip templates)
│   ├── Selected template auto-installs recommended plugins from uMod
│   └── Plugins installed with sensible default configs
│
├── 6. SETUP WIZARD — Step 5: Set Up Your First Wipe Schedule
│   ├── How often do you wipe? (weekly/bi-weekly/monthly)
│   ├── What day and time?
│   ├── Wipe blueprints? (yes/no)
│   └── Creates default wipe profile and schedule
│
└── 7. DONE → Dashboard
    └── "Your server is live at servername.corrosionmgmt.com!"

Subdomain & Routing Architecture

URL Structure

URL Purpose
panel.corrosionmgmt.com Main platform login and dashboard
{servername}.corrosionmgmt.com Customer's public server site
{servername}.corrosionmgmt.com/store Customer's webstore (if enabled)
status.corrosionmgmt.com Public status page (opted-in servers)
api.corrosionmgmt.com REST API endpoint
nats.corrosionmgmt.com NATS cluster endpoint (plugin/companion connections)

Subdomain Provisioning

On license registration:

  1. Customer chooses subdomain during setup wizard
  2. Corrosion API calls Cloudflare API to create CNAME/A record
  3. Nginx config dynamically routes based on subdomain → license_id lookup
  4. SSL handled automatically by Cloudflare

For custom domains:

  1. Customer adds CNAME record pointing their domain to {servername}.corrosionmgmt.com
  2. Customer enters custom domain in dashboard settings
  3. Corrosion API updates Cloudflare and Nginx routing
  4. SSL provisioned via Cloudflare

Security Model

Authentication & Authorization

  • User registration with email verification
  • Argon2 password hashing
  • JWT access tokens (15 min expiry) + refresh tokens (7 days)
  • TOTP 2FA with encrypted backup codes
  • RBAC enforced on every API endpoint
  • License ownership verified on all license-scoped operations

Data Isolation

  • Every database query filters by license_id
  • NATS subjects namespaced by license_id — subscriptions scoped per tenant
  • File storage paths prefixed by license_id
  • API middleware validates license ownership before any operation

Secrets Management

  • Panel API keys encrypted at rest (AES-256-GCM)
  • Discord webhook URLs encrypted at rest
  • Pushbullet API keys encrypted at rest
  • PayPal credentials encrypted at rest
  • Companion agent tokens are unique per license, rotatable from dashboard

Plugin & Companion Authentication

  • Plugin authenticates to NATS with license-specific token
  • Companion authenticates to NATS with separate companion-specific token
  • Both tokens are revocable from the dashboard
  • License validation on plugin startup and periodic check-in (every 6 hours)
  • Invalid/expired license → plugin enters read-only mode (stats only, no commands)

Crash Recovery System

CRASH DETECTION
│
├── Plugin heartbeat stops (no message for 90 seconds)
│   └── Cloud marks server as "unresponsive"
│
├── Companion heartbeat confirms server process is dead
│   └── OR Panel API confirms server is stopped
│
├── If crash_recovery_enabled = true:
│   ├── Attempt 1: Restart server
│   │   └── Wait for plugin heartbeat (timeout: 120s)
│   ├── Attempt 2: Restart server
│   │   └── Wait for plugin heartbeat (timeout: 120s)
│   ├── Attempt 3: Restart server
│   │   └── Wait for plugin heartbeat (timeout: 120s)
│   └── All attempts failed:
│       ├── Mark server as "crashed — manual intervention required"
│       └── Send critical alert (Discord + Pushbullet + Email)
│
├── Cooldown: No more auto-recovery for crash_recovery_cooldown_minutes
│   └── Prevents restart loops from corrupted data
│
└── All crash events logged with timestamps and attempt details

Server Migration System

Export

Customer triggers export from dashboard. System packages:

  • All server configuration (server_config, config_overrides)
  • All wipe profiles and schedules
  • Plugin registry with configurations
  • Map rotation settings (not map files — too large)
  • Webstore categories and items (not transaction history)
  • Public site configuration
  • Game admin list
  • Notification settings
  • RBAC roles (custom only)

Exported as encrypted JSON archive. Download link valid for 7 days.

Import

Customer registers new license, runs setup wizard, then imports:

  • Upload export archive
  • System validates and maps data to new license_id
  • Customer reviews what will be imported
  • One-click apply
  • Map files must be re-uploaded separately

PHASE 1 — Foundation & Core Platform

Goal: Customer buys the plugin, registers, connects their server, and sees it live on the dashboard with basic management capabilities. Prove the platform works end-to-end.

Success metric: A customer with zero technical knowledge beyond "install this plugin" can register, connect their server, and manage it from the web within 15 minutes.

Phase 1 Deliverables

Platform Infrastructure

  • Corrosion Cloud deployment (Docker Compose: PostgreSQL, NATS, Rust API, Nginx)
  • panel.corrosionmgmt.com — main web application
  • Cloudflare DNS API integration for subdomain provisioning
  • Nginx dynamic subdomain routing
  • SSL via Cloudflare (wildcard cert for *.corrosionmgmt.com)

Registration & Licensing

  • User registration with email verification
  • License key validation and activation
  • Login with JWT auth
  • TOTP 2FA setup and verification
  • License check-in endpoint for plugin validation

Setup Wizard

  • Step 1: Name server + choose subdomain
  • Step 2: Select connection type (AMP / Pterodactyl / Bare Metal)
  • Step 3: Panel API configuration with connection test OR companion agent download
  • Step 4: Plugin download (pre-configured with license token) + connection verification
  • Step 5: Server template selection with auto plugin install from uMod
  • Step 6: First wipe schedule creation
  • Wizard completion → redirect to dashboard

uMod Plugin (C#)

  • NATS outbound connection with auto-reconnect
  • License token authentication
  • Periodic license validation (every 6 hours)
  • Heartbeat publishing (every 30 seconds)
  • Server stats publishing (players, FPS, entities, uptime, memory)
  • Player join/leave event publishing
  • Chat message publishing
  • Console output streaming
  • Command subscription and execution
  • Player kick/ban execution
  • In-game announcement broadcasting
  • Plugin list reporting (name, version, loaded state)
  • Wipe countdown message broadcasting
  • Post-wipe health report publishing
  • Configurable via license token only (no manual config editing)

Companion Agent (Go)

  • NATS outbound connection with auto-reconnect
  • Pre-configured download from dashboard (license token + NATS endpoint baked in)
  • Server process management (start, stop, restart)
  • Server process monitoring (detect crashes)
  • File system operations (read, write, delete, list)
  • SteamCMD update execution
  • Self-update capability
  • Runs as system service (systemd / Windows service)

Panel Adapters

  • PanelAdapter trait definition
  • AMP adapter: connect, test, discover server, start, stop, restart, file ops, send command
  • Pterodactyl adapter: same interface
  • Panel connection health monitoring

Dashboard — Server Management

  • Server status overview (online/offline, player count, FPS, uptime)
  • Start / Stop / Restart server
  • Live server console (real-time via NATS WebSocket)
  • Console command input with history
  • Server configuration editor (server.cfg key-value editing from web)
  • Scheduled restarts (cron-based with timezone)
  • Crash recovery (auto-restart with configurable attempts and cooldown)

Dashboard — Player Management

  • Live player list (name, SteamID, playtime, ping)
  • Kick player with reason
  • Ban player with reason and duration
  • Unban player
  • Ban list management
  • In-game admin registration (enter SteamID, select level, apply)

Dashboard — Plugin Management

  • View installed plugins with version info
  • Load / Unload / Reload plugins
  • uMod plugin browser (search and install from uMod)
  • Plugin configuration editing from web UI (JSON editor with save)
  • Plugin data wipe settings (per-plugin, per-wipe-type toggles)

Dashboard — Auto-Wiper

  • Wipe profile creation and management
  • Pre-wipe sequence configuration (toggleable steps)
  • Post-wipe verification configuration (toggleable checks)
  • Wipe schedule creation (cron with timezone, wipe type)
  • Wipe calendar view (all scheduled wipes + force wipe dates)
  • Facepunch force wipe conflict detection
  • SteamUpdateWatcher (buildid polling, auto-trigger)
  • Manual wipe trigger with confirmation
  • Dry-run / preview mode
  • Wipe history with detailed execution logs
  • Pre-wipe backup (via panel/companion)
  • One-click rollback from dashboard

Dashboard — Map Management

  • Map library (upload, metadata, thumbnails)
  • Map rotation configuration (ordered list per server)
  • Procedural seed management
  • Signed download URLs for plugin map retrieval (15 min expiry)
  • Checksum verification

Dashboard — Notifications

  • Discord webhook configuration and test
  • Pushbullet configuration and test
  • Email alerts (server crash, wipe failed)
  • Per-event notification toggles

Dashboard — Team Management (RBAC)

  • Invite team members by email
  • Assign roles to team members
  • Default system roles (Owner, Head Admin, Moderator, Viewer)
  • Clone and customize roles
  • Permission enforcement on all UI elements and API endpoints

Dashboard — Chat Log & Moderation

  • Real-time chat feed from server
  • Chat history with search
  • Flag messages with reason
  • Quick-action: kick/ban from chat log entry

Public Server Site (servername.corrosionmgmt.com)

  • Server info display (name, description, header image)
  • Steam connect link (clickable)
  • MOTD display
  • Mod/plugin list (curated by admin)
  • Wipe schedule display
  • Next wipe countdown timer (live via NATS WebSocket)
  • Live player count
  • Discord invite link
  • Configurable from dashboard (toggle sections on/off, colors, images)

Platform Features

  • Changelog / update feed in dashboard
  • Server migration export
  • Server migration import

PHASE 2 — Analytics & Intelligence

Goal: Data-driven insights that make admins smarter and look incredible in screenshots. This is the CodeFling differentiator.

Depends on: Phase 1 complete. NATS stats stream already collecting data.

Phase 2 Deliverables

Player Analytics

  • Player count tracking over time (hourly, daily, weekly graphs)
  • Peak player tracking per day/week/month
  • Player retention after wipe (what percentage return within 24h, 48h, 72h)
  • Player count correlation with wipe timing
  • Unique player counts (SteamID-based)
  • Average session duration trends
  • New vs returning player ratio
  • Player join/leave heatmap (time of day patterns)

Wipe Analytics

  • Wipe success/failure rate over time
  • Average wipe execution duration
  • Wipe-to-peak-population time (how fast server fills post-wipe)
  • Population curve by wipe cycle (day 1 vs day 2 vs day 3 pattern)
  • Optimal wipe timing recommendations based on historical data
  • "Your best wipe day is X at Y" summary card

Server Performance Analytics

  • FPS tracking over time (trend graphs)
  • Entity count growth over wipe cycle
  • FPS vs player count correlation
  • Memory usage trends
  • Performance degradation alerts (FPS below configurable threshold)

Map Analytics

  • Player count per map (which maps drive the most players)
  • Average population per map across wipe cycles
  • Map rotation effectiveness scoring

Dashboard Visualizations (Apache ECharts)

  • Interactive charts with date range selectors
  • Server comparison views (if customer has multiple licenses)
  • Summary insight cards
  • Real-time updating charts
  • Exportable chart images (PNG download for CodeFling screenshots / social media)

Alerting

  • Discord/Pushbullet alerts for anomalies (population drop > X%, FPS below threshold)
  • Configurable alert thresholds
  • Alert history log

Data Infrastructure

  • Aggregation service: raw stats → hourly → daily rollups
  • Data retention policies (raw: 7 days, hourly: 90 days, daily: 1 year)
  • Historical data CSV export

PHASE 3 — Status Page

Goal: Public status page showcasing all opted-in servers. Free marketing for the platform.

Depends on: Phase 1 complete. Heartbeat and stats data already flowing.

Phase 3 Deliverables

Status Page (status.corrosionmgmt.com)

  • Public page listing all servers with show_on_status_page = true
  • Per-server: name, status (online/offline/degraded), player count, uptime percentage
  • Per-server: basic config display (map size, max players, wipe schedule)
  • Overall platform health summary
  • Uptime history graph per server (24h, 7d, 30d)
  • Incident history (downtime events with duration)
  • Real-time updates via NATS WebSocket
  • Mobile-responsive design
  • "Powered by Corrosion" branding with link to platform

PHASE 4 — Module Store & First Modules

Goal: Launch the module marketplace and ship the first paid add-on modules. Prove the module ecosystem works.

Depends on: Phase 1 complete. Plugin infrastructure supports module loading.

Phase 4 Deliverables

Module Store Infrastructure

  • Module store page in dashboard (browse, preview, purchase)
  • Module purchase flow (payment processing — details TBD)
  • License key module activation (purchased modules tied to license)
  • Module auto-installation (download module plugin, deploy to server via companion/panel)
  • Module update system (new versions auto-detected, one-click update)
  • Module configuration in dashboard (per-module settings UI)

Loot Manager Module ($9.99)

  • Visual loot table editor (drag-and-drop items, set spawn rates, quantities)
  • Container browser (every crate type, barrel, NPC drop, Bradley, Heli)
  • Loot profiles ("2x Vanilla", "10x Modded", "Event Weekend")
  • One-click profile switching (no restart required)
  • Import/export loot profiles
  • Skin selection from visual gallery
  • Probability distribution preview
  • Wipe-aware loot rotation (swap loot profiles automatically on wipe day)
  • Scheduled loot changes (generous day 1, tighter day 5)

Future Module Pipeline (not built in Phase 4, but planned)

  • Event plugins (convoy-style PvE events)
  • Economics/currency system
  • Kits manager
  • Teleportation system
  • Home/base management
  • Clan/team management
  • Voting rewards
  • Custom crafting recipes

PHASE 5 — Integrated Webstore

Goal: Tebex alternative where server owners monetize their community. $10/month recurring revenue per customer.

Depends on: Phase 1 complete (public site), Phase 4 complete (module delivery infrastructure).

Phase 5 Deliverables

Webstore Setup

  • Webstore add-on activation ($10/month subscription via PayPal)
  • PayPal Business account connection (client ID + secret)
  • Sandbox mode for testing before going live
  • Store configuration (name, description, currency)

Store Management (Dashboard)

  • Category management (create, reorder, toggle)
  • Item management (create, edit, pricing, images)
  • Item types: kits, ranks, in-game currency, custom commands
  • Delivery configuration (server commands to execute on purchase)
  • Item preview (see what the customer sees)

Customer-Facing Store (servername.corrosionmgmt.com/store)

  • Store page integrated into public server site
  • Category browsing
  • Item detail pages with images and descriptions
  • Cart and checkout flow
  • PayPal payment processing (money goes directly to server owner)
  • SteamID verification (buyer enters their Steam ID)
  • Order confirmation page

Delivery System

  • PayPal IPN/webhook listener
  • Payment verification
  • Automatic in-game delivery via NATS → Plugin command execution
  • Delivery for online players: immediate
  • Delivery for offline players: queued, delivered on next join
  • Delivery confirmation logging

Revenue Dashboard

  • Transaction history with filters
  • Revenue summary (daily, weekly, monthly)
  • Top-selling items
  • Purchase activity graph
  • Transaction status tracking (pending, paid, delivered, failed)

Store Notifications

  • Discord notification on purchase
  • Pushbullet notification on purchase
  • Email receipt to buyer (optional)
  • In-game announcement on purchase (optional, "Player X just bought VIP!")

PHASE 6 — B2B Site Licensing

Goal: Hosting companies integrate Corrosion into their platform as a value-add for their Rust customers. High-value recurring B2B revenue.

Depends on: All previous phases stable and proven in production.

Phase 6 Deliverables

B2B Infrastructure

  • Organization/tenant model (hosting company as parent org)
  • Bulk license provisioning (hosting company generates licenses for their customers)
  • White-label options (custom branding, custom domain for the panel)
  • Usage-based billing (per-active-server-month)
  • B2B admin dashboard (hosting company sees all their customer servers)
  • Custom panel adapter development support (hosting company's proprietary panel)

Integration

  • API for hosting company to provision/deprovision servers
  • SSO integration (customer logs into hosting company panel → auto-authenticated in Corrosion)
  • Embedded dashboard option (iframe or SDK for embedding in hosting company panel)
  • Custom module distribution (hosting company can offer their own modules)

Infrastructure Scaling Notes

Phase 1 (Single-server deployment)

# Docker Compose — suitable for initial launch
services:
  postgres:
    image: postgres:16-alpine
    volumes: [pg_data:/var/lib/postgresql/data]

  nats:
    image: nats:latest
    command: [--jetstream, --store_dir, /data, --config, /etc/nats/nats.conf]
    volumes: [nats_data:/data]
    ports: [4222:4222, 9222:9222]  # Client + WebSocket

  api:
    build: ./backend
    environment:
      DATABASE_URL: postgres://...
      NATS_URL: nats://nats:4222
      CLOUDFLARE_API_TOKEN: ${CF_TOKEN}
      CLOUDFLARE_ZONE_ID: ${CF_ZONE}
      ENCRYPTION_KEY: ${ENC_KEY}

  nginx:
    image: nginx:alpine
    ports: [80:80, 443:443]
    volumes:
      - ./frontend/dist:/usr/share/nginx/html
      - ./nginx.conf:/etc/nginx/nginx.conf

Scaling Milestones

Customers Infrastructure Change
150 Single Docker Compose on one VPS
50200 Separate database server, NATS on dedicated node
200500 NATS cluster (3 nodes), read replicas for PostgreSQL
500+ Kubernetes, horizontal API scaling, managed PostgreSQL

The architecture supports all of these transitions without application code changes. NATS clustering is transparent to clients. Database connection pooling handles read replicas. API is stateless (JWT + NATS) so it scales horizontally.


Revenue Projections (Conservative)

Milestone Customers Monthly Revenue
Launch + 6 months 50 licenses ($50 each) $2,500 one-time + module sales
Year 1 200 licenses ~$10,000 one-time + $500/mo webstore subscriptions
Year 2 500 licenses, 2 hosting companies ~$25,000 one-time + $2,000/mo recurring
Year 3 1,000+ licenses, 5 hosting companies Recurring revenue exceeds one-time

These are conservative. The Convoy plugin sold 29,000 copies at $35. The Rust server market is large and underserved for management tooling.


End of specification. To begin implementation, say: "Build Phase X"