Configuration and authentication — bRRAIn Docs
How a Platform SDK client authenticates: the supervisor's internal URL and token, client options, the app slug and namespace isolation, timeouts, and secrets hygiene.
Configuration and authentication
An SDK client authenticates as your extension, not as a person. The brain pod's extension supervisor gives your process a URL, a token and your slug; the client sends the token on every request and asserts the slug so the platform can isolate your vault namespace. There are no API keys to create or rotate in your code.
The Options struct
type Options struct {
BaseURL string // required, absolute: scheme + host (BRRAIN_INTERNAL_URL)
Token string // BRRAIN_INTERNAL_TOKEN; sent as "Authorization: Bearer <token>"
HTTPClient *http.Client // optional; the default has a 30 s timeout
UserAgent string // optional; default "brrain-platform-sdk/1.2.0"
AppSlug string // optional; default os.Getenv("BRRAIN_APP_SLUG")
}
What platformsdk.New checks, and what it does not:
- An empty
BaseURLreturnsplatformsdk: BaseURL is required. A URL with no scheme, such as127.0.0.1:7843, returnsBaseURL must be absolute. - An empty
Tokenis accepted: the client simply sends noAuthorizationheader, and the pod answers every call with 401. Check the token yourself at start-up. AppSlugis trimmed and lowercased. A value containing/,\, NUL, or equal to.or..is dropped silently, and no slug header is sent. Leave it empty in production so the supervisor'sBRRAIN_APP_SLUGflows through; set it explicitly only in tests.
A production constructor
func newClient() *platformsdk.Client {
client, err := platformsdk.New(platformsdk.Options{
BaseURL: mustEnv("BRRAIN_INTERNAL_URL"),
Token: mustEnv("BRRAIN_INTERNAL_TOKEN"),
UserAgent: "hello-notes/0.1.0",
HTTPClient: &http.Client{Timeout: 150 * time.Second}, // room for model calls
})
if err != nil {
log.Fatalf("hello-notes: build SDK client: %v", err)
}
return client
}
mustEnv exits with a message naming the missing variable; see the Quickstart. The full server is in Go with net/http.
Decisions in that constructor:
- Fail fast on missing configuration. A missing token is a deployment fault; say so at start-up rather than through a stream of 401s.
- Read the URL from the environment. Do not hard-code a host or port.
- Size the transport timeout for your slowest call.
http.Client.Timeoutcaps every request regardless of a longer context deadline. Calls to the Handler can take well over 30 seconds on CPU-only pods, so model-calling extensions need a longer client timeout, with per-call context deadlines for everything else. - Build one client per process and share it. Sub-client accessors are cheap.
Prove the platform is reachable
Make one cheap call at start-up whose "not found" answer still means healthy:
func bootCanary(ctx context.Context, c *platformsdk.Client) error {
probeCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
_, err := c.Vault().Stat(probeCtx, "extensions/hello-notes")
var apiErr *platformsdk.APIError
switch {
case err == nil:
return nil // token accepted, namespace exists
case errors.As(err, &apiErr) && apiErr.StatusCode == http.StatusNotFound:
return nil // token accepted, first run: namespace not created yet
default:
return err // 401: wrong token; transport error: wrong URL or pod not ready
}
}
The slug and namespace isolation
When a slug is set, every request carries X-Brrain-App-Slug: <slug>. The platform uses it to enforce vault namespaces:
| Path | Who may use it |
| --- | --- |
| extensions/<your-slug>/ | Your extension. Other extensions get 403 and do not see it in unscoped searches. |
| extensions/_<name>/ | The platform only. Any extension asserting a slug gets 403. Use the owning SDK call instead (for example OperatorEnv()). |
| Everything else (projects/<Name>/, session files, standards) | Shared organization knowledge. Other controls apply; prefer Ingestion().Commit for content you publish here. |
Acting for a person
The internal API authorizes the extension. It does not know which person clicked a button in your interface, and a user's project permissions are not applied to your calls. When your extension acts for a user:
- Take the user's identity from the authenticated request the console proxies to you, never from the request body or a query parameter the browser composed, and never on a route declared
public. - Ask the policy engine before acting, and record the outcome in the audit chain.
- Scope reads to what that user could see in Nexus.
Secrets hygiene
- Never log, print or store
BRRAIN_INTERNAL_TOKEN, and never send it anywhere except the client. - Never store vendor credentials. Resolve them at call time with
OAuth().ResolveBearerorOperatorEnv().Get(see Examples). - Keep
.envfiles used for local experiments out of version control. Tests should use a fake token against anhttptestserver.