- Move all macOS-specific code from root to mac/ directory - Move app icons and assets to dedicated assets/ directory - Update GitHub workflows for new structure - Consolidate documentation files - Clean up root directory for better multi-platform organization
16 KiB
VibeTunnel API Analysis
Summary
This document analyzes the API endpoints implemented across all VibeTunnel servers, what the web client expects, and identifies critical differences, implementation errors, and semantic inconsistencies. The analysis covers:
- Node.js/TypeScript Server (
web/src/server.ts) - ✅ Complete - Rust API Server (
tty-fwd/src/api_server.rs) - ✅ Complete - Go Server (
linux/pkg/api/server.go) - ✅ Complete - Swift Server (
VibeTunnel/Core/Services/TunnelServer.swift) - ✅ Complete - Web Client (
web/src/client/) - Expected API calls and formats
Note: Rust HTTP Server (tty-fwd/src/http_server.rs) is excluded as it's a utility component for static file serving, not a standalone API server.
API Endpoint Comparison
| Endpoint | Client Expects | Node.js | Rust API | Go | Swift | Status |
|---|---|---|---|---|---|---|
GET /api/health |
✅ Used | ✅ | ✅ | ✅ | ✅ | ✅ Complete |
GET /api/sessions |
✅ Critical | ✅ | ✅ | ✅ | ✅ | ✅ Complete |
POST /api/sessions |
✅ Critical | ✅ | ✅ | ✅ | ✅ | ✅ Complete |
DELETE /api/sessions/:id |
✅ Critical | ✅ | ✅ | ✅ | ✅ | ✅ Complete |
DELETE /api/sessions/:id/cleanup |
❌ Not used | ✅ | ✅ | ✅ | ✅ | ✅ Complete |
GET /api/sessions/:id/stream |
✅ Critical SSE | ✅ | ✅ | ✅ | ✅ | ✅ Complete |
GET /api/sessions/:id/snapshot |
✅ Critical | ✅ | ✅ | ✅ | ✅ | ✅ Complete |
POST /api/sessions/:id/input |
✅ Critical | ✅ | ✅ | ✅ | ✅ | ✅ Complete |
POST /api/sessions/:id/resize |
✅ Critical | ✅ | ❌ | ✅ | ❌ | ⚠️ Missing in Rust API & Swift |
POST /api/cleanup-exited |
✅ Used | ✅ | ✅ | ✅ | ✅ | ✅ Complete |
GET /api/fs/browse |
✅ Critical | ✅ | ✅ | ✅ | ✅ | ✅ Complete |
POST /api/mkdir |
✅ Used | ✅ | ✅ | ✅ | ✅ | ✅ Complete |
GET /api/sessions/multistream |
❌ Not used | ✅ | ✅ | ✅ | ✅ | ✅ Complete |
GET /api/pty/status |
❌ Not used | ✅ | ❌ | ❌ | ❌ | ℹ️ Node.js Only |
GET /api/test-cast |
❌ Not used | ✅ | ❌ | ❌ | ❌ | ℹ️ Node.js Only |
POST /api/ngrok/start |
❌ Not used | ❌ | ❌ | ✅ | ✅ | ℹ️ Go/Swift Only |
POST /api/ngrok/stop |
❌ Not used | ❌ | ❌ | ✅ | ✅ | ℹ️ Go/Swift Only |
GET /api/ngrok/status |
❌ Not used | ❌ | ❌ | ✅ | ✅ | ℹ️ Go/Swift Only |
Web Client API Requirements
Based on analysis of web/src/client/, the client requires these endpoints to function:
Critical Endpoints (App breaks without these):
GET /api/sessions- Session list (polled every 3s)POST /api/sessions- Session creationDELETE /api/sessions/:id- Session terminationGET /api/sessions/:id/stream- SSE streaming (real-time terminal output)GET /api/sessions/:id/snapshot- Terminal snapshot for initial displayPOST /api/sessions/:id/input- Keyboard/mouse input to terminalPOST /api/sessions/:id/resize- Terminal resize (debounced, 250ms)GET /api/fs/browse- Directory browsing for session creationPOST /api/cleanup-exited- Cleanup exited sessions
Expected Request/Response Formats by Client:
Session List Response (GET /api/sessions):
Session[] = {
id: string;
command: string;
workingDir: string;
name?: string;
status: 'running' | 'exited';
exitCode?: number;
startedAt: string;
lastModified: string;
pid?: number;
waiting?: boolean; // Node.js only
width?: number; // Go only
height?: number; // Go only
}[]
Session Creation Request (POST /api/sessions):
{
command: string[]; // Required: parsed command array
workingDir: string; // Required: working directory path
name?: string; // Optional: session name
spawn_terminal?: boolean; // Used by Rust API/Swift (always true)
width?: number; // Used by Go (default: 120)
height?: number; // Used by Go (default: 30)
}
Session Input Request (POST /api/sessions/:id/input):
{
text: string; // Input text or special keys: 'enter', 'escape', 'arrow_up', etc.
}
Terminal Resize Request (POST /api/sessions/:id/resize):
{
width: number; // Terminal columns
height: number; // Terminal rows
}
Major Implementation Differences
1. Server Implementation Status
All API servers are fully functional and complete:
Rust API Server (tty-fwd/src/api_server.rs):
- ✅ Purpose: Full terminal session management server
- ✅ APIs: Complete implementation of all session endpoints
- ✅ Features: Authentication, SSE streaming, file system APIs
- ❌ Missing: Terminal resize endpoint only
Architecture Note: The Rust HTTP Server (tty-fwd/src/http_server.rs) is a utility component for static file serving and HTTP/SSE primitives, not a standalone API server. It's correctly excluded from this analysis.
2. CRITICAL: Missing Terminal Resize API
Impact: ⚠️ Client expects this endpoint and calls it continuously
Affected: Rust API Server, Swift Server
Endpoints: POST /api/sessions/:id/resize
Client Behavior:
- Calls resize endpoint on window resize events (debounced 250ms)
- Tracks last sent dimensions to avoid redundant requests
- Logs warnings on failure but continues operation
- Will cause 404 errors on Rust API and Swift servers
Working Implementation Analysis:
// Node.js Implementation (✅ Complete)
app.post('/api/sessions/:sessionId/resize', async (req, res) => {
const { width, height } = req.body;
// Validation: 1-1000 range
if (width < 1 || height < 1 || width > 1000 || height > 1000) {
return res.status(400).json({ error: 'Width and height must be between 1 and 1000' });
}
ptyService.resizeSession(sessionId, width, height);
});
// Go Implementation (✅ Complete)
func (s *Server) handleResizeSession(w http.ResponseWriter, r *http.Request) {
// Includes validation for positive integers
if req.Width <= 0 || req.Height <= 0 {
http.Error(w, "Width and height must be positive integers", http.StatusBadRequest)
return
}
}
Missing in:
- Rust API Server: No resize endpoint
- Swift Server: No resize endpoint
3. Session Creation Request Format Inconsistencies
Node.js Format:
{
"command": ["bash", "-l"],
"workingDir": "/path/to/dir",
"name": "session_name"
}
Rust API Format:
{
"command": ["bash", "-l"],
"workingDir": "/path/to/dir",
"term": "xterm-256color",
"spawn_terminal": true
}
Go Format:
{
"name": "session_name",
"command": ["bash", "-l"],
"workingDir": "/path/to/dir",
"width": 120,
"height": 30
}
Swift Format:
{
"command": ["bash", "-l"],
"workingDir": "/path/to/dir",
"term": "xterm-256color",
"spawnTerminal": true
}
Issues:
- Inconsistent field naming (
workingDirvsworking_dir) - Different optional fields across implementations
- Terminal dimensions only in Go implementation
4. Authentication Implementation Differences
| Server | Auth Method | Details |
|---|---|---|
| Node.js | None | No authentication middleware |
| Rust API | Basic Auth | Configurable password, realm="tty-fwd" |
| Go | Basic Auth | Fixed username "admin", realm="VibeTunnel" |
| Swift | Basic Auth | Lazy keychain-based password loading |
Problems:
- Different realm names (
"tty-fwd"vs"VibeTunnel") - Inconsistent username requirements
- Node.js completely lacks authentication
5. Session Input Handling Inconsistencies
Special Key Mappings Differ:
Node.js:
const specialKeys = [
'arrow_up', 'arrow_down', 'arrow_left', 'arrow_right',
'escape', 'enter', 'ctrl_enter', 'shift_enter'
];
Go:
specialKeys := map[string]string{
"arrow_up": "\x1b[A",
"arrow_down": "\x1b[B",
"arrow_right": "\x1b[C",
"arrow_left": "\x1b[D",
"escape": "\x1b",
"enter": "\r", // CR, not LF
"ctrl_enter": "\r", // CR for ctrl+enter
"shift_enter": "\x1b\x0d", // ESC + CR for shift+enter
}
Swift:
let specialKeys = [
"arrow_up", "arrow_down", "arrow_left", "arrow_right",
"escape", "enter", "ctrl_enter", "shift_enter"
]
Issues:
- Go provides explicit escape sequence mappings
- Node.js and Swift rely on PTY service for mapping
- Different enter key handling (
\rvs\n)
6. Session Response Format Inconsistencies
Node.js Session List Response:
{
"id": "session-123",
"command": "bash -l",
"workingDir": "/home/user",
"name": "my-session",
"status": "running",
"exitCode": null,
"startedAt": "2024-01-01T00:00:00Z",
"lastModified": "2024-01-01T00:01:00Z",
"pid": 1234,
"waiting": false
}
Rust API Session List Response:
{
"id": "session-123",
"command": "bash -l",
"workingDir": "/home/user",
"status": "running",
"exitCode": null,
"startedAt": "2024-01-01T00:00:00Z",
"lastModified": "2024-01-01T00:01:00Z",
"pid": 1234
}
Differences:
- Node.js includes
nameandwaitingfields - Rust API missing these fields
- Field naming inconsistencies across servers
7. File System API Response Format Differences
Node.js FS Browse Response:
{
"absolutePath": "/home/user",
"files": [{
"name": "file.txt",
"created": "2024-01-01T00:00:00Z",
"lastModified": "2024-01-01T00:01:00Z",
"size": 1024,
"isDir": false
}]
}
Go FS Browse Response:
[{
"name": "file.txt",
"path": "/home/user/file.txt",
"is_dir": false,
"size": 1024,
"mode": "-rw-r--r--",
"mod_time": "2024-01-01T00:01:00Z"
}]
Issues:
- Different response structures (object vs array)
- Different field names (
isDirvsis_dir) - Go includes additional fields (
path,mode) - Missing
createdfield in Go
8. Error Response Format Inconsistencies
Node.js Error Format:
{
"error": "Session not found"
}
Rust API Error Format:
{
"success": null,
"message": null,
"error": "Session not found",
"sessionId": null
}
Go Simple Error:
"Session not found" (plain text)
Problems:
- Inconsistent error response structures
- Some servers use structured responses, others plain text
- Different HTTP status codes for same error conditions
Critical Security Issues
1. Inconsistent Authentication
- Node.js server has NO authentication
- Different authentication realms across servers
- No standardized credential management
2. Path Traversal Vulnerabilities
Different path sanitization across servers:
Node.js (Proper):
function resolvePath(inputPath, fallback) {
if (inputPath.startsWith('~')) {
return path.join(os.homedir(), inputPath.slice(1));
}
return path.resolve(inputPath);
}
Go (Basic):
// Expand ~ in working directory
if cwd != "" && cwd[0] == '~' {
// Simple tilde expansion
}
Missing Features by Server
Node.js Missing:
- ngrok tunnel management
- Terminal dimensions in session creation
Rust HTTP Server Missing:
- ALL API endpoints (only static file serving)
Rust API Server Missing:
- Terminal resize functionality
- ngrok tunnel management
Go Server Missing:
- None (most complete implementation)
Swift Server Missing:
- Terminal resize functionality
Recommendations
1. Immediate Fixes Required
-
Standardize Request/Response Formats:
- Use consistent field naming (camelCase vs snake_case)
- Standardize error response structure
- Align session creation request formats
-
Implement Missing Critical APIs:
- Add resize endpoint to Rust API and Swift servers
- Add authentication to Node.js server
- Deprecate or complete Rust HTTP server
-
Fix Security Issues:
- Standardize authentication realms
- Implement consistent path sanitization
- Add proper input validation
2. Semantic Alignment
-
Session Management:
- Standardize session ID generation
- Align session status values
- Consistent PID handling
-
Special Key Handling:
- Standardize escape sequence mappings
- Consistent enter key behavior
- Align special key names
-
File System Operations:
- Standardize directory listing format
- Consistent path resolution
- Align file metadata fields
3. Architecture Improvements
-
API Versioning:
- Implement
/api/v1/prefix - Version all endpoint contracts
- Plan backward compatibility
- Implement
-
Error Handling:
- Standardize HTTP status codes
- Consistent error response format
- Proper error categorization
-
Documentation:
- OpenAPI/Swagger specifications
- API contract testing
- Cross-server compatibility tests
Rust Server Architecture Analysis
After deeper analysis, the Rust servers have a clear separation of concerns:
Rust Session Management (tty-fwd/src/sessions.rs)
Complete session management implementation:
list_sessions()- ✅ Full session listing with status checkingsend_key_to_session()- ✅ Special key input (arrow keys, enter, escape, etc.)send_text_to_session()- ✅ Text input to sessionssend_signal_to_session()- ✅ Signal sending (SIGTERM, SIGKILL, etc.)cleanup_sessions()- ✅ Session cleanup with PID validationspawn_command()- ✅ New session creation- ✅ Process monitoring and zombie reaping
- ✅ Pipe-based I/O with timeout protection
Rust Protocol Support (tty-fwd/src/protocol.rs)
Complete streaming and protocol support:
- ✅ Asciinema format reading/writing
- ✅ SSE streaming with
StreamingIterator - ✅ Terminal escape sequence processing
- ✅ Real-time event streaming with file monitoring
- ✅ UTF-8 handling and buffering
Main Binary (tty-fwd/src/main.rs)
Complete CLI interface:
- ✅ Session listing:
--list-sessions - ✅ Key input:
--send-key <key> - ✅ Text input:
--send-text <text> - ✅ Process control:
--signal,--stop,--kill - ✅ Cleanup:
--cleanup - ✅ HTTP Server:
--serve <addr>(launches API server)
Key Finding: tty-fwd --serve launches the API server, not the HTTP server.
Corrected Assessment
Rust Implementation Status: ✅ COMPLETE AND CORRECT
All servers are properly implemented:
- Node.js Server: ✅ Complete - PTY service wrapper
- Rust HTTP Server: ✅ Complete - Utility HTTP server (not meant for direct client use)
- Rust API Server: ✅ Complete - Full session management server
- Go Server: ✅ Complete - Native session management
- Swift Server: ✅ Complete - Wraps tty-fwd binary
Remaining Issues (Reduced Severity):
- Terminal Resize Missing (Rust API, Swift) - Client compatibility issue
- Request/Response Format Inconsistencies - Client needs adaptation
- Authentication Differences - Security/compatibility issue
Updated Recommendations
1. Immediate Priority: Terminal Resize
Add resize endpoint to Rust API and Swift servers:
// Rust API Server needs:
POST /api/sessions/{sessionId}/resize
2. Response Format Standardization
Align session list responses across all servers for client compatibility.
3. Authentication Standardization
Implement consistent Basic Auth across all servers.
Conclusion
Previous Assessment Correction: The Rust servers are fully functional and complete. The HTTP server is correctly designed as a utility component, while the API server provides full session management.
Current Status: 4 out of 5 servers are client-compatible. Only missing terminal resize in Rust API and Swift servers.
Impact: Much lower than initially assessed. The main issues are:
- Terminal resize functionality - causes 404s but client continues working
- Response format variations - may cause field mapping issues
- Authentication inconsistencies - different security models
The project has solid API coverage across all platforms with minor compatibility issues rather than fundamental implementation gaps.