Last updated 2026-06-29

Workspaces

The Zanzibar-inspired authorization layer for workspaces, groups, and fine-grained access. Run a single container, point it at Postgres, and you have a relation-tuple ReBAC engine plus a workspace, membership, and invitation product surface — all over Connect-RPC on HTTP/JSON.

This is the workspace/authz service from identity's ADR-0001 two-service split. Identity authenticates the end user and mints an access token; the token is verified at your product edge. Your product backend then calls Workspaces with a trusted service credential, passing the acting user as an explicit field. The two services never share a table.

What you get

Relation-tuple engine

A Zanzibar-style ReBAC core. Write tuples, then ask Check "may this user do this?" and Expand "who can?" Userset rewrites are evaluated transitively and are cycle-safe.

Personal & team workspaces

Every user owns exactly one auto-provisioned personal workspace; they create team workspaces for collaboration, with members at a role (owner ⊃ admin ⊃ member ⊃ guest). The Claude/ChatGPT model — serves B2C and B2B alike.

Nestable groups

Reusable membership sets, separate from workspaces. A group's members can themselves be groups, so group:all-eng#member can contain group:backend#member — resolved transitively at Check time.

Multi-tenant projects

project_id is the isolation shard. Every workspace, group, invitation, and tuple is scoped to a project. Run one B2C product as a single project, or shard a B2B platform per customer.

In 30 seconds

Every RPC is an HTTP POST to /workspace.v1.<Service>/<Method> with a JSON body, a Bearer service token, and — for actions — the acting user as a field. Ask whether bob is an admin of a workspace:

Check
curl -X POST http://localhost:8080/workspace.v1.AuthzService/Check \
-H "Authorization: Bearer $WS_SERVICE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"namespace":"workspace","object_id":"acme","relation":"admin","subject_user_id":"bob"}'
# => { "allowed": false }

Where to next