Particles UIDOCSDESIGN DECISION INFRASTRUCTUREStudioCLIMCP
Getting startedStudioTokensToken architectureThemesChanges & governanceBranches & reviewsDesign documentationFigma pluginCLIConnect AI agentsWebhooks & CI/CDSecurityPrivacyTerms
Docs / Studio / Changes & governance

Changes & governance

The token editor is govern-first: opening a project always lands you in read-only browse mode. Every edit — big or small — happens inside a named Change, so nothing gets modified by accident and every edit carries a reason from the moment it's made.

What is a Change?#

A Change is the primary editing object in the Studio. When you open a project, the whole token system is visible but read-only — you can browse every token, but the detail form stays locked until you deliberately start a Change.

Click Start a change in the topbar, or from the read-only inspector card on any token. You'll be asked for three things:

FieldWhat it is
NameA kebab-case identifier, e.g. darken-brand-ramp. Must be unique in the project.
IntentThe "why" behind the change. Stored as the working branch’s description.
Base branchWhere the change forks from. Defaults to main.

Submitting the form creates a working branch and switches you into it — the detail form unlocks and editing begins. Under the hood, a Change is 1:1 with a branch: starting a change always creates a new branch, and the change's name and intent are exactly the branch's name and description.

i

Branch names are unique per project. If you reuse a name, the form validates before submitting — the request would otherwise fail with HTTP 409 BRANCH_NAME_TAKEN.

The Change Bar#

While a change is active, a Change Bar docks at the bottom of the editor. It keeps the two things you need mid-edit — what changed, and whether it's safe to ship — always in view:

ElementWhat it shows
Change nameThe name you gave the change when you started it.
Edit count / diffA live count of tokens touched so far. Expand it for the full diff — added, modified, removed, and renamed tokens versus main.
Accessibility gateAn ambient badge showing whether every contrast pair still passes at the project’s enforcement level, evaluated against this change’s current token values.
DiscardEnds the change. The branch itself is kept — delete it separately from Branches if you don’t need it.
Request reviewOpens the token-request form to send the change for review. Disabled while the accessibility gate fails.

The gate is read from GET /v1/projects/:id/branches/:branchId/a11y-gate, which evaluates every tagged foreground/background contrast pair in the project against the branch's current token values — at WCAG AA, or AAA if the project's accessibility enforcement level is set to AAA. It runs even when enforcement is set to off: the gate is an always-on signal on the Change Bar, independent of whether the organisation has turned on blocking enforcement elsewhere.

a11y-gate response
{
  "passed": false,
  "totalPairs": 12,
  "failingPairs": [
    {
      "pairId": "018fde70-…",
      "foregroundTokenId": "018fde70-…",
      "backgroundTokenId": "018fde70-…",
      "foregroundName": "color/text-muted",
      "backgroundName": "color/surface",
      "ratio": 3.1,
      "required": 4.5
    }
  ]
}

A failing gate only blocks review — editing stays free. Fix the failing pairs, or point them at compliant tokens, and the badge clears on its own.

How it composes with branches#

Clicking Request review opens the token-request form prefilled with the change's name as the request title, and its intent shown alongside as read-only context for the reviewer. Submitting ends the change and returns the editor to main — from there, review and merge follow the same token-request lifecycle described in Branches & reviews.

A change survives reloads: it's persisted client-side, so reopening the project drops you straight back into whatever change you were working on, on the same branch, with the Change Bar already docked.

i

A branch created outside of Start a change (for example, forked from the branch selector or the CLI) behaves the same way once you open it in the editor — the editor still requires an active change to unlock editing.

Governance controls#

Beyond the editor's browse-mode gate, governance is enforced server-side per project. Everything below lives in the project's Protection settings (org admins only) and applies to every client — Studio, CLI, Figma plugin, and API alike.

ControlWhat it enforces
Protected mainDirect token writes to main are rejected (403 MAIN_PROTECTED) — including bulk paths: applied imports, CLI push, Figma push, Make Scalable, restructure, cutover, and reverts. Org-admin writes go through but are audited as hotfix_write events. New projects on Team and Business plans start protected; Free and Pro start unprotected, and admins can toggle it any time.
Required approvalsThe review quorum (1–5). A token request only flips to approved once that many distinct reviewers approve. Self-approval is banned while main is protected.
Owner rulesCODEOWNERS-style routing: pattern + optional tier + owners. Requests touching matching tokens additionally need an approval from a listed owner. An org-admin approval can override unsatisfiable ownership — audited as ownership_override.
Token policyWrite-time rules on token shape: naming pattern (with per-tier overrides), required description, semantic-must-alias, and allowed units for dimension tokens. Violations block editor writes with 422 POLICY_VIOLATION. Imports are never blocked — the import diff reports non-blocking policyWarnings instead.

The one exemption: the first import into an empty main is always allowed, so onboarding can seed a brand-new protected project before any governance is relevant.

The audit trail#

Every governance-relevant action is recorded as an event and readable at GET /v1/projects/:id/governance/events?page=&pageSize= — newest first, with the actor, branch, and detail attached. The same feed is shown in the Studio under the project rail's Activity page.

EventRecorded when
hotfix_writeAn org admin writes directly to a protected main.
gate_block_mergeA merge into main was blocked by the accessibility gate.
gate_block_releaseA release publish was blocked by the accessibility gate.
unreviewed_mergeA branch merged into an unprotected main with no approved request.
ownership_overrideAn org admin’s approval overrode unsatisfiable owner-rule routing.
← PREVIOUS
Themes
NEXT →
Branches & reviews