Security model

Every connection
starts with a boundary.

Authentication proves who the client is. Authorization decides exactly which scopes it may use. Project and environment isolation surround both before realtime traffic begins.

client grantsigned · expires in 15m
identity
user_123
project
prj_acme
environment
production
scope
resource:document:842
permission
subscribe
Authorized for this scope only

The access path

No shared secret.
No implicit access.

Your backend remains the identity authority. Orastack enforces the realtime grant on every subscription.

  1. Your backendAuthenticates its own userExisting session or auth provider
  2. Client tokenEncodes narrow grantsIdentity · scope · permission · expiry
  3. Orastack edgeVerifies every requestProject and environment first
  4. Realtime scopeConnects or rejectsStable machine-readable result
user_932resource:document:842unauthorized

Core controls

Safe defaults.
Explicit behavior.

Tenant isolation

Project and environment are resolved before any customer-controlled scope identifier.

Default deny

A client can access only the scopes and permissions present in its signed grant.

Short-lived tokens

Client credentials are identity-bound, environment-bound, renewable, and intentionally narrow.

Server-only secrets

Server API keys never belong in a browser and can be named, rotated, and revoked.

Bounded resources

Payloads, subscriptions, fanout, rates, and connection queues have explicit limits.

Private by default

Payloads, state, presence metadata, user IDs, and scope IDs are treated as sensitive.

Credential separation

Two credentials.
Two different jobs.

Trusted backendora_sk_••••••••••

Server API key

Publishes events, writes state, and issues client tokens. Environment-specific and never exposed to end users.

  • Shown once
  • Rotatable
  • Revocable
Untrusted client15 minute grant

Client token

Connects one application identity with only the scopes and permissions supplied by the backend.

  • Short-lived
  • Identity-bound
  • Renewable

Data handling

Retention has a reason.

Recovery data, operational traces, and ephemeral connection state have different jobs and different lifetimes.

Data retention summary
DataLifetimePurposeBoundary
Reliable replayConfigured retentionOrdered reconnect recoveryExpired cursors return resync_required
StateUntil replaced or deletedCurrent synchronized valueAtomic replacement; versioned writes
PresenceEphemeral + TTLCollaborative awarenessNever authoritative for access or billing
Operational tracesBoundedDebugging and observabilitySampled unless deep tracing is enabled

Operational safeguards

Pressure stays bounded.

Layered limits

Organization, project, environment, key, IP, user, scope, and connection limits reduce amplification and abuse.

Backpressure

Signals coalesce, state converges, and reliable clients disconnect and recover before memory can grow without bound.

Observable denial

Authorization failures, rate limits, forced disconnects, and resync conditions expose stable codes and metrics.

Isolated environments

Development, preview, staging, and production do not share credentials, traffic, cursors, state, or usage.

Responsible disclosure

Found a security issue?

Do not disclose it publicly. Send the smallest reproducible report you can to security@orastack.dev.