companies row and a
child project is a tenant_users row, so company_id, tenant_user_id,
/v1/company and /v1/users/:user_id/... all keep working.
The default project
Created for each organization by migration059, which backfilled every pre-existing
account kit, child project, connection, vault entry, approval, activity event, and
agent into it (older untouched organizations get it lazily, on first read). It is not
deletable and not archivable — it is where every un-projected caller lands.
A row whose project_id is NULL belongs to the default project: the column is
nullable on purpose, so a write from an un-taught path is still visible exactly where
its organization can see it — never invisible, never another project’s.
Selecting a project
Five ways, in this order:- The path —
/v1/projects/:project_id/...in front of any data-plane route./v1/projects/<id>/users/<child_id>/vaultis/v1/users/<child_id>/vaultscoped to that project. - The
X-Naive-Project-Idheader — same effect without changing the route. Treated as untrusted input and validated against the key’s organization, like any path param. - The API key’s pinned project (
active_project_id), set when the key is created. - The project of the key’s sealed child project, if it is sealed to one —
what makes a key sealed into a non-default project usable without also
pinning the project. A child project named in the path does not select
a project this way: naming a child of another project without selecting that
project is a
404, not a door into it. - The organization’s default project.
default and current mean the caller’s own project: the
key’s pinned project when it has one, otherwise the organization’s default
project. They are a way to decline to name a project, not a way to name the
default one — a pinned key writing default still acts inside its pin.
The cross-project guard
Subject resolution now asserts both axes. After resolving a candidate child project, the resolver requires:What is project-scoped, and what is organization-wide
Deployments were already namespaced by
(organization, project) before this
layer existed — the IaC project: string is the same project key, now first-class.
See Infrastructure as code.
Using it
naive.forUser(id), naive.users, naive.accountKits,
naive use <child_project_id>, /v1/users/..., /v1/company, and MCP tools
called with user_id alone.
See Projects (getting started) for the walkthrough.