# Security and spending boundaries

Arrakis credentials authorize paid operations. Keep secrets in a secret manager, not in source control, logs or agent prompts. This document describes the API contract, not an independent security certification. The console is at [/console/](/console/); current schemas are at [/openapi.json](/openapi.json).

## Credentials

- Token plaintext is returned once and stored hashed. Tokens are scoped and revocable; an expired token is rejected with 401.
- Available scopes are `read`, `rent`, `manage` and `billing`. Issuance defaults to `read`. Creating a token with a bearer requires `manage`, and requested scopes must be a subset of the caller's scopes.
- API-only setup creates a tenant and returns one `bootstrap_secret`. This secret is single-use, stored hashed and expires after 24 hours. A token request without a bearer needs both `tenant_id` and `bootstrap_secret`. Unknown tenants and wrong, expired or consumed secrets share the same 401 response. Do not hand this secret to a workload agent.
- Linking a social identity to an existing tenant requires a manage-scoped bearer. A read-only token cannot be used to gain account-management access.

## Bound unattended spending

Give each workload a `read` + `rent` token with a positive `spend_limit_usd`, a `max_rental_hours` limit and an expiry. Retain account-management access separately.

A capped token must supply `termination_hours` when renting. The window cannot exceed its maximum duration. The API reserves the full machine price per hour multiplied by that window against the cap, and rejects a request exceeding the remaining cap with 402. Committed spend is not a balance that automatically resets when a machine stops. Child tokens cannot be uncapped or exceed their parent's remaining cap or maximum rental duration.

Use a stable `idempotency_key` for each intended rental. Retrying the same request with the same key returns the same machine. A different key represents a new request. Set a shutdown deadline on every machine, save results and explicitly terminate when finished. Do not rely on a zero account balance to stop running machines.

## Tenant and money isolation

The API derives the tenant from the authenticated token. Instance lists contain only that tenant's recorded instances, not other tenants' or unrelated host-account machines. Cross-tenant instance operations are denied.

During early access a deposit request remains pending until our team confirms it. Only operator confirmation credits the prepaid balance. Ordinary tenant credentials cannot confirm deposits or create arbitrary charges. Never share an operator credential with a client or an agent.

## MCP uses the same boundaries

The remote endpoint is `$ARRAKIS_URL/mcp`. Each call uses the caller's own bearer token against the same API, retaining scope checks, spend caps, expiry and tenant isolation. MCP does not give a client extra authority. See [client setup and all eight tools](/docs/mcp.md).

## Host risk remains

Machines run with independent hosts; keep regulated data off them. Arrakis offers no SLA. Hosts and machines can fail. Use volumes for checkpoints where supported and keep a separate copy of important results on storage you control. A spend cap is not a guarantee about workload completion or availability.

## Credential rotation

1. Create a replacement token with only the scopes, budget and duration the job needs.
2. Store it in the client's secret storage and update the client.
3. Revoke the old token.
4. Review running instances separately and terminate any that should no longer incur costs.
