Access
Introduction
Caller authorization always runs before a concurrency slot is taken. Configure caller auth on the source's Access tab. Upstream secrets for managed sources live under Credentials.
Checks run in this order: IP policies → JWT / Cloudflare Access → access key.
Access keys
An access key admits callers to one source. There are two kinds, and both go in the same header:
- Keys you create under Sources → Access → Create key, or with the
Control API. Today they start with
nb_live_. - Session tokens that agents get from
start_source_sessionover MCP. They start withsv_at_and always expire. See Session tokens.
Send the key with X-Swarmvia-Key:
curl -sS "https://your-source.swarmvia.cloud/v1/records" \
-H "X-Swarmvia-Key: $ACCESS_KEY"On managed sources you may instead send
Authorization: Bearer $ACCESS_KEY or Authorization: Swarmvia $ACCESS_KEY.
Authorization: Nthbouncer is still accepted. X-Nthpool-Key is still accepted.
On pass-through sources, always use X-Swarmvia-Key for the access key so
Authorization can carry the upstream credential.
Missing or invalid keys return 401. The message says why; see
Understand admission errors.
Session tokens
When an agent calls start_source_session, swarmvia signs a short-lived
access token for that source and returns it with its expires_at. The token
works only on the source it was issued for, with the access it was issued
with (read or write), and acts for the member who connected the agent.
- Lifetime: 1 hour by default. The agent may ask for
24hor7dwithexpires_in. A session token cannot be made non-expiring. - Revocation: a token expires on its own, so nothing needs to end a
session when the work is done. Revoke a token only if it leaked: on the
Access tab, or with
revoke_source_sessionfrom the agent. It stops working at once. - Expiry: an expired token returns
401withaccess token expired. The agent starts a new session and carries on. Tokens are not renewed in place.
A new token works on its first request: swarmvia checks its signature, so there is nothing to wait for.
Keys you create are moving to short-lived tokens too. Until then they work as they always have.
Keys that act for a member
A key minted with Acts for: Me carries your identity. The source's logs name you as the caller, and a per-member credential uses your own connected account for its calls. Keys agents mint over MCP act for the member who connected the agent. Leave Acts for off for machine keys such as CI.
When a member is removed from the org or leaves it, the keys that act for them are revoked. Machine keys are not affected.
Write blocking
Each key either blocks writes (default) or has writes allowed. With
writes blocked, the key admits GET, HEAD, and OPTIONS only. Every other
method returns 403 before the request reaches your origin, and before it
takes a concurrency slot.
On Access, under the access keys, you can add methods this origin uses for
reads. SuiteQL and GraphQL are POST. Paths belong to that method only. Leave
a method's paths blank to allow it everywhere, or list prefixes
(/services/rest/query/) so other POSTs stay blocked.
Leave writes blocked for callers that only fetch: retrieval agents, dashboards, search indexers. It means a prompt injection or a buggy loop cannot delete a record no matter what it sends.
Keys minted before this option existed have writes allowed and are unchanged.
The lock API is not affected: acquiring, renewing, and releasing a concurrency slot are coordination calls, not writes to your origin, so a writes-blocked key can still do them.
On a database source the HTTP method is not the write
gate. Every query is a POST, including a read. The write boundary is the
Postgres role swarmvia connects as. In v1 that is always the read role, so a
writes-allowed key and a writes-blocked key connect the same way. A statement
that tries to write is refused by the database (403, SQLSTATE 25006), not
by the key's method list. MCP query tools (source_query, source_schema,
source_count_rows) are read-only; there is no write tool to hide.
Origin verification (outbound HMAC)
Enable Origin verification on Sources → Access. swarmvia then signs every request it forwards so your origin can prove traffic came through swarmvia and reject direct callers.
The canonical string hashes only the first 1 MB of the body and binds
Content-Length, so large uploads can stream. The secret is a source-level
osk_… value (shown once when you enable or rotate).
What swarmvia sends upstream
After stripping every inbound X-Swarmvia-* header (callers cannot forge these),
swarmvia adds:
| Header | Value |
|---|---|
X-Swarmvia-Timestamp |
Fresh epoch seconds |
X-Swarmvia-Nonce |
Fresh UUID (new on every attempt, including retries) |
X-Swarmvia-Signature |
Hex HMAC-SHA256 of the outbound canonical string with osk_… |
Canonical string (fields joined with \n):
METHOD
PATH
QUERY
SHA256(BODY_PREFIX)
CONTENT_LENGTH
TIMESTAMP
NONCEPATH / QUERY are what the origin receives (forwarded verbatim).
BODY_PREFIX is the first min(body length, 1 MiB) raw bytes (empty body →
SHA-256 of empty input). CONTENT_LENGTH is the decimal full body length
swarmvia forwards (0 when empty).
Limits
| Limit | Behavior |
|---|---|
| Prefix window 1 MB | Only the first mebibyte is hashed; the rest streams |
Declared Content-Length on large bodies |
Preferred; bodies over 1 MB stream without a 10 MB reject |
No Content-Length and body > 10 MB |
413 payload_too_large (length cannot be bound without buffering) |
| Clock skew at origin | Match ±300 seconds |
Nonce replay defense at the origin is optional (swarmvia already mints a fresh nonce per attempt). Retry-on-429 still needs a re-readable body under 10 MB; larger bodies with a declared length run as a single streamed attempt and are still prefix-signed.
Rotation
Mint a new secret, update the origin to accept both old and new, then Activate in the dashboard. Discard a pending secret if you abort the rotation.
Worked verification code: Determine a request came from the proxy.
Caller JWT (plan-gated)
Configure a JWKS URL (and optional issuer / audience) on Access. Prefer the
X-Swarmvia-Jwt header. On pass-through sources, a bearer JWT may also be
accepted in Authorization when that does not conflict with upstream auth
needs.
Cloudflare Access (plan-gated)
Configure team domain and application audience on Access. Send the Access JWT
as Cf-Access-Jwt-Assertion or X-Swarmvia-Jwt.
Worked setup: Configure Cloudflare Zero Trust.
IP policies (plan-gated)
Attach an IP policy to the source. Requests from a blocked
range, or from outside the allowed ranges when an allow policy is attached,
receive 403 before other auth checks. Policy edits take effect within a few
seconds.