Melange v0.7.3

Melange v0.7.3

March 16, 2026·pthm
pthm

Melange v0.7.3 adds the new melange init command for interactive project scaffolding, fixes four bugs where list_objects and list_users returned incorrect results, and adds several improvements to melange doctor including table index recommendations, orphaned tuple detection, and a fix for multi-table view parsing.

No breaking changes from v0.7.2. Upgrade and run melange migrate to pick up the list function fixes. Run melange doctor to check for orphaned tuples and missing indexes.

Highlights

melange init — Interactive Project Scaffolding

New command to bootstrap a melange project with a single command:

melange init        # interactive wizard
melange init -y     # accept all defaults

The wizard detects your project type (Go module or Node.js package), then scaffolds:

  • melange/config.yaml — configuration file with schema path, database URL, and client code generation settings
  • melange/schema.fga — starter OpenFGA schema from one of four templates:
    • org-rbac — organization/team/repository hierarchy with role-based access (default)
    • doc-sharing — document/folder sharing with viewer/editor roles
    • minimal — single type with one relation
    • none — empty schema
  • Runtime dependency — automatically runs go get or npm install (supports npm, pnpm, yarn, and bun)

Use --no-install to skip dependency installation, or pass --schema, --db, --template, --runtime, and other flags to override defaults without prompting.

Configuration discovery has also been updated: melange now finds melange/config.yaml in addition to the existing melange.yaml at the project root (backwards compatible).

Bug Fixes

list_objects Returned Results Through Non-Recursive Parent Chains

Fixed a bug (#34) where list_objects incorrectly granted access on child objects for relations that don’t use recursive parent lookups. For example, given a folder_viewer: [user] relation (no from parent clause), a user assigned folder_viewer on a parent folder would incorrectly appear as having access to all child folders.

check_permission was unaffected — only list functions exhibited this behavior.

Thanks to @jtbeach for reporting and fixing this.

list_objects Over-Propagated When Recursive and Non-Recursive Relations Share a Permission

A follow-up to the fix above. When a permission combines a recursive relation (e.g., viewer from parent) with a non-recursive one (e.g., editor: [user]) that also satisfies the permission, list_objects could still incorrectly propagate the non-recursive relation’s results through the parent chain. For example, a user directly assigned editor on a folder would incorrectly appear as having viewer access on all child folders.

list_objects and list_users Ignored Exclusions on Userset Lookups

Relations using exclusions with userset patterns (e.g., active_member: member but not blocked where access comes through group#member) were not filtering out excluded subjects. This meant list_objects could return objects a user should have been blocked from, and list_users could return users who should have been excluded.

list_users Returned Incomplete Results for Multi-Path TTU Relations

When a permission can be reached through multiple parent relations — either via role hierarchy (e.g., viewer is satisfied by admin, editor, and viewer roles, each linked through a different parent) or via a union of parent lookups (e.g., contributor: member from team or staff from department) — list_users only walked the first parent path. This caused missing results when access was granted through any of the other paths.

check_permission was unaffected — only list_users exhibited this behavior.

melange doctor Multi-Table View Parsing Fix

Fixed a bug (#35) where melange doctor incorrectly parsed melange_tuples views that join multiple tables. A FROM sites, organization clause was reported as source table sites, (with a trailing comma), and the second table was dropped entirely. This also produced invalid CREATE INDEX suggestions.

The view parser now handles:

  • Comma-separated cross joins (single and multi-line)
  • Explicit JOINs (JOIN, LEFT JOIN, etc.)
  • PostgreSQL’s ONLY keyword
  • Quoted identifiers ("Schema"."Table")

Thanks to @sgsfak for reporting this.

Improvements

melange doctor — Table Index Recommendations

Previously, performance checks only ran when melange_tuples was a view. Now melange doctor also checks for recommended indexes when melange_tuples is a regular table, based on the query patterns melange generates:

  • check_lookup(object_type, object_id, relation, subject_type, subject_id) for check_permission and list_subjects
  • list_objects(object_type, relation, subject_type, subject_id, object_id) for list_accessible_objects

Severity scales by table size: warning for small tables, critical for tables with 10k+ rows.

melange doctor — Orphaned Tuple Detection

melange doctor now comprehensively validates all tuples against the schema model, replacing the previous sampling-based check that only inspected 100 (object_type, relation) pairs. Four categories of orphaned data are now detected with affected tuple counts:

  • Unknown object typesobject_type values not defined in the schema
  • Unknown relations — relations not defined on their object type
  • Unknown subject typessubject_type values not defined in the schema
  • Invalid subject type assignments — subject types not allowed by the relation definition (e.g., organization used as subject for a relation that only accepts [user])

Keeping melange_tuples lean matters for query performance. These checks help surface stale references after schema changes so you can clean up waste.

Testing & Maintenance

  • Removed over 1,000 lines of dead code (#33)
  • Added Codecov integration for continuous coverage tracking (#32)
  • Added 22 new test cases covering real-world authorization patterns including layered role chains, org/team/repo hierarchies, SaaS entitlement gating, and role-binding intermediaries

Contributors

Thanks to the contributors who made this release possible:

  • @jtbeach — fixed list_objects returning results through non-recursive parent chains (#34)
  • @sgsfak — reported multi-table view parsing bug in melange doctor (#35)

Migration Notes

From v0.7.2

No breaking changes. Upgrade and run migrations to pick up the list function fixes:

melange migrate

New projects can now use melange init to get started:

melange init
melange migrate

Try It Out

# Install / upgrade CLI
brew install pthm/melange/melange

# Apply migrations
melange migrate

# Go runtime
go get github.com/pthm/melange/melange@v0.7.3

# TypeScript runtime
npm install @pthm/melange

Feedback

We welcome feedback and bug reports. Please open an issue with questions or feature requests.