# Go SDK

The Go SDK (`sdks/go/`) provides a native QUIC + Cap'n Proto client for
quicproquo, giving Go applications full access to the messaging API without
any HTTP translation layer.

## Prerequisites

- Go 1.21+
- A running qpq server

## Installation

```go
import "quicproquo.dev/sdk/go/qpq"
```

## Quick start

```go
package main

import (
    "context"
    "fmt"
    "log"

    "quicproquo.dev/sdk/go/qpq"
)

func main() {
    ctx := context.Background()

    // Connect to the server
    client, err := qpq.Connect(ctx, qpq.Options{
        Addr:               "127.0.0.1:7000",
        InsecureSkipVerify: true, // development only
    })
    if err != nil {
        log.Fatal(err)
    }

    // Health check
    status, err := client.Health(ctx)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Server status:", status)

    // OPAQUE authentication
    if err := client.LoginStart(ctx, "alice", "secret"); err != nil {
        log.Fatal(err)
    }
    if err := client.LoginFinish(ctx); err != nil {
        log.Fatal(err)
    }

    // Resolve a peer
    peerKey, err := client.ResolveUser(ctx, "bob")
    if err != nil {
        log.Fatal(err)
    }

    // Create a DM channel
    channelID, err := client.CreateChannel(ctx, peerKey)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Channel:", channelID)

    // Send a message
    if err := client.Send(ctx, peerKey, []byte("Hello from Go!")); err != nil {
        log.Fatal(err)
    }

    // Send a disappearing message (1 hour TTL)
    if err := client.SendWithTTL(ctx, peerKey, []byte("This vanishes"), 3600); err != nil {
        log.Fatal(err)
    }

    // Receive messages
    msgs, err := client.Receive(ctx, peerKey)
    if err != nil {
        log.Fatal(err)
    }
    for _, m := range msgs {
        fmt.Println("Received:", string(m))
    }
}
```

## API reference

| Method | Description |
|---|---|
| `Connect(ctx, opts)` | Establish QUIC connection to server |
| `Health(ctx)` | Server readiness probe |
| `RegisterStart/Finish(ctx, user, pass)` | OPAQUE registration |
| `LoginStart/Finish(ctx, user, pass)` | OPAQUE login |
| `ResolveUser(ctx, username)` | Look up a user's identity key |
| `CreateChannel(ctx, peerKey)` | Create a 1:1 DM channel |
| `Send(ctx, recipientKey, payload)` | Send a message |
| `SendWithTTL(ctx, recipientKey, payload, ttlSecs)` | Send a disappearing message |
| `Receive(ctx, recipientKey)` | Fetch queued messages |
| `ReceiveWait(ctx, recipientKey, timeoutMs)` | Long-poll for messages (default 5 s timeout) |
| `DeleteAccount(ctx)` | Delete the authenticated account |

## Transport details

- **Protocol:** QUIC with TLS 1.3 via `quic-go`
- **ALPN:** `"capnp"` (same as the Rust client)
- **Serialisation:** Cap'n Proto RPC over a single bidirectional stream
- **Idle timeout:** 300 seconds
- **Auth:** Session token stored in client, sent with every RPC via the `Auth` struct

## Connection options

```go
type Options struct {
    Addr               string // "host:port"
    CACertPath         string // path to CA cert (DER format)
    InsecureSkipVerify bool   // skip TLS verification (dev only!)
    Token              string // pre-existing auth token (optional)
}
```

## Project structure

```
sdks/go/
├── proto/         # Generated Cap'n Proto types from node.capnp
├── transport/     # QUIC transport layer (quic-go + TLS 1.3)
├── qpq/           # High-level client API (QpqClient)
├── cmd/example/   # Example CLI program
├── go.mod
└── README.md
```

## Running the example

```bash
cd sdks/go/cmd/example
go run main.go
```

## Regenerating proto types

If you modify `schemas/node.capnp`, regenerate the Go types:

```bash
capnp compile -ogo sdks/go/proto/node.capnp
```
