Files
onebox/.claude/CLAUDE.md
2025-11-24 19:52:35 +00:00

5.0 KiB

Onebox Development Notes

⚠️ CRITICAL DEVELOPMENT RULES ⚠️

NEVER GUESS - ALWAYS READ THE ACTUAL CODE

FUCKING ALWAYS look at the dependency actual code. Don't start fucking guessing stuff.

run "pnpm run watch" when starting to do stuff, so the UI gets recompiled and the server automatically restarts on file changes.

When working with any dependency:

  1. READ the actual source code in node_modules/ or check the package documentation
  2. CHECK the exact API - don't assume based on similar libraries
  3. VERIFY method names, return types, and property structures before using them
  4. TEST with the actual implementation - APIs change between versions

Common mistakes to avoid:

  • Assuming API structure based on similar libraries
  • Guessing method names or property paths
  • Using outdated documentation without checking current version
  • Read the actual TypeScript definitions in node_modules
  • Check the package's README and changelog
  • Test the actual behavior before implementing

Architecture Changes

Reverse Proxy Implementation

  • Replaced Nginx with native Deno reverse proxy (ts/classes/reverseproxy.ts)
  • Features:
    • HTTP/HTTPS dual servers (ports 80/443)
    • TLS/SSL certificate management with hot-reload
    • WebSocket bidirectional proxying
    • Dynamic routing from database
    • SNI (Server Name Indication) support

Code Organization

  • Removed "onebox." prefix from all TypeScript files
  • Organized into subfolders:
    • ts/classes/ - All class implementations
    • ts/ - Root level utilities (logging, types, plugins, cli, info)

WebSocket Real-time Communication

  • Backend: WebSocket endpoint at /api/ws (ts/classes/httpserver.ts:96-174)
    • Connection management with client Set tracking
    • Broadcast methods: broadcast(), broadcastServiceUpdate(), broadcastServiceStatus()
    • Integrated with service lifecycle (start/stop/restart actions)
    • Status monitoring loop broadcasts changes automatically
  • Frontend: Angular WebSocket service (ui/src/app/core/services/websocket.service.ts)
    • Auto-connects on app initialization
    • Exponential backoff reconnection (max 5 attempts)
    • RxJS Observable-based message streaming
    • Components subscribe to real-time updates
  • Message Types:
    • connected - Initial connection confirmation
    • service_update - Service lifecycle changes (action: created/updated/deleted/started/stopped)
    • service_status - Real-time status changes from monitoring loop
    • system_status - System-wide updates
  • Testing: Use .nogit/test-ws-updates.ts to monitor WebSocket messages

Docker Configuration

  • System Docker: Uses root Docker at /var/run/docker.sock (NOT rootless)
  • Swarm Mode: Enabled for service orchestration
  • API Access: Interact with Docker via direct API calls to the socket
    • DO NOT switch Docker CLI contexts
    • Use curl/HTTP requests to /var/run/docker.sock
  • Network: Overlay network onebox-network with Attachable: true
  • Services vs Containers: All workloads run as Swarm services (not standalone containers)

Debugging Tips

Backend Logs

Use the background bash task to check server logs:

# Check for specific patterns (e.g., Login attempts)
BashOutput tool with filter: "Login|error|Error"

# Check all recent output
BashOutput tool without filter

The dev server runs with --watch so it auto-restarts on file changes.

Frontend Testing

Use Playwright for UI testing:

// Navigate to app
mcp__playwright__browser_navigate({ url: "http://localhost:3000" })

// Fill login form
mcp__playwright__browser_fill_form({
  fields: [
    { name: "Username", type: "textbox", ref: "...", value: "admin" },
    { name: "Password", type: "textbox", ref: "...", value: "admin" }
  ]
})

// Click button
mcp__playwright__browser_click({ element: "Sign in button", ref: "..." })

// Check console errors
// Playwright automatically shows console messages in results

Common Issues

Login Issue (Fixed)

Problem: admin/admin credentials returned "Invalid credentials"

Root Cause: rowToUser() function in database.ts was accessing rows as arrays row[2] instead of objects row.password_hash. The @db/sqlite library returns rows as objects with snake_case column names.

Fix: Updated rowToUser() to support both access patterns:

private rowToUser(row: any): IUser {
  return {
    passwordHash: String(row.password_hash || row[2]),
    // ... other fields
  };
}

Location: ts/classes/database.ts:506-515

Default Credentials

  • Username: admin
  • Password: admin
  • ⚠️ Change immediately after first login!

Development Server

# Main server (port 3000)
deno task dev

# Check server status
curl http://localhost:3000/api/status

API Endpoints

  • POST /api/auth/login - Login (returns JWT-like token)
  • GET /api/status - System status (requires auth)
  • GET /api/services - List services (requires auth)
  • See ts/classes/httpserver.ts for full API