# Kosmi API Reverse Engineering Findings

## Key Discovery: HTTP POST Works!

After browser-based investigation, we discovered that Kosmi's GraphQL API works via **HTTP POST**, not just WebSocket!

### Working Endpoint

```
POST https://engine.kosmi.io/
Content-Type: application/json

{
  "query": "{ __schema { types { name } } }"
}
```

**Response**: ✅ 200 OK with proper GraphQL response

### WebSocket Issue

The WebSocket endpoint `wss://engine.kosmi.io/gql-ws` returns **403 Forbidden** when connecting directly because:

1. **Missing Cookies**: The browser has session cookies that aren't accessible via `document.cookie` (HTTP-only)
2. **Missing Headers**: Likely needs `Origin: https://app.kosmi.io` header
3. **Session Required**: May need to establish a session first via HTTP

## Implementation Options

### Option 1: HTTP POST with Polling (Recommended for Now)

**Pros**:
- ✅ Works without authentication
- ✅ Simple implementation
- ✅ No WebSocket complexity

**Cons**:
- ❌ Not real-time (need to poll)
- ❌ Higher latency
- ❌ More bandwidth usage

**Implementation**:
```go
// Poll for new messages every 1-2 seconds
func (c *GraphQLClient) PollMessages() {
    ticker := time.NewTicker(2 * time.Second)
    for range ticker.C {
        // Query for messages since last timestamp
        messages := c.QueryMessages(lastTimestamp)
        // Process new messages
    }
}
```

### Option 2: WebSocket with Session Cookies

**Pros**:
- ✅ Real-time updates
- ✅ Efficient (push-based)
- ✅ Lower latency

**Cons**:
- ❌ Requires session establishment
- ❌ Need to handle cookies
- ❌ More complex

**Implementation**:
```go
// 1. First, establish session via HTTP
session := establishSession()

// 2. Then connect WebSocket with cookies
dialer := websocket.Dialer{
    Jar: session.CookieJar,
}
conn, _, err := dialer.Dial(wsURL, http.Header{
    "Origin": []string{"https://app.kosmi.io"},
    "Cookie": []string{session.Cookies},
})
```

### Option 3: Hybrid Approach

**Best of both worlds**:
1. Use HTTP POST for sending messages (mutations)
2. Use HTTP POST polling for receiving messages (queries)
3. Later upgrade to WebSocket when we figure out auth

## Next Steps

### Immediate (HTTP-based)

1. ✅ Update `graphql.go` to use HTTP POST instead of WebSocket
2. ✅ Implement message polling
3. ✅ Test with actual Kosmi room
4. ✅ Verify message sending works

### Future (WebSocket-based)

1. ⏳ Figure out session establishment
2. ⏳ Extract cookies from browser or create session
3. ⏳ Update WebSocket connection to include cookies
4. ⏳ Switch from polling to real-time subscriptions

## GraphQL Schema Discovery

From the introspection query, we found these types:
- `RootQueryType` - For queries
- `RootMutationType` - For mutations  
- `Session` - Session management
- `Success` - Success responses

We need to explore the schema more to find:
- Message query fields
- Message mutation fields
- Room/channel structures

## Testing Commands

### Test HTTP Endpoint
```bash
curl -X POST https://engine.kosmi.io/ \
  -H "Content-Type: application/json" \
  -d '{"query": "{ __schema { types { name } } }"}'
```

### Test with Go
```go
resp, err := http.Post(
    "https://engine.kosmi.io/",
    "application/json",
    strings.NewReader(`{"query": "{ __schema { types { name } } }"}`),
)
```

## Browser Findings

### Cookies Present
```
g_state={...}
```
Plus HTTP-only cookies we can't access.

### User Agent
```
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36
```

### Origin
```
https://app.kosmi.io
```

## Recommendations

**For MVP**: Use HTTP POST with polling
- Simpler to implement
- Works without authentication
- Good enough for initial testing
- Can upgrade to WebSocket later

**For Production**: Figure out WebSocket auth
- Better performance
- Real-time updates
- Lower bandwidth
- Better user experience

## Updated Architecture

```
IRC Message
    ↓
Matterbridge
    ↓
Kosmi Bridge (HTTP POST)
    ↓
POST https://engine.kosmi.io/
    ↓
Kosmi Room

Kosmi Room
    ↓
Poll https://engine.kosmi.io/ (every 2s)
    ↓
Kosmi Bridge
    ↓
Matterbridge
    ↓
IRC Message
```

## Action Items

1. **Update `graphql.go`**:
   - Replace WebSocket with HTTP client
   - Implement POST request method
   - Add polling loop for messages

2. **Test queries**:
   - Find the correct query for fetching messages
   - Find the correct mutation for sending messages
   - Test with actual room ID

3. **Implement polling**:
   - Poll every 1-2 seconds
   - Track last message timestamp
   - Only fetch new messages

4. **Document limitations**:
   - Note the polling delay
   - Explain why WebSocket doesn't work yet
   - Provide upgrade path

---

**Status**: HTTP POST endpoint discovered and verified ✅  
**Next**: Implement HTTP-based client to replace WebSocket

