Skip to content
pthmPublic

About

OpenFGA-to-PostgreSQL authorization compiler. Generates specialized SQL functions from .fga schemas that query your existing tables. Zero sync, always consistent.

Topics

Resources

Stars

104 stars

Watchers

2 watching

Forks

Latest commit

 

History

687 Commits

Folders and files

Repository files navigation

Melange


Melange

GitHub License GitHub Release Go Reference Go Report Card codecov Matrix

An OpenFGA-to-PostgreSQL authorization compiler.

Melange compiles OpenFGA authorization schemas into specialized PL/pgSQL functions that run inside your PostgreSQL database. Like Protocol Buffers compiles .proto files into serialization code, Melange compiles .fga files into SQL functions for Zanzibar-style relationship-based access control.

The generated functions read a melange_tuples view you define over your existing domain tables. There is no separate tuple store and nothing to sync.

Note

📚 Documentation: guides, API reference and examples at melange.sh.

Why Melange?

Most authorization systems run as a separate service that you keep in sync with your application data. Melange is a compiler instead.

At migration time, melange migrate parses your OpenFGA schema, analyzes each relation's patterns (direct, union, exclusion, tuple-to-userset and so on), resolves role hierarchies, and installs a specialized SQL function per relation.

At runtime, a permission check is a single SQL function call, check_permission(), which runs those functions against your melange_tuples view.

That gives you:

  • Always in sync. Checks read your tables directly, with no replication lag.
  • Transaction-aware. Checks see uncommitted changes in the same transaction, so they work in triggers and RLS policies.
  • Any language. Anything that can run SQL can check permissions. Go and TypeScript clients are optional conveniences.
  • No recursive lookups. Role hierarchies are resolved at compile time and inlined into the generated SQL.
  • OpenFGA compatible. Every Schema 1.1 feature except conditions, validated against the official OpenFGA test suite.

Inspired by OpenFGA and built on ideas from pgFGA.

Installation

macOS and Linux (Homebrew):

brew install pthm/tap/melange

Windows (Scoop):

scoop bucket add pthm https://github.com/pthm/scoop-bucket
scoop install pthm/melange

Go (1.27 or later):

go install github.com/pthm/melange@latest

Docker:

docker pull ghcr.io/pthm/melange:latest

Debian / RPM packages and archives: .deb and .rpm packages for Linux, and .tar.gz / .zip archives for Linux, macOS, and Windows, all for amd64 and arm64, on GitHub Releases. macOS binaries are code-signed and notarized.

The installation guide has step-by-step instructions for each platform, running in Docker, updating, and verifying downloads. The CLI tells you when a newer release is available; pass --no-update-check to turn that off.

Client libraries (optional):

go get github.com/pthm/melange/melange   # Go 1.24+, standard library only
npm install @pthm/melange pg             # TypeScript, Node.js 18+, pg is a peer dependency

Quick Start

1. Define your schema

model
  schema 1.1

type user

type repository
  relations
    define owner: [user]
    define reader: [user] or owner
    define can_read: reader

melange init creates a config file and a starter schema for you.

2. Map your tables to tuples

Create a melange_tuples view over the tables that already hold your authorization data:

CREATE VIEW melange_tuples AS
SELECT
  'user' AS subject_type,
  user_id::text AS subject_id,
  'owner' AS relation,
  'repository' AS object_type,
  repo_id::text AS object_id
FROM repository_owners
UNION ALL
SELECT 'user', user_id::text, 'reader', 'repository', repo_id::text
FROM repository_readers;

3. Compile the schema into SQL functions

melange migrate --db postgres://localhost/mydb --schema schema.fga

This installs check_permission(), list_accessible_objects(), list_accessible_subjects(), and a specialized check function for each relation.

4. Check permissions

SQL, from any language:

SELECT check_permission('user', 'alice', 'can_read', 'repository', 'my-repo');
-- 1 (allowed) or 0 (denied)

Go:

checker := melange.NewChecker(db)

allowed, err := checker.Check(ctx,
    melange.Object{Type: "user", ID: "alice"},
    melange.Relation("can_read"),
    melange.Object{Type: "repository", ID: "my-repo"},
)

TypeScript:

const checker = new Checker(pool);

const decision = await checker.check(
  { type: "user", id: "alice" },
  "can_read",
  { type: "repository", id: "my-repo" },
);
if (decision.allowed) { /* ... */ }

5. Generate type-safe clients (optional)

melange generate client --runtime go --schema schema.fga --output ./authz/
melange generate client --runtime typescript --schema schema.fga --output ./src/authz/
allowed, err := checker.Check(ctx, authz.User("alice"), authz.RelCanRead, authz.Repository("my-repo"))

Inspect It With Studio

melange studio opens a local, read-only web console on any melange database. See what a user can access and who can access an object, explain a decision step by step, try a grant before you write it, and read the SQL melange generated for each relation. It reads the model from the database, so it needs only a connection.

melange studio --env staging
Studio's tuple browser showing the repositories a user can access, with relation chips and an inline Explain
An Explain trace showing why a user can read an issue

Explain any check, path by path

A relation page with its definition, analysis and dependencies

Relations with their analysis and generated SQL

A matrix of every repository relation, allowed or denied for one user

Matrix of every relation for a subject

Studio binds a loopback address, opens read-only connections, and loads nothing from other hosts. It is experimental. See the Studio guide for environments, privileges and every page.

CLI

Schema
  migrate     Apply schema to database
  validate    Validate a schema
  status      Show schema, tuples, and deployed-model status
  diff        Show what changed between the deployed model and your local schema
  history     Show the migration history recorded in the database
  schema      Inspect the model deployed in a database
  explain     Show why a permission check returns true or false
  expand      Show who has a permission on an object
  doctor      Run health checks
  studio      Open a local, read-only web console for a database (experimental)

Client
  generate    Generate code from schema

Utility
  init        Initialize a new Melange project
  config      Configuration utilities
  env         Environment profile utilities
  version     Print version information
  license     Print license and third-party notices

A few common commands:

melange migrate --dry-run                      # print the SQL without applying it
melange diff                                   # compare your schema with the deployed one
melange explain user:alice can_read repository:42
melange expand repository:42 can_read
melange doctor --verbose

Commands read melange.yaml and support named environments (--env staging). See the CLI reference.

Contributing

Contributions are welcome. Melange is still evolving, and feedback, bug reports and improvements are appreciated.

  • Chat: questions, ideas and help getting started in the Matrix room.
  • Issues: bug reports and feature requests. For bugs, include steps to reproduce, expected and actual behavior, and any errors.
  • Security: report vulnerabilities through private vulnerability reporting.
  • Pull requests: fork, branch, run just test, and open a PR with a clear description. Include tests for new behavior. For larger changes, open an issue or ask on Matrix first so we can agree on the approach.

The contributing guide covers the architecture, testing and benchmarks.

Resources

  • Documentation: guides, API reference and examples
  • OpenFGA: the authorization model Melange implements
  • Zanzibar paper: Google's original authorization system
  • pgFGA: the PostgreSQL FGA implementation that inspired this project

License

MIT License. See LICENSE for details.

About

OpenFGA-to-PostgreSQL authorization compiler. Generates specialized SQL functions from .fga schemas that query your existing tables. Zero sync, always consistent.

Topics

Resources

Stars

104 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages