Groundfloor Docs

Dataplane Authorization Brief

How Control Plane auth relates to Dataplane — projection scope, SpiceDB boundaries, and integration rules.

This page explains the authorization boundary between Control Plane and Dataplane. It is written for teams building on or integrating with Dataplane.

TL;DR

LayerDataAuth storeProjection needed?
Control PlanePlatform metadata (~10 Postgres tables)Direct SpiceDB gRPCNo — scale is thousands of rows, not millions
DataplaneCustomer business dataSpiceDB + optional projectionYes at scale

Rule for integrators: Federated apps and the Customer Portal call Control Plane APIs. Do not call Dataplane directly from the browser.

What Control Plane stores

Dedicated Postgres database gf_controlplane:

TablePurpose
usersPortal user identity (synced from IdP)
accountsBilling / org units
workspacesTenant boundaries
environmentsdev / staging / prod
membershipsUser → scope role grants
audit_eventsAppend-only audit (30d retention)
provisioning_runsSaga state
processed_idp_eventsWebhook idempotency

Customer collections, documents, and queries live in Dataplane — accessed through Control Plane proxies like Data Vault.

SpiceDB usage

Control Plane uses the portal_* namespace in a shared SpiceDB instance with Dataplane tenant types. Prefixing prevents schema collisions.

OperationPath
Schema read/writeDirect authzed gRPC
CheckPermissionDirect authzed gRPC
WriteRelationshipDirect gRPC + DLQ on failure

Dataplane's /transaction rebac_write op is not in the Control Plane write path after the storage cutover.

Why Control Plane skips projection

Permission projection materializes SpiceDB tuples into customer databases so SQL queries can filter by permission at scale.

Control Plane does not need this because:

  • List endpoints use the memberships table as a permission proxy
  • Per-record checks are O(1) SpiceDB round-trips — fine for admin UI QPS
  • Row counts are thousands, not millions

Projection remains a customer-data feature for Dataplane tenants.

Read patterns

Endpoint styleSpiceDB on list?Notes
GET /v1/workspacesNo — membership joinShows workspaces you belong to
GET /v1/workspaces/{id}YesPer-record read check
Data Vault queryYesWorkspace-scoped proxy to Dataplane

Write patterns

  1. Postgres transaction commits the data row
  2. write_spicedb_or_dlq() writes the tuple after commit
  3. DLQ drain retries failures; drift reconciler heals membership tuples hourly

Integration implications

  • Scope projection design to customer-tier datastores only
  • Do not build a Control Plane Postgres projection adapter
  • Use Control Plane /v1/workspaces/{id}/vault/… for customer data from apps
  • For ReBAC debugging on customer data, Dataplane may expose operator trace endpoints

On this page