araxia-trinity-launcher/
├── src/
│ ├── main/
│ │ ├── index.ts # Electron main process
│ │ ├── tunnelManager.ts # SSH tunnel management
│ │ └── configManager.ts # Configuration handling
│ ├── renderer/
│ │ ├── App.tsx # Main React component
│ │ ├── components/ # React components
│ │ │ ├── TunnelStatus.tsx
│ │ │ ├── ConfigEditor.tsx
│ │ │ └── ServerSelector.tsx
│ │ └── styles/ # TailwindCSS styles
│ └── shared/
│ ├── types.ts # Shared TypeScript types
│ └── ipc.ts # IPC message definitions
├── Dockerfile # Build environment
├── docker-compose.yml # Docker orchestration
├── package.json # Dependencies
├── tsconfig.json # TypeScript config
├── araxiatrinity.yml # Example config
└── docs/
├── PLAN.md
├── ARCHITECTURE.md
├── DECISIONS.md
└── PROGRESS.md
- Window management
- IPC message handling
- Lifecycle management
- Delegate tunneling to TunnelManager
- Establish SSH connections
- Create port forwarding tunnels
- Monitor tunnel health
- Implement reconnection logic with backoff
- Emit status updates to renderer
- Load/parse
araxiatrinity.yml - Validate configuration
- Watch for file changes
- Provide config to TunnelManager
- Display server list
- Show tunnel status (connected/disconnected/connecting)
- Display error messages
- Allow config editing
- Real-time status updates via IPC
User selects server in UI
↓
Renderer sends IPC message to Main
↓
ConfigManager loads server config
↓
TunnelManager creates SSH connection
↓
TunnelManager establishes port forwards
↓
TunnelManager emits status updates
↓
Main sends status via IPC to Renderer
↓
UI updates with tunnel status
- Load server config from
araxiatrinity.yml - Establish SSH connection with private key auth
- For each tunnel:
- Create local listening socket on localhost:PORT
- Forward to remote server:REMOTE_PORT
- Monitor connection health
- On disconnect: retry with exponential backoff (1s, 2s, 4s, 8s, 16s, max 60s)
- Connection refused → show error, retry
- Auth failure → show error, don't retry
- Network timeout → retry with backoff
- Tunnel failure → attempt to re-establish
tunnel:status-update- Tunnel connection status changedtunnel:error- Tunnel error occurredconfig:loaded- Configuration loaded successfully
tunnel:connect- Connect to servertunnel:disconnect- Disconnect from serverconfig:get- Request current configconfig:save- Save new config
- Private keys stored in user's home directory (not in config file)
- SSH key path in config is relative to user home
- No credentials logged or stored in app
- Config file should have restricted permissions (0600)