MemorySyncMemorySync
Core Concepts

Projects

A project is the sub-scope inside a tenant. Memories live in projects; queries and writes target one project at a time. This page covers the model, how the project id is resolved on every request, and the difference between header-driven and key-pinned scoping.

Project model fields

FieldNotes
project_idString, unique, indexed. Format: "proj_" + 16 hex characters.
tenant_idFK to Tenant.tenant_id. Hard ownership.
nameHuman label.
is_defaultTrue for the auto-created project on a fresh tenant.
memory_countMaintained counter.

The default project

Every tenant starts with one project marked is_default=true. If a request omits a project context entirely, the default project is used — but only on routes that do not enforce a project scope. Project-scoped routes still require an explicit signal.

How <code>project_id</code> is resolved on a request

  1. 1The middleware reads the X-Project-ID header, validates its format, and checks ownership against the resolved tenant.
  2. 2If the header is missing, the middleware checks whether the active API key is project-locked (its project_id column is set).
  3. 3If neither source produces a project, the project-enforcement dependency raises 400 on routes that require one.
  4. 4If both produce a project, the header takes precedence — but ownership is still checked.

Project-locked API keys

When you create an API key with POST /org/api-keys you can set project_id. A key with a project_id satisfies project-scope enforcement automatically — callers can omit X-Project-ID on every request.

Use it for
One service, one project. Cleaner request shape, fewer chances of header drift.
  • Memory.project_id is a nullable FK to Project.project_id with ON DELETE SET NULL.
  • Deleting a project does not delete its memories — they go org-wide (project_id = null) until you re-assign them.
  • Project.memory_count is maintained by the platform; you do not write to it.

CRUD routes

RouteAction
GET /org/projectsList projects in the active tenant.
POST /org/projectsCreate a new project (allocates a fresh project_id).
PATCH /org/projects/{project_id}Update name or default flag.
DELETE /org/projects/{project_id}Soft-delete; memories drop to org-wide.

What projects do not do

  • Projects do not provide isolation strong enough to substitute for tenants — cross-project access inside a single tenant is allowed by the model.
  • Projects do not bill independently — quota and usage count at the tenant level.
  • Projects do not have nested children.