OpenFGA
Use OpenFGA for relationship-based MainSDK access on your existing store and model - main.yaml, adopt, testing and swapping.
OpenFGA is an open-source, Zanzibar-style engine for relationship-based access: "she can edit this document because her team owns the folder". Behind access, your OpenFGA model and tuples stay where they are, and MainSDK adds typed permissions, checks and audit in front. Pick it when permissions follow relationships between users, teams and records, or when your company already runs OpenFGA.
Interfaces it serves
Pick OpenFGA in main.yaml for any of these. Your calls stay the same, and you can swap later.
accessBuilding for 0.3Driver openfga OpenFGA
access:
driver: openfgaSwap to another provider
Before you start
- Run an OpenFGA server, or use a managed OpenFGA service, reachable from your app.
- Create a store and an authorization model, and note both IDs.
- Set up credentials for your app if your server requires them, and keep them in your secrets manager.
Configure
access:
driver: openfga
openfga: { api: https://fga.pinecart.internal, store: 01J…, model: 01J… } # shape from the requirements; not in the spec yet
models: [rebac, abac]
fresh-after-write: true
unreachable: { deny: true, cache: 30s }The access spec does not define connection keys for remote engines yet, so the openfga: line may change. Credentials take secret: references.
Use it
import { access } from "mainsdk";
export async function shareFolder(user: { id: string }, folderId: string, teamId: string) {
const folder = { type: "folder", id: folderId };
await access.relate({ type: "team", id: teamId }, "editor", folder);
return access.can(user, "folders.edit", folder); // higher consistency right after the write
}Local development and testing
mainsdk dev runs Cedar in process, so you can build without a server; run OpenFGA locally to exercise your real model. mainsdk test access runs your model tests, createTestApp() from @mainsdk/testing puts access on its fake, and chaos.on("access", { outage: true }) shows checks denying with MAIN-ACCESS-0007.
What MainSDK adds on top
- Typed permissions from your model through
mainsdk adopt access --from openfga. - Fresh after write: a check right after
access.relate()in the same request uses higher consistency. - Denies when OpenFGA is unreachable, with only a short cache you set.
- Every decision written to the audit log with the model ID.
See Permissions.
Limits and notes
- The OpenFGA driver is a phase 1 ticket in the
accessspec (milestone 0.3). mainsdk checkflags OpenFGA 1.8.0 to 1.13.1 (CVE-2026-34972) withMAIN-ACCESS-0011; upgrade OpenFGA.- New tuples are written through the job outbox, so the database row and the tuple never drift apart.
access.raw()returns the OpenFGA client;mainsdk checklists every use.
Swap to or from it
access:
driver: spicedb # was openfgaFAQ
Do I have to move my tuples? No. They stay in your store; MainSDK sits in front.
Does this work with Auth0 FGA? Auth0 FGA is managed OpenFGA, listed in the requirements as a close relative on the same path. How the driver connects to it is not specified yet.
Next
Was this page helpful?