Organize sites into a project
A project is boatramp’s owning + tenant boundary. It groups many sites together
with their functions and compute, and it is the tenant a managed handler’s row-level
scope resolves to. Every resource belongs to exactly one project; a reserved
default project holds everything that predates projects, so if you never name a
project you keep the single-site experience unchanged.
Use projects when you run more than one site per operator (agencies, monorepos,
multi-tenant SaaS) and want each tenant’s sites, functions, and compute isolated —
including their names. Two projects can each own a site called blog.
Before you start
- A boatramp server and an admin token. See Bootstrap authentication & mint tokens.
- On an existing (pre-0.2.0) store, migrate it first — see Upgrade a store to project scoping.
1. Create a project
boatramp project create acme --display "Acme, Inc."
boatramp project ls
create needs a slug (unique, no /); --display, --description, and --region
are optional. project ls lists every project; project show acme prints the full
record; project rm acme deletes an empty project (it refuses while the project
still owns resources, and the default project can never be removed).
2. Target a project
Every site-scoped command takes a --project flag; it falls back to
[publish].project in project.cfg, then the BOATRAMP_PROJECT environment
variable, then the default project. So these are equivalent:
boatramp --project acme sync ./dist --site blog
BOATRAMP_PROJECT=acme boatramp sync ./dist --site blog
With --project omitted you are working in default, byte-identical to how boatramp
behaved before projects existed. A site name only has to be unique within its
project, so acme/blog and beta/blog are two different sites that deploy, serve,
and run their background work independently.
3. Declare a whole project at once
boatramp apply reconciles an entire project from one manifest — see
Declare a project with apply. A minimal apply.cfg:
(
project: "acme",
sites: [
( name: "www", path: "www/dist" ),
( name: "blog", path: "blog/dist", routing: ( clean_urls: true ) ),
],
)
boatramp apply -f apply.cfg
What a project owns
- Sites — each with its own deployments, aliases, domains, and background work (consumers, crons). Same-named sites in different projects are fully isolated.
- Functions — top-level functions and their versions, triggers, invocations, and metering.
- Compute — container / micro-VM workloads.
- A tenant identity — a request routed to one of the project’s sites carries the
project as its host-asserted tenant, which is what a managed handler’s
Authorized::db()scopes rows to (nothing guest-supplied).
Content-addressed bodies (blobs, manifests, site and compute config) are shared across projects and deduplicated — a byte-identical asset uploaded by two projects is stored once, and it is only garbage-collected when no project references it.
Authorization
Cedar gains a Project resource with three project-scoped roles —
project_admin, project_publisher, project_viewer — that govern a project’s
sites, functions, compute, and workflows. A token scoped to one project cannot touch
another: a project_admin:acme token is refused (403) on project beta. Legacy
site-only grants (publisher:blog) read as publisher:default/blog, so existing
tokens keep working against the default project. See
RBAC roles, actions & resources.