Concepts
Workspaces, teams, apps, deployments, channels, grants — the model behind VibeHost.
The shape of an account
Workspace ─── billing + admin boundary, owns apps
├── Workspace members (owner / admin / member)
├── Teams ─── member sub-groups within the workspace
│ └── Team members (owner / manager / member)
└── Apps ─── one project, many deployments
├── primaryTeamId ─── nullable, the team that "leads" the app
├── App-team grants ─── viewer / deployer / admin
├── App-email grants ─── same roles, addressed by email
└── Channels
├── production
└── preview-dark-mode
└── Deployment (live)A few things this diagram does not say but you'll feel anyway:
- Apps are owned by the workspace, not by a team. A team's relationship to an app is granted, not owned.
- Teams are how you group humans, not how you group apps. They exist so you can grant access to many apps with one grant.
- A user can belong to multiple workspaces and multiple teams within each.
Workspaces
The billing and admin boundary. A workspace owns one plan, one bill, one set of platform-admin overrides. It also owns every app, team, deployment, and audit log row inside it.
Workspace member roles:
| Role | What it unlocks |
|---|---|
member | Be in the workspace; see what app/team grants give you |
admin | Create teams, manage workspace settings, see all apps |
owner | Plus billing, plan changes, workspace deletion |
A user can belong to multiple workspaces — switch with vibehost whoami to inspect, or pass --workspace to any command.
Teams
A way to group members inside a workspace. Teams exist so you can issue one grant ("the Web team can deploy to all marketing apps") instead of N email grants.
Team member roles:
| Role | What it unlocks |
|---|---|
member | Be in the team; receive whatever grants the team has |
manager | Manage team members + settings |
owner | Plus delete the team |
For 1–3 person workspaces, one team is usually enough. Add more when you want grant isolation between sub-groups (e.g. contractors vs full-time, web vs mobile).
Apps
One project, one deploy target. Static or Next.js. Created with:
vibehost app create my-site # default runtime: static
vibehost app create my-app --runtime nextjsApp name rules: [a-z][a-z0-9-]*, 2–40 chars, unique within workspace.
Optionally tag an app with a primaryTeamId — surfaces in the dashboard as "owned by the Web team", but doesn't gate access by itself. Access is gated by grants (next section).
Grants — how access actually works
To do anything on an app, a user needs an app-level grant. Grants are additive: if both your team and your email have grants, the effective role is the max.
Two grant tables:
- app_team_grants —
(appId, teamId, role). Every member of the team picks up the role. - app_email_grants —
(appId, email, role). Targets one person; the email need not match an existing user (invite-before-signup works).
App-level roles:
| Role | Can do |
|---|---|
viewer | View deployments, see logs |
deployer | Above + push new deploys, promote, rollback |
admin | Above + manage grants, settings, custom domains |
Plus visibility (public / workspace / private) and optional password / share-link gates. All gates AND-compose, never short-circuit (Hard Rule #8).
See Grants and visibility for the full model.
Deployments
An immutable artifact + a runtime config. Every deploy gets:
id— opaque deployment IDimmutableUrl— permanent URL that always points to this exact version (https://<deploy-id>.vibehost.space)url— alias URL that moves with the live deployment on this channel
Rolling back doesn't mutate or delete the old deployment — it just points the channel alias at the older immutableUrl. The previous deploy keeps its own URL forever (until you app delete or the workspace is pruned).
Channels
Preview deploys are channels, not git branches. The server has zero git knowledge.
vibehost deploy --channel production
vibehost deploy --channel pr-42
vibehost deploy --channel dark-mode-experimentEvery channel gets its own alias URL. Each channel runs independently — a deploy in dark-mode never affects production (Hard Rule #5).
Promote between channels without re-uploading:
vibehost promote --from pr-42 --to productionPersonal access tokens
Long-lived bearer tokens for CI and external integrations. Scoped per resource group, optionally bound to a specific workspace and team.
See Personal access tokens for the full scope list and rotation guidance.
How the pieces talk
You (CLI) Your agent (MCP) CI (PAT)
│ │ │
└─── HTTPS, Bearer ─────┴─── HTTPS, Bearer ─┘
│
api.vibehost.com/api/v1
│
┌────────┴───────────┐
│ │
Postgres Cloudflare R2 (assets)
(control plane) │
│ │
▼ ▼
Cloudflare Workers for Platforms
(one isolate per tenant Next.js app;
dispatcher serves static from R2)
│
*.vibehost.space (live URLs)Control plane (API, dashboard, Postgres, Redis) runs on GKE. Tenant apps run on Cloudflare Workers — no shared process, no container escape surface. Everything goes through the same REST API; CLI, MCP, and dashboard all call the same endpoints with the same auth checks.