Multi-project
Why projects
Section titled “Why projects”A project is the tenancy boundary in z4j. Agents, tasks, events, schedules, memberships - all scoped to a project.
Use one project per:
- Environment (
staging,production). - Business unit (
marketing-queue,billing-queue). - Customer (if you're running z4j for your customers).
Creating a project
Section titled “Creating a project”- First project is created automatically at first-boot setup.
- Subsequent projects: API
POST /api/v1/projects(requires org-level admin).
curl -X POST https://z4j.example.com/api/v1/projects \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{"slug": "billing-prod", "name": "Billing (production)"}'slug is required. The bearer token is a personal API key; a cookie session can call the same route but must also send the CSRF header.
Agent to project binding
Section titled “Agent to project binding”When you mint an agent token, you pick the project. The token is bound - an agent authenticated with token_A can only write to project_A.
Membership model
Section titled “Membership model”A user can belong to many projects with different roles per project:
| User | project: staging | project: billing-prod |
|---|---|---|
| alice | admin | admin |
| bob | operator | viewer |
| charlie | viewer | none |
See RBAC.
Project switcher
Section titled “Project switcher”The dashboard's navigation rail (the left sidebar) shows the active project. Switching reloads the tasks/events views with the new scope.
Audit log
Section titled “Audit log”Audit rows carry project_id. Export is per-project through the project's own route, GET /api/v1/projects/{slug}/audit?format=csv; there is no project_id query parameter.
Archiving a project
Section titled “Archiving a project”DELETE /api/v1/projects/{slug} is a soft archive, not a hard delete. It
requires a system administrator, CSRF protection, and a fresh MFA check. The
brain refuses to archive the last active project.
Archiving sets is_active=false and hides the project from ordinary list
views. Agents, tasks, events, schedules, memberships, and audit rows remain in
the database. There is no public hard-delete or typed-confirmation workflow.
The project's agents are disconnected as part of the archive: live sockets
close with the revoked-agent close code on every replica, new handshakes are
refused, and the long-poll routes answer 403 with error: project_inactive.
Their tokens stay valid, so reactivating the project needs no re-minting; the
agents reconnect on their next retry.
Cross-project queries
Section titled “Cross-project queries”Not supported. Each project is isolated. If you need cross-project metrics, export audit and events via API and aggregate externally.