Connection resolution contract
This page specifies the endpoint behind the Http connection resolver. When Arc or Chronicle needs a storage connection, it calls your endpoint and asks where to connect and who to connect as. The contract is the same for every storage, MongoDB as well as SQL Server, PostgreSQL and SQLite, and it is plain JSON over HTTP, so you can implement the endpoint in any language or platform.
For how the resolver is configured on the caller’s side, see connection resolution. The calling host decides which values it sends in the request scope. Arc’s are listed under Scope values; Chronicle documents its own in storage connection resolution.
Operation
Section titled “Operation”| Method | POST |
| URL | The configured endpoint, used exactly as configured. The caller adds no path or query string. |
| Request body | application/json, UTF-8. See Request. |
| Request headers | Content-Type: application/json; charset=utf-8, plus every header configured for the resolver, such as an API key. With authentication configured, also Authorization: Bearer <token>. |
| Response body | application/json on 200 OK. See Response. |
| Timeout | 10 seconds unless configured otherwise. A timeout is a failure. |
The caller sends one request per storage, purpose and scope, and caches the answer (see Caching). Calls happen when a connection is about to be used, so your endpoint sits on the path of the first data access after a cache entry expires. Keep it fast.
Request
Section titled “Request”{ "storage": "SqlServer", "purpose": "Runtime", "scope": { "tenant": "acme" }}| Property | Type | Required | Description |
|---|---|---|---|
storage | string | Yes | The kind of storage being connected to: MongoDB, SqlServer, PostgreSql or Sqlite. Treat it as an open set and answer an unknown value with 204 or an error. |
purpose | string | Yes | Runtime for reading and writing data, Schema for schema changes such as migrations or creating tables. Use it to hand out a more privileged identity for Schema only. |
scope | object | Yes | String keys to string values identifying what is being connected, such as a tenant. Never null, possibly empty. The keys depend on the calling host. |
Ignore properties you do not recognize. New ones may be added without notice.
Scope values
Section titled “Scope values”When Arc calls the endpoint, the scope holds one key:
| Key | Value |
|---|---|
tenant | The tenant of the current request. It is Default when no tenant is set. |
Chronicle sends a different set, describing the cluster, event store or namespace it connects for. See storage connection resolution.
Response
Section titled “Response”Status codes
Section titled “Status codes”| Status | Meaning |
|---|---|
200 OK | The body is a resolution, described below. Parts present in it are applied; parts left out keep their configured value. {} changes nothing. |
204 No Content | Keep the configured connection unchanged. Use it when you have nothing to say about this request. |
| Any other status | Resolution fails, and so does the connection that needed it. The caller does not read the body and does not retry immediately; the next connection attempt calls you again. |
Redirects are followed. A 200 OK whose body is not a JSON object is a failure.
Every property is optional and may be left out or set to null.
{ "connectionString": "Server=sql-eu-2.example;Encrypt=true", "database": "tenant-acme", "schema": "acme", "identity": { "accessToken": "eyJ0eXAiOiJKV1Qi..." }, "expiresAt": "2026-10-16T12:00:00+00:00"}| Property | Type | Description |
|---|---|---|
connectionString | string | Replaces the configured connection string, in the native format of the storage: a mongodb:// or mongodb+srv:// URI for MongoDB, an ADO.NET style string for SQL Server, PostgreSQL and SQLite. |
database | string | The database to use. Replaces the database in the connection string. For SQLite this is the database file. |
schema | string | The schema to use, for storage that has schemas. Ignored where the calling host does not support placing data in a schema. |
identity | object | Who to connect as. Replaces any identity resolved before it as a whole. See Identity. |
expiresAt | string | When this answer stops being valid, as an ISO 8601 date and time with an offset. Set it whenever you return a short-lived credential. |
Property names are matched without regard to case, and unknown properties are ignored.
Identity
Section titled “Identity”| Property | Type | Description |
|---|---|---|
userName | string | User name for password authentication. |
password | string | Password for password authentication. |
accessToken | string | A bearer access token, such as one issued by Microsoft Entra ID or another OpenID Connect provider. |
Return either a user name and password, or an access token. How each storage uses them:
| Storage | userName + password | accessToken |
|---|---|---|
| MongoDB | SCRAM authentication against the connection string’s authSource, else its database, else admin | MONGODB-OIDC authentication. The caller asks you again when the driver needs a fresh token. |
| SQL Server | SQL authentication | Entra ID token authentication. The token must be issued for https://database.windows.net/. |
| PostgreSQL | Password authentication | Sent as the password, as Azure Database for PostgreSQL and Amazon RDS IAM authentication expect. |
| SQLite | Ignored | Ignored |
Two slots, one endpoint or two
Section titled “Two slots, one endpoint or two”The caller has two slots, Connection and Identity, and each can point to its own endpoint. Both endpoints receive the same request and implement this same contract. The caller applies the answer from the Connection slot first and the answer from the Identity slot on top of it, so an answer only needs to contain the parts its endpoint is responsible for. An identity-only endpoint returns only identity and expiresAt.
Caching
Section titled “Caching”The caller keeps each answer in memory, keyed by storage, purpose and scope, never by credential:
- With
expiresAt, the answer is used until one minute before that time, and then resolved again. Return a laterexpiresAtwith every fresh credential. - Without
expiresAt, the answer is used for the configured cache duration, five minutes by default. - When a connection fails to authenticate, the caller drops the cached answer, and the next connection asks you again. Rotating a credential therefore takes effect at the latest on the next failed sign-in.
A 204 is cached like an answer that changes nothing.
Security
Section titled “Security”- Serve the endpoint over HTTPS only. Answers contain credentials.
- Authenticate the caller. Prefer a short-lived bearer token over a static API key: on Azure, have the caller sign in with a managed identity or workload identity and send a Microsoft Entra ID token in
Authorization: Bearer. - Validate every token: its signature, its issuer (your tenant), its audience (your endpoint’s application ID URI) and its expiry. Require an app role, and register the endpoint as an enterprise application with assignment required, so only the identities you assigned get a token at all.
- Answer
401when the token is missing, expired or invalid, and403when it is valid but lacks the role. The caller retries a401once with a fresh token and does not retry a403; either way it fails instead of connecting. - You do not have to write the validation yourself: App Service authentication or the API Management
validate-jwtpolicy can do it in front of the endpoint. - Network isolation, such as a private endpoint or access restrictions, complements token validation; it does not replace it.
- Authorize the scope. Only return a connection that the caller may use for the tenant or namespace it asked about. Resolution chooses a destination; it is not an authorization check on the end user.
- Prefer short-lived access tokens with an
expiresAtover long-lived passwords in your answers. - Do not log response bodies or tokens. The caller never logs the credentials it receives or the tokens it sends.
OpenAPI description
Section titled “OpenAPI description”openapi: 3.1.0info: title: Connection resolution version: "1.0"paths: /: post: summary: Resolve where and as whom to connect to a storage. description: The path is whatever the resolver is configured with. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ConnectionRequest" responses: "200": description: Apply the parts that are present. content: application/json: schema: $ref: "#/components/schemas/ResolvedConnection" "204": description: Keep the configured connection unchanged. default: description: Resolution failed. The connection is not opened.components: schemas: ConnectionRequest: type: object required: [storage, purpose, scope] properties: storage: type: string description: The kind of storage. An open set. examples: [MongoDB, SqlServer, PostgreSql, Sqlite] purpose: type: string enum: [Runtime, Schema] scope: type: object additionalProperties: type: string ResolvedConnection: type: object properties: connectionString: type: [string, "null"] database: type: [string, "null"] schema: type: [string, "null"] identity: oneOf: - $ref: "#/components/schemas/ConnectionIdentity" - type: "null" expiresAt: type: [string, "null"] format: date-time ConnectionIdentity: type: object properties: userName: type: [string, "null"] password: type: [string, "null"] accessToken: type: [string, "null"]