Skip to main content

Authentication

Every endpoint except the /health* family requires a tenant API key sent in the x-api-key header.

curl -sS \
-H "x-api-key: $CONSTELLATION_API_TOKEN" \
"https://api.constellation.space/topology?freshness_seconds=900"

There is no OAuth flow, no token exchange, and no Authorization: Bearer support on the customer surface. The key is the credential.

How keys are issued and validated

Keys are provisioned by the platform team, per environment, in AWS Secrets Manager under constellation-os/<env>/api-keys. The API validates the presented key against a SHA-256 hash map loaded at startup; the plaintext key material is scrubbed from the process environment after parsing. Validation is constant-cost and adds no measurable latency.

Practical consequences:

  • Keys are environment-specific. A dev key returns 401 on prod.
  • New keys and rotations go through the platform team; there is no self-serve key mint against the platform today. Keys generated locally in the console browser are not registered with the platform and return 401 until provisioned. See Integration bundle.

Tenant scoping comes from the key

The tenant for a request is derived from the validated key, never from the hostname. Calling a dedicated tenant domain such as warpware.api.constellation.space with a key for a different tenant does not grant access to that tenant's data. Every read is filtered to your tenant and every telemetry write is stamped with your tenant server-side.

Tenant-related outcomes after a key validates:

StatusBodyMeaning
403{"error": "tenant_disabled"}The tenant exists but has been disabled.
404{"error": "unknown_tenant"}The key maps to a tenant the environment does not know.
503{"error": "tenant_unavailable"}The key authenticated but the tenant's data plane is not registered or reachable in this environment.

Failed-auth lockout

Authentication failures are tracked per client IP in an in-process LRU (capacity 10,000 IPs):

  • 5 failures within a 300 second window locks the IP out for 900 seconds.
  • Each successful authentication decays the failure counter by 1.
  • The lockout gate runs before key verification, so a locked-out IP gets 429 even when it presents a correct key.

A locked-out request returns:

{
"error": "auth_lockout",
"retry_after_seconds": 842
}

with HTTP status 429 and a Retry-After header. Honor the header; hammering through a lockout only resets the clock. A misconfigured agent retrying a bad key in a tight loop will lock out its own gateway IP, so fail fast on 401 in your clients instead of retrying.

Other auth error shapes:

StatusBodyMeaning
401{"error": "auth_failed"}Missing or invalid x-api-key. May include a reason field.
400{"error": "tenant_required"}The request could not be associated with a tenant.
503{"error": "operator_auth_unavailable"}Operator JWT verification is down; only affects the operator-only /rules* surface.

Key storage guidance

  • Keep the key in an environment variable (CONSTELLATION_API_TOKEN is the convention used by the console integration bundle) or a secret store such as AWS Secrets Manager. Never commit it, never log it, never put it in a URL query string.
  • Use one key per integration so a leak has a narrow blast radius and rotation is a one-system change.
  • On 401 auth_failed, stop and alert; do not retry. Automatic retries against a revoked or wrong key trip the lockout and take down healthy traffic from the same IP.
  • The fleet agent reads its key from ~/.constellation/config.toml. Keep that file mode 0600 and off shared filesystems.

Verifying a key

There is no dedicated key-introspection endpoint. The standard probe is an authenticated GET /topology with a small freshness window; a 200 proves the key, the tenant scoping (tenant_key in the response), and the data plane in one call. See Health and the connection smoke test example.