Tokens
Glubean Cloud has one token type. Every token starts with glb_ and is
bound to a user within an organization — it is not scoped to a single
project or target. There are two variants of the same token, differing only in
how much they’re allowed to do:
| Variant | What it can do | Reach for it when |
|---|---|---|
| Personal | Inherits your full org role/permissions (no scope list) | You want one credential that does everything you can do |
| Scoped | Limited to an explicit list of scopes (least-privilege) | CI, agents, or any automation that needs only a slice |
Default for automation: a scoped token with the minimum scopes. Reach for a personal token only for your own interactive use across the whole org.
Both variants live in your org and act as you — what they can touch is still bounded by your org membership. A scoped token simply narrows that further to the scopes you list.
How a token authorizes a request
A glb_ token does not encode a project or target. Project and target are
verified at the request path, not baked into the token. An upload, for
example, POSTs to:
POST /v1/projects/{projectId}/targets/{targetId}/runs
Authorization: Bearer glb_xxxxxxxxxxxxxxxxCloud authorizes that request by checking, in order:
- The
glb_token is valid and belongs to a user in the org. - The token carries the scope the route needs (here,
runs:write). - The
projectIdin the path belongs to that org. - The
targetIdin the path belongs to that project.
So you always provide the project + target IDs separately (via flags, env,
or glubean.yaml); the token authorizes via org membership + scope. One
glb_ token can therefore upload to any project/target in its org — as long as
its scopes allow it.
Personal token
A glb_ token with type: personal.
Where to create: Cloud webapp → Tokens → “Personal”.
What it does:
- Carries no scope list — it inherits your full org role and permissions.
- Acts as you across every project and target in the org you can already access.
- Leak blast radius = everything your org role can touch.
Use a personal token for your own interactive CLI work spanning many projects. For anything automated (CI, an agent), prefer a scoped token below — smaller blast radius if the credential leaks.
Scoped token
A glb_ token with type: scoped, limited to an explicit list of scopes.
Where to create: Cloud webapp → Tokens → “Scoped”, then pick the scopes.
What it does:
- Can do only what its listed scopes allow — least-privilege by design.
- Still bound to your user + org; it cannot exceed what your org role permits.
- Revoke it without touching your account or any other token.
- Leak blast radius = exactly the scopes you granted, across the org.
Common automation scopes:
| Scope | What it allows |
|---|---|
runs:write | Upload runs / events (CI, --upload) |
runs:read | List + read runs |
targets:read / targets:write | Read / manage targets |
contracts:write | Sync source projections with glubean sync |
apis:read / apis:write | Read / manage APIs |
collections:read / collections:write | Read / manage collections |
portal:read / portal:write | Read / manage the portal |
agent:use | Let an agent act through Cloud |
The Tokens page is the source of truth for the full scope list. It is generated from the server catalog and includes module scopes such as projects, targets, contracts, APIs, environments, data, files, taxonomy, collections, portals, Explore code tests, Library shared modules, reviews, runs, and agent use.
For glubean run --upload from CI, runs:write is enough if the project
and target IDs are explicit. Add targets:read only when the CLI needs to
resolve a default target for a non-default project. For glubean sync, use
contracts:write.
When to use glubean login
glubean login is the intended way to authenticate the CLI interactively:
it runs the RFC 8628 device-authorization flow (you approve in the browser) and
saves the resulting glb_ token to ~/.glubean/credentials.json, which the CLI
then uses as a fallback whenever no project-local credential is set.
⚠️ Not available yet. The server-side device endpoints (
/cli/device/code,/cli/device/token) are not implemented, soglubean logincannot complete the device flow today. Until they ship, authenticate by creating aglb_token in the dashboard and providing it directly — see Where to store it. Treat device login as the planned path, not the current one.
The current path:
- Cloud webapp → Tokens → create a token (personal or scoped).
- Provide it via
--token glb_…, theGLUBEAN_TOKENenv var, or.env.secrets.
Where to store it
The CLI looks for a token in this order. The first one it finds wins:
| # | Source | Best for |
|---|---|---|
| 1 | --token CLI flag | One-off / debugging |
| 2 | A profile’s upload.tokenEnv (names the env var holding its token) | Per-profile tokens in glubean.yaml |
| 3 | GLUBEAN_TOKEN env var | CI (from secret store), shell exports |
| 4 | .env.secrets file (GLUBEAN_TOKEN=...) | Local project work |
| 5 | ~/.glubean/credentials.json (via glubean login, once device login ships) | Personal fallback across projects |
A token is a secret — it never lives in a committed file, and there is no
glubean.yaml slot for the token value (only tokenEnv, the env var’s name).
Project ID resolves in this order:
--projectflag- A profile’s
upload.projectIdinglubean.yaml(when you run that profile) GLUBEAN_PROJECT_ID(env var or.env)- Your
glubean logincredential
Target ID resolves in this order:
--upload-targetflag- A profile’s
upload.targetIdinglubean.yaml(when you run that profile) GLUBEAN_TARGET_ID(env var or.env)- The project’s default target
Profile upload fields apply to glubean run --profile <name>, glubean ci run,
and glubean load --profile <name>. A bare glubean load <target> --upload
(no --profile) does not resolve a profile, so it uses flags, env/env-file
values, saved credentials, and the project default target instead.
When a profile declares upload.tokenEnv, that env var is exclusive after an
explicit --token; the CLI does not silently fall back to GLUBEAN_TOKEN.
When --project overrides a profile’s project, the profile target is not paired
with the new project; set --upload-target or GLUBEAN_TARGET_ID if you need a
specific target.
Both GLUBEAN_PROJECT_ID and upload.projectId must be the project’s
short ID (find it in Project Settings — e.g. prj_abc123), not a friendly
name. Cloud resolves the value as a project short ID, not a slug/alias lookup.
The same goes for the target ID.
One token, many destinations. Because a
glb_token isn’t tied to a project or target, the project + target IDs you supply choose the destination — Cloud just verifies the token’s org owns that project and the project owns that target (plus theruns:writescope). The upload preflight still requires both IDs to be resolvable, so always set them.
For most projects, put GLUBEAN_PROJECT_ID (and, if the project has more than
one target, GLUBEAN_TARGET_ID) in the committed .env file — they’re not
secrets, they apply to every run mode (glubean run --upload, glubean ci run, filtered runs), and every contributor uploads to the same destination:
# .env — committed
GLUBEAN_PROJECT_ID=prj_abc123
GLUBEAN_TARGET_ID=tgt_def456Use a profile’s upload block in glubean.yaml instead when a profile should
always target a specific project/target. Pair it with tokenEnv — the name
of the env var holding that profile’s token (the value stays in .env.secrets)
— so different profiles can upload to different destinations with different
tokens:
profiles:
ci:
suites: [tests, contracts]
upload:
enabled: true
projectId: prj_abc123 # destination project (a project short ID)
targetId: tgt_def456 # destination target within that project
tokenEnv: GLUBEAN_TOKEN_CI # env var holding its token; never the token itself
upload.projectAliasis the deprecated former name forprojectId— it still works (with a warning) but useprojectId.
API URL normally needs no configuration — the CLI talks to Glubean Cloud by
default. If you’re pointed at a different Glubean-hosted environment (e.g.
staging), set GLUBEAN_API_URL (env var or .env / .env.secrets) to that
environment’s host — https://api.<env>.glubean.com — and the CLI
automatically derives the matching Platform ingest host from it.
Multi-workspace setup
If you work across multiple Glubean organizations (e.g. acme-saas for your
day job, oss-side-project personal), create one glb_ token per org and keep
them isolated using .env.secrets ${VAR} interpolation against shell env:
Shell (~/.zprofile):
# One export per org token. Rotate these centrally when a token changes.
export GLUBEAN_TOKEN_ACME=glb_acme_xxx
export GLUBEAN_TOKEN_OSS=glb_oss_xxxPer-project .env (committed, no secret value):
# acme-saas/.env
GLUBEAN_PROJECT_ID=prj_acme_1
GLUBEAN_TARGET_ID=tgt_acme_1
# oss-side-project/.env
GLUBEAN_PROJECT_ID=prj_oss_1
GLUBEAN_TARGET_ID=tgt_oss_1Per-project .env.secrets (gitignored):
# acme-saas/.env.secrets
GLUBEAN_TOKEN=${GLUBEAN_TOKEN_ACME}
# oss-side-project/.env.secrets
GLUBEAN_TOKEN=${GLUBEAN_TOKEN_OSS}The ${VAR} syntax reads from your shell environment at run time, so the .env
file stays public while .env.secrets carries only a local reference to the
actual token. See Environments & Secrets for the full
env-file mechanics.
Rotation is one place: update the shell export, restart the terminal, all projects pick it up.
Lifecycle
Creating
- Cloud webapp → Tokens → choose personal or scoped (and the scopes) → name → create. Copy the token now — Glubean never shows it again.
Using
- Local dev: write to
.env.secrets(gitignored), orglubean loginonce the device flow ships. - CI: store in provider secret store, inject as
GLUBEAN_TOKENenv var.
Rotating
- Create the new token first, deploy it, then revoke the old one. Never delete the active token until the replacement is in use.
- For a token saved in
~/.glubean/credentials.json, runglubean loginagain (once available) — it overwrites the stored credential.
Revoking / leaks
- Cloud webapp → Tokens → delete the row. Effective immediately; any session relying on it stops working at the next request.
- If a token may have leaked into source control, paste, or CI logs, revoke it now and rotate.
Common mistakes
- Personal token in CI. Use a scoped token with just
runs:writeinstead — smaller blast radius if the CI runner is compromised. - Committing token to
.env(the non-secret env file). Tokens go in.env.secrets, secret manager, or shell env — never in tracked files. - Granting extra scopes to a CI upload token. CI usually only needs
runs:write. Extra scopes are extra liability. - Sharing one token across teammates. Each person should have their own. Audit logs identify the token, not the human.