Quick Start
This is the shortest path to a working permission check. It uses the default settings; see Project Setup for customization.
1. Initialize Your Project
melange init -yThis creates a melange/ directory with a config file and starter schema:
myproject/
├── melange/
│ ├── config.yaml
│ └── schema.fga
└── ...The default schema defines organizations with role hierarchies and repositories with inherited permissions:
model
schema 1.1
type user
type organization
relations
define owner: [user]
define admin: [user] or owner
define member: [user] or admin
type repository
relations
define org: [organization]
define owner: [user]
define admin: [user] or owner
define can_read: member from org or admin
define can_write: admin
define can_delete: owner2. Create the melange_tuples View
Melange reads authorization data from a SQL view called melange_tuples. This view maps your existing tables into tuples. Create it in your database:
CREATE OR REPLACE VIEW melange_tuples AS
-- Organization memberships
SELECT
'user' AS subject_type,
user_id::text AS subject_id,
role AS relation, -- 'owner', 'admin', or 'member'
'organization' AS object_type,
organization_id::text AS object_id
FROM organization_members
UNION ALL
-- Repository -> Organization relationship
SELECT
'organization' AS subject_type,
organization_id::text AS subject_id,
'org' AS relation,
'repository' AS object_type,
id::text AS object_id
FROM repositories
UNION ALL
-- Direct repository owners
SELECT
'user' AS subject_type,
user_id::text AS subject_id,
'owner' AS relation,
'repository' AS object_type,
repository_id::text AS object_id
FROM repository_owners;3. Apply Migrations
melange migrateThis compiles your schema into PostgreSQL functions and installs them.
To preview the generated SQL without applying:
melange migrate --dry-run4. Check Permissions
The migration installed a check_permission function. Try it in SQL:
-- Returns 1 (allowed) or 0 (denied)
SELECT check_permission('user', 'alice', 'can_read', 'repository', '42');Or from application code:
import (
"context"
"database/sql"
"github.com/pthm/melange/melange"
)
db, _ := sql.Open("postgres", "postgres://localhost/mydb")
checker := melange.NewChecker(db)
user := melange.Object{Type: "user", ID: "alice"}
repo := melange.Object{Type: "repository", ID: "42"}
allowed, err := checker.Check(context.Background(), user, "can_read", repo)Install the runtime library (stdlib-only, no external dependencies):
go get github.com/pthm/melange/melangeWhat melange migrate Did
- Parsed your OpenFGA schema
- Analyzed each relation to detect patterns (direct assignment, role hierarchy, parent inheritance)
- Generated a SQL function for each type+relation pair (e.g.,
check_repository_can_read) - Installed a dispatcher function (
check_permission) that routes to the correct per-relation function
Permission checks are SQL function calls. There is no external service, no network round-trip, and no tuple synchronization.
Next Steps
- Creating Your Tuples View: mapping your domain tables in detail
- Your First Migration: validation, health checks, and external migration frameworks
- Project Setup: templates, migration strategies, and code generation options
- Checking Permissions: Checker API, caching, bulk checks, and transactions
- How It Works: the compiler model and generated SQL