Vol. 001 Jeffs Brain·Documentation

Source spec/openfga

OpenFGA model

The shared FGA authorisation model used by the TS, Go, and Python OpenFGA adapters.

spec/openfga/schema.fga is the canonical authorisation model used by every SDK’s OpenFGA adapter. The three adapters (@jeffs-brain/memory-openfga, github.com/jeffs-brain/memory/go/aclopenfga, jeffs_brain_memory.acl_openfga) all encode subjects and resources with the same scheme and use the same default action -> relation map, so the model file is the single source of truth.

Schema

model
  schema 1.2

type user

type workspace
  relations
    define owner: [user]
    define admin: [user] or owner
    define member: [user] or admin
    define billing_manager: [user] or owner

type brain
  relations
    define workspace: [workspace]
    define owner: [user] or owner from workspace
    define admin: [user] or admin from workspace
    define writer: [user] or admin
    define reader: [user] or writer
    define can_delete: admin

type collection
  relations
    define brain: [brain]
    define reader: [user] or reader from brain
    define writer: [user] or writer from brain
    define admin: [user] or admin from brain

type document
  relations
    define collection: [collection]
    define reader: [user] or reader from collection
    define writer: [user] or writer from collection
    define can_export: reader

type api_key
  relations
    define workspace: [workspace]
    define owner: [user]
    define scope_reader: [brain#reader, collection#reader, document#reader]
    define scope_writer: [brain#writer, collection#writer, document#writer]

The authoritative file lives at spec/openfga/schema.fga. If this page diverges from the file, the file wins.

Resource hierarchy

workspace -> brain -> collection -> document

api_key sits beside user as a subject type and may carry scope tuples that bind it to brain, collection, or document readers/writers.

Encoding on the wire

Subjects and resources serialise as <kind>:<id> strings exactly as they do across all three adapters:

  • Subject user:alice -> { kind: "user", id: "alice" }
  • Resource brain:notes -> { type: "brain", id: "notes" }

A check call sends:

POST {apiUrl}/stores/{storeId}/check
{
  "tuple_key": {
    "user": "user:alice",
    "relation": "writer",
    "object": "brain:notes"
  },
  "authorization_model_id": "<optional>"
}

The OpenFGA server returns { "allowed": true | false, "resolution": "<reason>" }. The adapter maps that to CheckResult.

Action -> relation map

The default the three adapters use:

ActionRelation
readreader
writewriter
deletecan_delete
adminadmin
exportcan_export

If your deployed model uses different relation names, drive Provider.write / Provider.read directly with pre-computed tuples that name your relations.

Loading the model

fga model write --store-id <STORE_ID> --file spec/openfga/schema.fga

Pin the returned model id in your provider configuration (modelId in TS, ModelID in Go, model_id in Py) so checks always evaluate against the version you tested.

Versioning

The schema file carries schema 1.2 at the top. If the model evolves in a backward-incompatible way (relation rename, type removal) we’ll bump it and call out the migration in the repo changelog. Adapters never silently re-map relation names; if a check needs a different relation today, drive it through the tuple API explicitly.

See also