maslc 1.0.0

Maduka Authorization Specification Language (MASL) toolchain and runtime
maslc-1.0.0 is not a library.

MASL — Maduka Authorization Specification Language

Crates.io License: MIT CI

MASL is a declarative, graph-first authorization schema language for Zanzibar-style authorization systems.

You describe who can do what on which resource in a .mdk file.
maslc compiles it to a compact binary (.mdkc) loaded at runtime by the Zanzibar engine.

namespace commerce
schema 1

subject User
subject Group {
    relation {
        member: User | Group::member
    }
}

resource Store {
    relation {
        owner:  User
        staff:  User | Group::member
        org:    Organization
    }
    grant {
        view   => owner | staff | org::member
        manage => owner | org::manage
        delete => owner
    }
}

Features

  • Purely declarative — no variables, no loops, no conditions.
  • Compile-time validation — type resolution, circular alias detection, unreachable grant checks.
  • Public Contracts — grants are the public API; relations are implementation details.
  • Zero runtime overhead — aliases fully expanded at compile time, .mdkc loaded once at startup.
  • Rich toolingmaslc build, maslc check, maslc fmt, maslc lint, maslc doc, maslc lsp.
  • VS Code extension — real-time diagnostics powered by the LSP server.

Installation

From crates.io

cargo install maslc

From source

git clone https://gitlab.com/exytech/community/masl
cd maduka/masl
cargo build --release --bin maslc
# Optionally install globally:
cargo install --path crates/maslc

Pre-built binaries

Download the latest release from GitHub Releases for:

  • x86_64-unknown-linux-gnu
  • x86_64-apple-darwin / aarch64-apple-darwin
  • x86_64-pc-windows-msvc

Quick Start

1. Create a schema file my_app.mdk:

namespace my_app
schema 1

subject User

resource Document {
    relation {
        author:   User
        reviewer: User
    }
    grant {
        view    => author | reviewer
        edit    => author
        delete  => author
    }
}

2. Validate:

maslc check my_app.mdk

3. Compile to binary:

maslc build my_app.mdk --out my_app.mdkc

4. Inspect / format / lint:

maslc fmt  my_app.mdk       # auto-format in place
maslc lint my_app.mdk       # architectural lint warnings
maslc doc  my_app.mdk       # generate markdown documentation

CLI Reference

maslc <COMMAND> [OPTIONS]

Commands:
  build   Compile a .mdk schema to a .mdkc binary
  check   Parse and validate a schema without producing output
  fmt     Format a .mdk file in place
  lint    Run the architectural linter
  doc     Generate markdown documentation from the schema
  lsp     Start the LSP server (used by editor extensions)

Options:
  -h, --help       Print help
  -V, --version    Print version

maslc build

maslc build <INPUT> [--out <OUTPUT>]

Arguments:
  <INPUT>          Path to the .mdk source file
  --out <OUTPUT>   Output path for the .mdkc binary [default: <INPUT>.mdkc]

maslc check

maslc check <INPUT>

Runs parsing, semantic analysis, and validation. Exits 0 on success, 1 on error — suitable for CI.

maslc fmt

maslc fmt <INPUT> [--check]

  --check    Fail if the file is not already formatted (for CI)

maslc lint

maslc lint <INPUT>

Emits architectural warnings (public contracts violations, naming conventions, unused aliases, etc.).

maslc doc

maslc doc <INPUT> [--out <DIR>]

  --out <DIR>    Output directory for generated markdown [default: ./docs]

VS Code Extension

Install from the VS Code Marketplace or via VSIX:

code --install-extension masl-lsp-client-0.1.0.vsix

The extension provides:

  • Real-time diagnostics (errors & warnings as you type).
  • Syntax recognition for .mdk files.
  • Auto-closing brackets and comment toggling.

Requires maslc in your PATH, or configure:

"masl.compiler.path": "/usr/local/bin/maslc"

Library Usage (Rust)

If you want to integrate MASL in your application to evaluate authorization queries, use the masl_runtime crate:

[dependencies]
masl_runtime = { version = "0.1.0" }

Quick Example

use masl_runtime::prelude::*;

// 1. Define a TupleReader (e.g. connected to your SurrealDB or Postgres database)
struct MyDatabase;

impl TupleReader for MyDatabase {
    async fn exists(
        &self,
        _namespace: &str,
        subject_type: &str,
        subject_id: &str,
        relation: &str,
        object_type: &str,
        object_id: &str,
    ) -> Result<bool, Box<dyn std::error::Error + Send + Sync>> {
        // Query database to check if the tuple exists
        Ok(true)
    }

    async fn lookup_subjects(
        &self,
        _namespace: &str,
        _relation: &str,
        _object_type: &str,
        _object_id: &str,
    ) -> Result<Vec<(String, String)>, Box<dyn std::error::Error + Send + Sync>> {
        // Find indirect relation parent subjects (e.g. groups containing this user)
        Ok(vec![])
    }

    async fn lookup_resources(
        &self,
        _namespace: &str,
        _subject_type: &str,
        _subject_id: &str,
        _relation: &str,
    ) -> Result<Vec<(String, String)>, Box<dyn std::error::Error + Send + Sync>> {
        Ok(vec![])
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    // 2. Load compiled schema(s) (either a folder, file, or raw bytes)
    let schema = CompiledSchema::load_from_directory("policies/compiled/")?;

    // 3. Construct the Authorizer via builder
    let authorizer = Authorizer::builder()
        .schema(schema)
        .tuple_store(MyDatabase)
        .max_depth(32) // recursion limit guard
        .build()?;

    // 4. Run the check!
    let result = authorizer.authorize(AuthorizationQuery {
        namespace: "commerce".to_string(),
        subject_type: "User".to_string(),
        subject_id: "alice".to_string(),
        action: "view".to_string(),
        object_type: "Store".to_string(),
        object_id: "store-42".to_string(),
    }).await?;

    assert_eq!(result, AuthorizationResult::Allowed);
    Ok(())
}

Crate Architecture

This repository is a Cargo workspace. The crates are layered as follows:

maslc (binary)
 └── masl_compiler      — compilation driver (orchestrates all phases)
      ├── masl_parser   — Pest-based parser, produces AST
      ├── masl_hir      — High-level IR (semantic model)
      ├── masl_validator — architectural & performance lint checks
      ├── masl_ir       — lowered intermediate representation
      └── masl_bytecode — .mdkc binary serialization

masl_runtime            — high-performance ReBAC reference runtime
masl_formatter          — canonical formatting of .mdk source
masl_linter             — standalone linter rules (naming, public contracts)
masl_lsp                — LSP server (tower-lsp, stdio transport)
masl_diagnostics        — shared diagnostic types (errors, warnings, spans)
masl_testing            — test helpers and fixtures
Crate Description Publish
maslc CLI binary
masl_compiler Compiler driver
masl_parser Parser + AST
masl_hir Semantic HIR
masl_validator Architectural validator
masl_ir IR types
masl_bytecode .mdkc encoder/decoder
masl_runtime ReBAC reference engine
masl_formatter Source formatter
masl_linter Linter rules
masl_lsp LSP server
masl_diagnostics Shared diagnostics
masl_testing Test helpers ❌ (internal)

Examples

See the examples/ directory:

File Description
commerce.mdk Multi-tenant e-commerce schema (stores, products, orders)

Documentation

  • MASL Book — language guide (concepts, operators, best practices).
  • RFCs — design specifications and architectural decisions.
  • crates.io docs — generated API documentation.

Contributing

  1. Fork the repository.
  2. Create a feature branch: git checkout -b feat/my-feature.
  3. Run checks before committing:
    cargo test --workspace
    cargo clippy --workspace --all-targets
    cargo fmt --check
    
  4. Open a pull request.

New language features must be discussed in an RFC first — see rfcs/.


License

MIT — see LICENSE.