Security Model
How GoodMem decides who is making a request and what they are allowed to do.
Security Model
Every request to GoodMem gets the same two questions: who is this, and are they allowed to do what they are asking. This page describes how GoodMem answers them. The sibling pages cover each part in more depth; this one exists so the parts have somewhere to fit.
Principals
A principal is a durable identity that can own resources. There are two kinds:
- A human user represents a person.
- A service identity represents a production workload — a retrieval service, an ingestion pipeline, an agent.
Both kinds can own spaces, hold grants, be assigned roles, and be the subject of API keys. They differ in how they authenticate and in their lifecycle, which is the subject of Users and Service Identities.
Principals are never hard-deleted. Deletion leaves a permanent tombstone: the UUID stays occupied, history stays intact, and nothing can authenticate as the deleted principal again.
Credentials
A credential is how a request proves who it is. Credentials are separate objects from principals, and the distinction carries most of the model's weight.
An API key authenticates as its subject principal. The key is a resource in its own right — it has an owner, an issuer, and a lifecycle — but when it is used, the request is the subject's request. Several keys can share one subject, which is how a service identity rotates credentials without changing who it is. Keys are described in API Keys and Ceilings.
An enrollment credential is a one-time invitation that lets a new human user obtain their first API key. It is not an API key and cannot authorize any ordinary request. See Onboard a User.
How a Request Is Evaluated
Evaluation happens in two stages, always in the same order.
Authentication. The request carries an API key in the x-api-key header.
The key must be unrevoked, the current time must fall inside its validity
window [valid_from, expires_at), and its subject must be an active
principal. If any of these fails, the request is rejected as unauthenticated —
gRPC UNAUTHENTICATED, HTTP 401 — and authorization is never consulted. When
authentication succeeds, the request principal is the key's subject.
Authorization. GoodMem resolves the operation the request performs (for
example READ_MEMORY or CREATE_SPACE) and the resource it targets, then
asks whether the request principal's authority covers that operation on that
target. A request that fails here gets gRPC PERMISSION_DENIED, HTTP 403.
A scoped API key adds a third check, described below.
Sources of Authority
A principal's live authority is the union of several sources. Any one of them is sufficient; nothing requires them to agree.
allowed(principal, operation, target) =
a direct grant to the principal covers (operation, target)
or a role assignment held by the principal covers (operation, target)
or an all-authenticated grant covers (operation, target)- Direct grants attach one operation and one selector to one principal.
- Role assignments bind a principal, a code-defined role, and a resource
the role is assigned on — the whole instance for roles like
USERandADMIN, a single space for roles likeSPACE_VIEWER. - All-authenticated grants extend an operation on a specific resource to every principal that has successfully authenticated. This is how a space is opened to everyone on the instance.
One further source sits outside the grant machinery. An active principal
always administers the access policy of the resources it owns, and the
instance owner administers access policy on every resource in the instance.
These rights follow ownership; no grant confers them and no revocation
removes them. They cover policy administration only: an owner decides who may
access the resource, but content operations like READ_MEMORY still come
from grants and roles, and the instance owner does not silently hold every
content permission.
All of this is mutable and takes effect immediately. Revoke a grant and the access is gone on the next request; regrant it and the access is back.
Details, including the delegation rules for who may change whose policy, are in Roles, Grants, and Selectors.
Scoped Keys Check Twice
An API key operates in one of two authority modes. An inheriting key uses its human subject's current authority. A scoped key carries an immutable permission ceiling, and every request through it must pass two independent checks:
subject's live authority allows (operation, target)
and
key's ceiling allows (operation, target)Each side is checked against the actual request; the two rules are never
compared with each other. Suppose a principal holds READ_MEMORY with selector ANY, and their
scoped key's ceiling contains READ_MEMORY bounded to the direct members of
space Y. Reading a memory in space Y passes both checks. Reading a memory in
space Z passes the subject check and dies at the ceiling. The grant and the
ceiling are different rules, but the requests they jointly admit are exactly
the memories of space Y.
The ceiling never adds authority. Remove the subject's READ_MEMORY grant
and both requests fail, ceiling notwithstanding.
Selectors
Every grant, role capability, and ceiling rule pairs an operation with a
selector that bounds which targets it covers: ANY (every compatible
resource), OWN (resources the principal owns), EXACT (one named
resource), or DIRECT_MEMBERS_OF (the direct members of one named container,
such as the memories of a space). The selector algebra, and which selectors
each operation supports, are covered in
Roles, Grants, and Selectors and
enumerated in the
Operations and Selectors
reference.
Not Found Before Forbidden
When a request names a resource that does not exist, GoodMem returns
NOT_FOUND (HTTP 404). When the resource exists but the caller lacks
authority, it returns PERMISSION_DENIED (HTTP 403). The two cases are
deliberately distinguishable — with one exception. Looking up a user by email
or username returns NOT_FOUND both when no such user exists and when one
exists but the caller may not read it. Email addresses are guessable, and a
403 would confirm the guess.
One Tenant per Database
A GoodMem instance is one database serving one tenant. Grants and roles partition access within the instance, and they do it precisely, but a partition is not a tenant boundary. Deployments that need hard isolation between customers run one database per customer. Placing several tenants in one database behind ACLs is possible in the way that most inadvisable things are possible; GoodMem does not support it.
Where to Go Next
Concepts: Users and Service Identities · API Keys and Ceilings · Roles, Grants, and Selectors
Guides: Onboard a User · Redeem an Enrollment · Set Up a Service Identity · Share a Space · Issue Scoped API Keys · Upgrade to the New Authorization Model
Reference: Access Control · Operations and Selectors · Built-in Roles