# Public API Contract

The public `/api/v1` surface is owned by Open Orchestra. It exposes Orchestra
DTOs and request semantics only; it must not expose provider ids, raw vendor
payloads, provider credentials, or backend base URLs.

## Workspace And Principal Isolation

- Public API data must be isolated by project workspace.
- Public API data must also be bound to a principal so threads and messages from
  one user are not listed or read by another user in the same project.
- The current `/api/v1` slice uses an explicit local-development auth adapter
  that reads `x-orchestra-user-id` and optional `x-orchestra-user-name` headers.
  This is not a production IAM mechanism; production deployments must replace
  the adapter with session/API-key authentication before public exposure.
- Routes pass a server-bound auth context into services. Tenant, workspace,
  task, run, phase, session, actor, provider, model, and backend URL values from
  the request body or query are rejected and are never authoritative.
- Storage scope is computed server-side from the workspace root plus principal,
  so users in the same workspace cannot list, read, or write each other's public
  threads through `/api/v1`.

## Bounds, Rate Limits, And Idempotency

- Public JSON request bodies are bounded to 64 KiB.
- Public string fields and headers are bounded before execution: thread titles,
  message text, request ids, thread ids, cursors, idempotency keys, local-dev
  principal ids, and display names all have explicit maximum lengths.
- Side-effecting message writes require `Idempotency-Key`. Thread creation may
  use `Idempotency-Key`; replays are scoped by workspace and authenticated
  principal, and conflicts return the stable `idempotency_conflict` error code.
- `/api/v1` currently enforces process-local per-principal rate limiting and
  concurrent request admission. Durable, shared rate-limit and idempotency
  storage is still required before a multi-process or public production rollout.
- Rate limited requests return `rate_limited` with HTTP 429 and a sanitized
  message.

## Transport Security

- Public deployments must terminate TLS 1.2+ at the Open Orchestra boundary.
- Plain HTTP is acceptable only for local development on loopback interfaces.
- Provider traffic, secrets, and backend topology remain internal and must not
  be exposed through public API responses.
