Skip to content

Authorization

Authorization is one invariant: every external read runs against an immutable database value filtered for the verified principal before query semantics begin.

A deployment verifies a JWT’s signature, issuer, audience, lifetime, and subject. The token identifies a principal across the deployment; it does not select a database, catalog, or policy.

Trusted routing selects a server-owned database and catalog. Callers cannot combine an internal database with another catalog.

Ramose compiles code-defined read rules into a predicate over facts. The current, historical, or history view is filtered first. Query, relation traversal, pull, aggregate, ordering, limit, and live synchronization operate only on the filtered result.

That order prevents hidden data from changing visible answers indirectly. A hidden row cannot alter a count, make a negative condition fail, displace a visible row from a limit, or reveal itself through a missing reference.

Entity, trait, and field rules can each narrow access. A trait cannot grant a composer hidden by its concrete entity rule; a field cannot reopen a hidden parent. Deny rules override allows at the same focus.

Read rules may use stable roles, claims, subject identity, the current resource, the principal entity, and bounded relation paths. Policy is inert schema-checked data applied to the named schema, not arbitrary request-time code.

Read rules do not authorize mutations. Every owned operation has its own session-only allow or deny decision. Targeted operations also require a visible compatible target in the current filtered database. The server repeats those checks at commit time; discovery and client method presence are not authority.

Errors and metadata intentionally omit internal database ids, catalog keys, hashes, transaction ids, storage layout, policy internals, hidden names, and hidden-only timing signals. Missing and unauthorized resources are indistinguishable when a richer answer would disclose authority.