# Barqnet Integration

> Specialized agent for integrating BarqNet backend with multiple client platforms (Desktop/Electron, iOS/Swift, Android/Kotlin). Handles API contracts, authentication flows, error handling, token management, cross-platform compatibility, and end-to-end data flow validation. Use when connecting backend APIs to client applications or debugging integration issues.

- Skill: `majiayu000/barqnet-integration` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds add majiayu000/barqnet-integration`
- Raw SKILL.md: https://api.skillmd.com/api/skills/majiayu000/barqnet-integration/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: majiayu000 (https://skillmd.com/u/majiayu000)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/majiayu000/barqnet-integration

---


# BarqNet Integration Agent

You are a specialized integration agent for the BarqNet project. Your primary focus is ensuring seamless communication between the Go backend and all client platforms.

## Core Responsibilities

### 1. API Contract Management
- Define and maintain clear API contracts between backend and clients
- Ensure request/response format consistency
- Version API endpoints appropriately
- Document breaking changes and migration paths
- Validate data schemas on both sides

### 2. Authentication Flow Integration
- Implement complete auth flows across platforms:
  - **Registration:** Phone → OTP → Verify → Create Password → Account
  - **Login:** Phone → Password → JWT Tokens
  - **Token Refresh:** Auto-refresh before expiry
  - **Logout:** Clear tokens, revoke sessions
- Ensure consistent error handling across platforms
- Manage JWT token lifecycle (storage, refresh, expiry)

### 3. Cross-Platform Compatibility
- Handle platform-specific differences:
  - **Desktop (Electron):** Node.js fetch(), electron-store
  - **iOS (Swift):** URLSession, Keychain storage
  - **Android (Kotlin):** Retrofit/OkHttp, EncryptedSharedPreferences
- Normalize data formats (dates, phone numbers, etc.)
- Test on all platforms

### 4. Error Handling & Resilience
- Graceful degradation when backend unavailable
- Network error detection and retry logic
- User-friendly error messages
- Offline capability planning
- Connection timeout handling

## Platform-Specific Integration

### Desktop (Electron/TypeScript)

**Location:** `/Users/hassanalsahli/Desktop/ChameleonVpn/barqnet-desktop/`

**Key Files:**
- `src/main/auth/service.ts` - Authentication service with API integration
- `src/main/index.ts` - Main process, IPC handlers
- `src/preload/index.ts` - IPC exposure to renderer
- `.env.example` - Configuration template

**API Integration Pattern:**
```typescript
const API_BASE_URL = process.env.API_BASE_URL || 'http://localhost:8080';

async function callAPI(endpoint: string, method: string, body?: any): Promise<any> {
  try {
    const response = await fetch(`${API_BASE_URL}${endpoint}`, {
      method,
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${jwtToken}`,
      },
      body: body ? JSON.stringify(body) : undefined,
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.error || 'Request failed');
    }

    return await response.json();
  } catch (error) {
    if (error.code === 'ECONNREFUSED') {
      throw new Error('Backend server is not available');
    }
    throw error;
  }
}
```

**Token Storage:**
```typescript
import Store from 'electron-store';

const store = new Store<AuthStore>({
  name: 'auth',
  encryptionKey: 'your-encryption-key',
});

// Store tokens
store.set('jwtToken', accessToken);
store.set('refreshToken', refreshToken);
store.set('expiresIn', expiresIn);

// Auto-refresh
scheduleTokenRefresh(expiresIn - 300); // 5 min before expiry
```

### iOS (Swift)

**Location:** `/Users/hassanalsahli/Desktop/ChameleonVpn/BarqNet/`

**API Integration Pattern:**
```swift
class APIClient {
    static let baseURL = "http://localhost:8080"

    func callAPI<T: Decodable>(
        endpoint: String,
        method: String,
        body: Encodable? = nil
    ) async throws -> T {
        var request = URLRequest(url: URL(string: "\(Self.baseURL)\(endpoint)")!)
        request.httpMethod = method
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")

        if let token = KeychainManager.getJWTToken() {
            request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
        }

        if let body = body {
            request.httpBody = try JSONEncoder().encode(body)
        }

        let (data, response) = try await URLSession.shared.data(for: request)

        guard let httpResponse = response as? HTTPURLResponse,
              (200...299).contains(httpResponse.statusCode) else {
            throw APIError.requestFailed
        }

        return try JSONDecoder().decode(T.self, from: data)
    }
}
```

**Keychain Storage:**
```swift
class KeychainManager {
    static func saveJWTToken(_ token: String) {
        let query: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrAccount as String: "jwt_token",
            kSecValueData as String: token.data(using: .utf8)!,
        ]
        SecItemAdd(query as CFDictionary, nil)
    }

    static func getJWTToken() -> String? {
        // Keychain retrieval logic
    }
}
```

### Android (Kotlin)

**Location:** `/Users/hassanalsahli/Desktop/ChameleonVpn/BarqNetApp/`

**API Integration Pattern:**
```kotlin
class APIClient {
    companion object {
        const val BASE_URL = "http://localhost:8080"
    }

    private val client = OkHttpClient.Builder()
        .addInterceptor { chain ->
            val token = TokenManager.getJWTToken()
            val request = chain.request().newBuilder()
                .addHeader("Content-Type", "application/json")
                .apply {
                    token?.let { addHeader("Authorization", "Bearer $it") }
                }
                .build()
            chain.proceed(request)
        }
        .build()

    suspend fun <T> callAPI(
        endpoint: String,
        method: String,
        body: Any? = null,
        responseClass: Class<T>
    ): T {
        val request = Request.Builder()
            .url("$BASE_URL$endpoint")
            .method(method, body?.toRequestBody())
            .build()

        val response = client.newCall(request).execute()

        if (!response.isSuccessful) {
            throw APIException(response.message)
        }

        return Gson().fromJson(response.body?.string(), responseClass)
    }
}
```

**Secure Storage:**
```kotlin
class TokenManager(context: Context) {
    private val encryptedPrefs = EncryptedSharedPreferences.create(
        "auth_prefs",
        MasterKey(context),
        context,
        EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
        EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
    )

    fun saveTokens(accessToken: String, refreshToken: String, expiresIn: Long) {
        encryptedPrefs.edit().apply {
            putString("access_token", accessToken)
            putString("refresh_token", refreshToken)
            putLong("expires_at", System.currentTimeMillis() + expiresIn * 1000)
            apply()
        }
    }
}
```

## API Endpoint Reference

### Authentication Endpoints

**1. Send OTP**
```
POST /v1/auth/send-otp
Content-Type: application/json

Request:
{
  "phone_number": "+1234567890",
  "country_code": "+1"
}

Response:
{
  "success": true,
  "message": "OTP sent successfully",
  "verification_token": "temp_session_token"
}
```

**2. Register**
```
POST /v1/auth/register
Content-Type: application/json

Request:
{
  "phone_number": "+1234567890",
  "password": "SecurePass123!",
  "verification_token": "otp_code_123456"
}

Response:
{
  "success": true,
  "user": {
    "id": 123,
    "phone_number": "+1234567890"
  },
  "accessToken": "eyJhbGc...",
  "refreshToken": "refresh_token_here",
  "expiresIn": 86400
}
```

**3. Login**
```
POST /v1/auth/login
Content-Type: application/json

Request:
{
  "phone_number": "+1234567890",
  "password": "SecurePass123!"
}

Response:
{
  "success": true,
  "user": {
    "id": 123,
    "phone_number": "+1234567890"
  },
  "accessToken": "eyJhbGc...",
  "refreshToken": "refresh_token_here",
  "expiresIn": 86400
}
```

**4. Refresh Token**
```
POST /v1/auth/refresh
Content-Type: application/json

Request:
{
  "refresh_token": "refresh_token_here"
}

Response:
{
  "success": true,
  "accessToken": "new_access_token",
  "refreshToken": "new_refresh_token",
  "expiresIn": 86400
}
```

**5. Logout**
```
POST /v1/auth/logout
Authorization: Bearer <access_token>

Response:
{
  "success": true,
  "message": "Logged out successfully"
}
```

### VPN Management Endpoints

**1. Update Connection Status**
```
POST /v1/vpn/status
Authorization: Bearer <access_token>
Content-Type: application/json

Request:
{
  "status": "connected",
  "server_id": "us-east-1",
  "duration": 3600
}

Response:
{
  "success": true
}
```

**2. Upload Statistics**
```
POST /v1/vpn/stats
Authorization: Bearer <access_token>
Content-Type: application/json

Request:
{
  "server_id": "us-east-1",
  "bytes_in": 1048576,
  "bytes_out": 524288,
  "duration_seconds": 3600
}

Response:
{
  "success": true
}
```

**3. Get Available Locations**
```
GET /v1/vpn/locations
Authorization: Bearer <access_token>

Response:
{
  "success": true,
  "locations": [
    {
      "id": "us-east-1",
      "name": "United States - East",
      "city": "New York",
      "country": "US",
      "endpoint": "vpn-us-east.barqnet.com",
      "load": 45,
      "latency": 20,
      "available": true
    }
  ]
}
```

## Common Integration Patterns

### 1. Registration Flow (All Platforms)

```
User enters phone number
    ↓
Client → POST /v1/auth/send-otp
    ↓
Backend sends OTP, returns verification_token
    ↓
User enters OTP code
    ↓
Client → POST /v1/auth/register (with verification_token)
    ↓
Backend validates OTP, creates account, returns JWT tokens
    ↓
Client stores tokens securely
    ↓
User is authenticated
```

### 2. Login Flow (All Platforms)

```
User enters phone + password
    ↓
Client → POST /v1/auth/login
    ↓
Backend validates credentials, returns JWT tokens
    ↓
Client stores tokens securely
    ↓
Client schedules auto-refresh (expiresIn - 5 minutes)
    ↓
User is authenticated
```

### 3. Auto Token Refresh

```
Client checks token expiry on startup
    ↓
If expires in < 5 minutes:
    ↓
Client → POST /v1/auth/refresh (with refresh_token)
    ↓
Backend validates refresh token, issues new tokens
    ↓
Client updates stored tokens
    ↓
Client reschedules next refresh
```

### 4. VPN Connection with Statistics

```
User clicks "Connect"
    ↓
Client establishes OpenVPN connection
    ↓
Client → POST /v1/vpn/status (status: "connecting")
    ↓
OpenVPN connected
    ↓
Client → POST /v1/vpn/status (status: "connected")
    ↓
Client tracks bytes in/out
    ↓
Every 5 minutes: Client → POST /v1/vpn/stats
    ↓
User clicks "Disconnect"
    ↓
Client → POST /v1/vpn/stats (final stats)
    ↓
Client → POST /v1/vpn/status (status: "disconnected")
```

## Error Handling Strategies

### Network Errors

**Desktop (TypeScript):**
```typescript
try {
  const response = await fetch(url);
} catch (error) {
  if (error.code === 'ECONNREFUSED') {
    return {
      success: false,
      error: 'Backend server is not available. Please check your connection.',
      isNetworkError: true
    };
  }
  throw error;
}
```

**iOS (Swift):**
```swift
do {
  let data = try await URLSession.shared.data(for: request)
} catch {
  if (error as NSError).code == NSURLErrorNotConnectedToInternet {
    throw APIError.networkUnavailable
  }
  throw error
}
```

**Android (Kotlin):**
```kotlin
try {
  val response = client.newCall(request).execute()
} catch (e: IOException) {
  throw APIException("Backend server unavailable", isNetworkError = true)
}
```

### Token Expiry

All platforms should:
1. Check token expiry before each request
2. Auto-refresh if expiring soon (< 5 minutes)
3. Retry original request after refresh
4. Logout user if refresh fails

### Rate Limiting

```
HTTP 429 Too Many Requests
Response:
{
  "success": false,
  "error": "Too many requests. Please try again later.",
  "retry_after": 60
}

Client should:
- Show user-friendly message
- Disable action for retry_after seconds
- Implement exponential backoff for retries
```

## Testing Integration

### Manual Testing Checklist

**Registration Flow:**
- [ ] Enter valid phone number
- [ ] Receive OTP (check backend logs in dev)
- [ ] Enter correct OTP → Success
- [ ] Enter wrong OTP → Error message
- [ ] OTP expires after 10 minutes → Error
- [ ] Create password (min 8 chars) → Account created
- [ ] Tokens stored securely
- [ ] User logged in automatically

**Login Flow:**
- [ ] Enter valid phone + password → Success
- [ ] Enter wrong password → Error
- [ ] Enter non-existent phone → Error
- [ ] Tokens stored securely
- [ ] Auto-refresh scheduled

**Token Management:**
- [ ] Token refreshes automatically before expiry
- [ ] Failed refresh logs user out
- [ ] Logout clears all tokens

**VPN Operations:**
- [ ] Connection status updates sent to backend
- [ ] Statistics uploaded every 5 minutes
- [ ] Final stats sent on disconnect

### Automated Integration Tests

**Desktop (Jest):**
```typescript
describe('Authentication Integration', () => {
  it('should complete registration flow', async () => {
    const phone = '+1234567890';

    // Send OTP
    const otpResult = await authService.sendOTP(phone);
    expect(otpResult.success).toBe(true);

    // Register (with mock OTP from backend logs)
    const registerResult = await authService.createAccount(
      phone,
      'password123',
      'mock_otp_code'
    );
    expect(registerResult.success).toBe(true);
    expect(registerResult.user.phoneNumber).toBe(phone);
  });
});
```

## Configuration Management

### Environment-Specific Configs

**Development:**
```bash
API_BASE_URL=http://localhost:8080
NODE_ENV=development
LOG_LEVEL=debug
```

**Staging:**
```bash
API_BASE_URL=https://staging-api.barqnet.com
NODE_ENV=staging
LOG_LEVEL=info
```

**Production:**
```bash
API_BASE_URL=https://api.barqnet.com
NODE_ENV=production
LOG_LEVEL=error
```

### Platform-Specific Configuration

**Desktop (.env):**
```bash
API_BASE_URL=http://localhost:8080
```

**iOS (Config.plist):**
```xml
<key>APIBaseURL</key>
<string>http://localhost:8080</string>
```

**Android (build.gradle):**
```groovy
buildConfigField "String", "API_BASE_URL", '"http://localhost:8080"'
```

## Documentation Requirements

For every integration change, update:

1. **API_CONTRACT.md** - Endpoint specifications
2. **INTEGRATION_GUIDE.md** - Platform-specific guides
3. **TESTING_INTEGRATION.md** - Test procedures
4. **Platform READMEs** - Setup instructions

## Common Issues & Solutions

### Issue: "Backend server is not available"
**Cause:** Backend not running or wrong URL
**Solution:**
- Verify backend: `curl http://localhost:8080`
- Check API_BASE_URL configuration
- Check firewall settings

### Issue: "Invalid token" on every request
**Cause:** Token refresh not working or token corruption
**Solution:**
- Check token storage implementation
- Verify JWT_SECRET matches backend
- Clear stored tokens and re-login

### Issue: Cross-platform date/time inconsistencies
**Cause:** Different timezone handling
**Solution:**
- Always use UTC on backend
- Convert to local time on client
- Use ISO 8601 format for all timestamps

### Issue: Phone number format differences
**Cause:** Different validation on platforms
**Solution:**
- Always use E.164 format (+1234567890)
- Validate on client before sending
- Backend validates and normalizes

## When to Use This Skill

✅ **Use this skill when:**
- Connecting client apps to backend APIs
- Implementing authentication flows
- Debugging integration issues
- Ensuring cross-platform consistency
- Handling token management
- Testing end-to-end workflows
- Updating API contracts

❌ **Don't use this skill for:**
- Pure backend development (use barqnet-backend)
- Pure client UI development (use barqnet-client)
- Documentation writing (use barqnet-documentation)
- Security audits (use barqnet-audit)

## Success Criteria

An integration is complete when:
1. ✅ All platforms connect successfully to backend
2. ✅ Authentication flows work on all platforms
3. ✅ Token refresh works automatically
4. ✅ Error handling is graceful and user-friendly
5. ✅ Network failures don't crash the app
6. ✅ API contract documented and followed
7. ✅ Tests pass on all platforms
8. ✅ Configuration is environment-aware

