melange

module
v0.6.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 31, 2026 License: MIT

README

Melange

GitHub License GitHub Release Go Reference Go Report Card

An OpenFGA-to-PostgreSQL authorization compiler.

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

The generated functions query a melange_tuples view you define over your existing domain tables—no separate tuple storage or synchronization required.

Why Melange?

Traditional authorization systems require syncing your application data to a separate service. Melange takes a different approach: it's a compiler, not a runtime service.

How it works

Compile time — When you run melange migrate, the compiler:

  • Parses your OpenFGA schema
  • Analyzes relation patterns (direct, union, exclusion, etc.)
  • Computes transitive closures for role hierarchies
  • Generates specialized SQL functions for each relation
  • Installs the functions into PostgreSQL

Runtime — Permission checks are simple SQL function calls:

  • check_permission() executes the generated functions
  • Functions query a melange_tuples view you define over your domain tables
  • PostgreSQL's query planner optimizes the specialized functions

This compilation model gives you:

  • Always in sync — Permissions query your tables directly, no replication lag
  • Transaction-aware — Permission checks see uncommitted changes in the same transaction
  • Language-agnostic — Use from any language that can call SQL (Go, TypeScript, Python, Ruby, etc.)
  • Optional runtime libraries — Convenience clients for Go and TypeScript, or use raw SQL
  • Single query — Role hierarchies resolved at compile time, no recursive lookups at runtime

Inspired by OpenFGA and built on ideas from pgFGA.


[!NOTE] 📚 Full Documentation Visit melange.sh for comprehensive guides, API reference, and examples.


Installation

CLI

Homebrew (macOS and Linux):

brew install pthm/tap/melange

Go install:

go install github.com/pthm/melange/cmd/melange@latest

Pre-built binaries: Download from GitHub Releases (macOS binaries are code-signed)

Updating:

# Homebrew
brew upgrade melange

# Go install
go install github.com/pthm/melange/cmd/melange@latest

Melange automatically checks for updates and notifies you when a new version is available. Use --no-update-check to disable.

Optional: Go Runtime Library

If you want to use the Go convenience library instead of raw SQL:

go get github.com/pthm/melange/melange

The runtime module has zero external dependencies (Go stdlib only).

Quick Start

1. Define Your Schema

Create a schema file (schema.fga) using the OpenFGA DSL:

model
  schema 1.1

type user

type repository
  relations
    define owner: [user]
    define reader: [user] or owner
    define can_read: reader
2. Compile Schema into SQL Functions

Run the migration to generate specialized PL/pgSQL functions:

melange migrate --db postgres://localhost/mydb --schemas-dir ./schemas/

This generates optimized SQL functions like check_permission(), list_objects(), and specialized check functions for each relation.

3. Define Your Tuples View

Create a melange_tuples view that exposes 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;
4. Check Permissions

With Go runtime (optional):

import "github.com/pthm/melange/melange"

checker := melange.NewChecker(db)
decision, err := checker.Check(ctx,
    melange.Object{Type: "user", ID: "alice"},
    "can_read",
    melange.Object{Type: "repository", ID: "my-repo"},
)
if !decision.Allowed {
    return ErrForbidden
}

Or use raw SQL from any language:

SELECT check_permission(
  'user', 'alice',
  'can_read',
  'repository', 'my-repo'
);
-- Returns: true/false
5. (Optional) Generate Type-Safe Client Code

For better type safety, generate constants and constructors:

melange generate client --runtime go --schema schema.fga --output ./authz/
import "yourapp/authz"

checker := melange.NewChecker(db)
decision, err := checker.Check(ctx,
    authz.User("alice"),
    authz.RelCanRead,
    authz.Repository("my-repo"),
)

CLI Reference

melange - PostgreSQL Fine-Grained Authorization

Commands:
  generate client  Generate type-safe client code from schema
  migrate          Apply schema to database
  validate         Validate schema syntax
  status           Show current schema status
  doctor           Run health checks on authorization infrastructure
Generate Client Code
# Generate Go code
melange generate client --runtime go --schema schema.fga --output ./authz/

# With custom package name
melange generate client --runtime go --schema schema.fga --output ./authz/ --package myauthz

# With int64 IDs instead of strings
melange generate client --runtime go --schema schema.fga --output ./authz/ --id-type int64

# Only generate permission relations (can_*)
melange generate client --runtime go --schema schema.fga --output ./authz/ --filter can_

Supported runtimes: go (TypeScript coming soon)

Apply Schema to Database
# Apply schema
melange migrate --db postgres://localhost/mydb --schemas-dir ./schemas/

# Dry run (show SQL without applying)
melange migrate --db postgres://localhost/mydb --schemas-dir ./schemas/ --dry-run

# Force re-apply even if unchanged
melange migrate --db postgres://localhost/mydb --schemas-dir ./schemas/ --force
Validate Schema
melange validate --schema schema.fga
Check Status
melange status --db postgres://localhost/mydb
Health Check
melange doctor --db postgres://localhost/mydb --verbose

Using from Any Language

Melange generates standard PostgreSQL functions, so you can use it from any language that can execute SQL:

# Python
cursor.execute(
    "SELECT check_permission(%s, %s, %s, %s, %s)",
    ('user', 'alice', 'can_read', 'repository', 'my-repo')
)
# Ruby
DB.fetch(
  "SELECT check_permission(?, ?, ?, ?, ?)",
  'user', 'alice', 'can_read', 'repository', 'my-repo'
).first
// TypeScript (with pg or any SQL client)
const result = await db.query("SELECT check_permission($1, $2, $3, $4, $5)", [
  "user",
  "alice",
  "can_read",
  "repository",
  "my-repo",
]);
Optional Runtime Libraries

For convenience, Melange provides type-safe runtime clients:

Language Runtime Package CLI Flag Status
Go github.com/pthm/melange/melange --runtime go Implemented
TypeScript @pthm/melange --runtime typescript Planned

These libraries provide a nicer API but are completely optional. See clients/ for language-specific implementations.


Contributing

Contributions are welcome! Here's how to get started:

  1. Fork the repository and clone locally
  2. Create a branch for your changes
  3. Run tests with just test
  4. Submit a pull request with a clear description

Please ensure your code:

  • Passes all existing tests
  • Includes tests for new functionality
  • Follows the existing code style

For bug reports and feature requests, please open an issue.


Resources

  • Documentation — Guides, API reference, and examples
  • OpenFGA — The authorization model Melange implements
  • Zanzibar Paper — Google's original authorization system
  • pgFGA — PostgreSQL FGA implementation that inspired this project

License

MIT License — see LICENSE for details.

Directories

Path Synopsis
cmd
melange command
Package main provides the melange CLI for managing authorization schemas.
Package main provides the melange CLI for managing authorization schemas.
internal
cli
Package cli provides shared configuration and utilities for the melange CLI.
Package cli provides shared configuration and utilities for the melange CLI.
clientgen
Package clientgen provides a registry of language-specific client code generators.
Package clientgen provides a registry of language-specific client code generators.
clientgen/go
Package gogen implements the Go client code generator for melange.
Package gogen implements the Go client code generator for melange.
clientgen/typescript
Package typescript implements the TypeScript client code generator for melange.
Package typescript implements the TypeScript client code generator for melange.
doctor
Package doctor provides health checks for melange authorization infrastructure.
Package doctor provides health checks for melange authorization infrastructure.
sqlgen
Package sqlgen generates specialized SQL functions for OpenFGA authorization checks.
Package sqlgen generates specialized SQL functions for OpenFGA authorization checks.
sqlgen/analysis
Package analysis provides relation analysis and strategy selection for SQL code generation.
Package analysis provides relation analysis and strategy selection for SQL code generation.
sqlgen/inline
Package inline generates VALUES clauses for inlining metadata into SQL functions.
Package inline generates VALUES clauses for inlining metadata into SQL functions.
sqlgen/plpgsql
Package plpgsql provides PL/pgSQL function builder types.
Package plpgsql provides PL/pgSQL function builder types.
sqlgen/sqldsl
Package sqldsl provides a type-safe DSL for building PostgreSQL queries.
Package sqldsl provides a type-safe DSL for building PostgreSQL queries.
sqlgen/tuples
Package tuples provides tuple-table specific builders and helpers.
Package tuples provides tuple-table specific builders and helpers.
melange module
pkg
clientgen
Package clientgen provides a public API for generating type-safe client code from authorization schemas.
Package clientgen provides a public API for generating type-safe client code from authorization schemas.
compiler
Package compiler provides public APIs for compiling OpenFGA schemas to SQL.
Package compiler provides public APIs for compiling OpenFGA schemas to SQL.
parser
Package parser provides OpenFGA schema parsing for melange.
Package parser provides OpenFGA schema parsing for melange.
schema
Package schema provides OpenFGA schema types and transformation logic for melange.
Package schema provides OpenFGA schema types and transformation logic for melange.
test
authz
Package authz contains generated types for the test authorization schema.
Package authz contains generated types for the test authorization schema.
cmd/dumpinventory command
Command dumpinventory produces an inventory report of relations that fall back to generic permission checking or list functions, grouped by the reason they cannot generate specialized SQL functions.
Command dumpinventory produces an inventory report of relations that fall back to generic permission checking or list functions, grouped by the reason they cannot generate specialized SQL functions.
cmd/dumpsql command
Command dumpsql dumps the generated SQL for a specific OpenFGA test case.
Command dumpsql dumps the generated SQL for a specific OpenFGA test case.
cmd/dumptest command
Command dumptest dumps OpenFGA test cases in a human-readable format.
Command dumptest dumps OpenFGA test cases in a human-readable format.
cmd/explaintest command
Command explaintest runs EXPLAIN ANALYZE on OpenFGA test cases to show query execution plans, buffer statistics, and performance metrics.
Command explaintest runs EXPLAIN ANALYZE on OpenFGA test cases to show query execution plans, buffer statistics, and performance metrics.
openfgatests
Package openfgatests provides an adapter to run the official OpenFGA test suite against the melange authorization implementation.
Package openfgatests provides an adapter to run the official OpenFGA test suite against the melange authorization implementation.
testutil
Package testutil provides shared test utilities for Melange integration tests.
Package testutil provides shared test utilities for Melange integration tests.
tooling module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL