Global API & Protocol Specs

A deep dive into the strict HTTP contracts, the Filter AST query translation, and the HMAC-SHA256 webhook delivery systems that power the Aeion OS headless BaaS.

Protocol & Performance Metrics

Cursor Pagination

O(1) latency on multi-million row tables

Webhook Window

Strict 5-minute replay protection

Relation Depth

Capped at 5 levels via `?depth=` to bound population queries

SLA Target

< 50ms p95 latency for Weight-1 endpoints

1. The Filter AST Query Engine

Aeion eliminates the need for backend developers to write custom search endpoints. - Bracket Notation & JSON Transport: The Global API supports complex queries natively. Clients can use bracket notation (?where[price][gt]=100&where[status][in]=paid,refunded) or URL-encoded JSON payloads. - Schema-Validated SQL Translation: The query engine intercepts the filter string, parses it into an AST, validates the requested fields against the collection's compiled schema (rejecting unknown fields to prevent SQL injection/sniffing), and maps the safe AST directly to a highly-optimized, parameterized SQL query. - 30+ Operators, One Grammar: The same AST vocabulary works on every collection — string (equals, contains, starts_with, in, ilike, search), numeric (gt, gte, between), array (overlaps, contains_any), JSON (json_contains, has_key), date (before, older_than), and logical (and, or, not) — so a client that learns the filter grammar once can query any table without a bespoke endpoint per collection. - Cursor Pagination Mastery: Standard OFFSET pagination becomes exponentially slower as table sizes grow. Aeion enforces cursor-based pagination for high-volume endpoints, passing a Base64-encoded cursor (a stable sort key + row identifier) to keep database lookups at constant time regardless of page depth. - `?explain=true` for Transparency: Any query can be introspected — append explain=true and the engine returns the generated SQL plus warnings (missing index, wide scan) instead of executing blindly. Developers debug a slow filter against the real query plan rather than guessing.

2. The Two-Step Authentication Flow

Aeion handles enterprise identity through a strict isolation paradigm separating Global Identity from Tenant Scope. - Step 1: System Auth: The client calls POST /api/auth/login using their global identity. The OS returns a stateful Refresh Token. - Step 2: Tenant Selection: Because a user may belong to multiple tenants, they must call POST /api/auth/select-tenant, providing the Refresh Token and the target tenantId. The OS evaluates their membership and mints a highly-optimized, stateless JWT scoped to exactly the permissions (e.g., *:* for full access, or commerce:read for a single module) allowed for that specific tenant context. - Why Two Steps, Not One: Folding tenant scope into the login credential would force a re-login every time a user switched organizations and would leak the full permission matrix into a long-lived token. Separating a stateful Refresh Token (global identity, revocable) from a short-lived stateless JWT (tenant-scoped, self-verifying) means the hot path — every subsequent API call — validates a signature with no database round-trip, while tenant switching is a single cheap exchange rather than a full re-authentication. - Machine Identities: Server-to-server callers skip the interactive flow entirely and use scoped API keys created via /admin/auth/api-keys — each key carries its own permission grants, per-key rate limit, optional IP allowlist, and rotation path, so a leaked integration key is contained to exactly what it was provisioned to touch.

Frequently Asked Questions

No. All four protocols share one RBAC engine, one audit log, one rate-limiter, and one error envelope. A collection registered once is exposed through every protocol, and an authorization rule is written in exactly one place — so there's no risk of GraphQL enforcing a permission that REST forgot.

Returning `403 FORBIDDEN` confirms a record exists, which lets an attacker map internal IDs by enumeration. When the RBAC engine denies a read on `GET /api/v1/{slug}/:id`, the API returns a strict `404 NOT_FOUND` — the "Do Not Leak Existence" rule — so existence and access are indistinguishable to a caller without the right role.

Each outbound event is signed `HMAC-SHA256(timestamp + "." + body, sharedSecret)` and carries an `x-aeion-timestamp` header. The receiver recomputes the signature over the exact payload and compares with `timingSafeEqual`, then rejects any request whose timestamp is outside the 5-minute window — closing both forgery and replay in one check. The `verifyAeionWebhook` snippet above is the reference implementation.

No — limits are tiered by operation cost, not request count. A Redis-backed sliding window defaults read endpoints to 900 requests/minute per tenant and writes to 300/minute, with separate lower presets for auth, password-reset, and bulk/batch operations. A collection can override the platform defaults with an explicit `governance.rateLimit` config, and `429` responses carry `Retry-After` so a well-behaved SDK backs off precisely.

Yes. The surface is pinned at `/api/v1`; breaking changes only ship behind `/api/v2` with a migration window, field additions to existing endpoints are non-breaking by design, and the whole surface is described by an auto-generated OpenAPI 3.1 spec you can codegen a typed SDK from rather than hand-rolling a client per collection.

Composes with the rest of the OS