> ## Documentation Index
> Fetch the complete documentation index at: https://docs.westyx.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Go SDK - Configuration

> Config field reference, TTL guidance, and HTTP client details for the Go SDK.

`nexus.Config` is a plain Go struct holding every value required to construct a client. Pass a value (not a pointer) to `NewClient`.

```go theme={null}
client, err := nexus.NewClient(ctx, nexus.Config{
    BaseURL: "https://<slug>.westyx.dev", // required
    APIKey:  "wxs_...",               // required
    TTL:     60 * time.Second,            // optional, default 60s
    Logger:  myLogger,                    // optional
})
```

## Field reference

| Field                  | Type                   | Default                                   | Description                                                                                                                                                                                                                                                         |
| ---------------------- | ---------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `BaseURL`              | `string`               | -                                         | Full service URL, e.g. `https://<slug>.westyx.dev`. The slug embedded in the host is also injected as the `Host` header on every request (Double-Gate requirement).                                                                                                 |
| `APIKey`               | `string`               | -                                         | Raw `wxs_...` or `wxp_...` key. Sent verbatim in `X-Nexus-API-Key`. Required unless `WIF.Enabled` is `true`.                                                                                                                                                        |
| `TTL`                  | `time.Duration`        | `60 * time.Second`                        | Local cache TTL. After this elapses, the next read triggers a one-shot background refresh while still serving the stale cache.                                                                                                                                      |
| `Logger`               | `nexus.Logger`         | `NoopLogger{}`                            | Optional diagnostic logger. See Custom logging.                                                                                                                                                                                                                     |
| `HTTPClient`           | `*http.Client`         | `&http.Client{Timeout: 10 * time.Second}` | Custom HTTP client. Mainly used in tests with a stub `http.RoundTripper`.                                                                                                                                                                                           |
| `WIF`                  | `*nexus.WIFConfig`     | `nil`                                     | Optional Workload Identity Federation config - when `Enabled`, the SDK exchanges a workload OIDC token for a Nexus session JWT and uses Bearer auth instead of `X-Nexus-API-Key`. See [Workload identity](workload-identity).                                       |
| `Observer`             | `nexus.StreamObserver` | `NoopStreamObserver{}`                    | Optional structured-callback observer for SSE lifecycle events. See [Stream observer](stream-observer).                                                                                                                                                             |
| `SSEReconnectCooldown` | `[]int`                | `nil`                                     | Schedule for reconnecting SSE after falling back to TTL polling. Unit: **minutes**. `nil` = default exponential `[5, 10, 20, 40, 60]` min. Single element = fixed interval. Multi-element = custom schedule (stays at last value). Values below 1 clamped to 1 min. |

## API key types

| Prefix    | Access                                          | Sync response shape                                      |
| --------- | ----------------------------------------------- | -------------------------------------------------------- |
| `wxs_...` | Full - all configs, all secrets, all flags      | `configs`, `secrets`, and `flags` populated              |
| `wxp_...` | Restricted - configs and flags only, no secrets | `secrets` field is **entirely absent** from the response |

<Warning>
  Calling `GetSecret(...)` with a public key returns `ErrPublicKeyRestricted` synchronously, before the network call.
</Warning>

## Where to keep the API key

For services, the conventional Go pattern is environment variables:

```go theme={null}
nexus.Config{
    BaseURL: os.Getenv("NEXUS_URL"),
    APIKey:  os.Getenv("NEXUS_API_KEY"),
}
```

Pair with `os.LookupEnv` for explicit "missing" handling, or with libraries like `github.com/caarlos0/env` or `github.com/kelseyhightower/envconfig`.

The SDK never logs the raw key. Log lines reference key type only:

```
nexus: client ready (key_type=sk, ttl=1m0s)
```

## Choosing the TTL

The TTL is a tradeoff between staleness window and redundant network traffic. With SSE enabled (started automatically by `NewClient`), **changes propagate in milliseconds regardless of the TTL** - the TTL only matters as a safety net if the stream falls back.

| Use case                                     | Suggested TTL                |
| -------------------------------------------- | ---------------------------- |
| Frequently-changing flags, latency-sensitive | `30 * time.Second`           |
| Standard configs with SSE                    | `60 * time.Second` (default) |
| Stable production secrets                    | `5 * time.Minute`            |
| Boot-time only, never rechecked              | `1 * time.Hour`              |

<Info>
  If SSE is connected, the SDK clamps the effective TTL to at least 60 s - no point polling more aggressively when the stream pushes events the moment they happen.
</Info>

## Custom HTTP client

For tests or when you want explicit control over timeouts / TLS:

```go theme={null}
nexus.Config{
    BaseURL:    "...",
    APIKey:     "...",
    HTTPClient: &http.Client{
        Timeout:   5 * time.Second,
        Transport: &http.Transport{
            // ... custom TLS, proxy, etc.
        },
    },
}
```

If `HTTPClient` is nil, the SDK builds its own with a 10-second timeout.

### Two clients under the hood

The SDK uses **two distinct HTTP clients** internally:

1. The **short-request client** - your `Config.HTTPClient` verbatim (or the default 10 s-timeout client). Used for `/v1/sync`, `/v1/auth/token-exchange`, and any future short request. May carry any total request timeout you choose.
2. A **streaming client** - derived from your client at construction time (a value-copy with `Timeout` cleared). Used exclusively for the long-lived `/v1/stream` SSE connection.

<Note>
  This split is not optional - Go's `http.Client.Timeout` applies to the entire request including reading the response body, so a single shared client with a non-zero `Timeout` would kill SSE connections at the timeout boundary regardless of activity. The SDK makes the split for you so you can keep your familiar `http.Client{Timeout: 10*time.Second}` pattern without breaking the stream.
</Note>

The streaming client inherits everything else from your client - `Transport` (proxies, custom TLS, instrumentation), `Jar` (cookies), `CheckRedirect`. Cancellation of the SSE goroutine is provided exclusively by the `context.Context` you pass to `RunStream(ctx)`.

If your client has a non-zero `Timeout`, the SDK emits a `Debug`-level log note at startup recording the split:

```
nexus: derived a separate streaming HTTP client (Timeout=0) from the supplied client (Timeout=10s) - required for long-lived SSE
```
