Quickstart#

Check a contract over four orders, compare access for a company and one supplier, then compile it.

Install parcel#

On Linux or macOS:

curl -LsSf https://github.com/griot-cloud/parcel/releases/latest/download/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
parcel --version

On Windows, in PowerShell:

powershell -ExecutionPolicy ByPass -c "irm https://github.com/griot-cloud/parcel/releases/latest/download/install.ps1 | iex"

Open a new terminal after installing on Windows, then run parcel --version. On Linux or macOS, add the same PATH setting to your shell profile if the directory is not already included.

You can also download an archive from releases, or build from source with cargo build --release -p parcel-cli.

Get the example files:

git clone https://github.com/griot-cloud/parcel.git
cd parcel/examples/suppliers

Run the commands below from this directory.

Data and contract#

orders.csv contains orders assigned to two suppliers. Order 3 has an invalid amount:

order_id,supplier_id,amount
1,globex,120
2,initech,80
3,globex,-5
4,globex,60

orders.yaml lets Acme read every supplier’s orders, limits each supplier to its own orders, and excludes non-positive amounts:

contract: purchasing/orders
version: 1.0.0
owner: acme
binding:
  parquet: data/orders/
expose:
  - {name: order_id, type: int64}
  - {name: amount, type: int64}
rules:
  - id: supplier_orders
    op: admit
    expr: ctx.tenant == 'acme' || row.supplier_id == ctx.tenant

  - id: positive_amount
    op: assert
    expr: row.amount > 0
    on_fail: drop

The binding declares a Parquet location for the orders. For this check, --data orders.csv supplies the sample; no Parquet files are needed or written.

Define two callers#

acme.yaml represents a member of Acme’s purchasing team:

id: purchasing-team
tenant: acme
purpose: purchasing

globex.yaml represents a supplier analyst:

id: supplier-analyst
tenant: globex
purpose: purchasing

These profiles mock ctx for the check: id identifies the caller, tenant identifies their organization, and purpose states why they need access.

Validate the contract#

parcel validate orders.yaml --schema orders.csv

validate checks that the contract is correct and compiles, without evaluating any data. --schema orders.csv supplies the column names and types; the rules read supplier_id, which the contract does not expose, so its type must come from the data. If something is wrong, each problem is listed with its line and what to change. parcel lint orders.yaml --schema orders.csv also points out rules that are legal but probably not what you meant.

Check the contract#

parcel check orders.yaml --data orders.csv --caller acme.yaml --caller globex.yaml

The report shows:

  • One failed quality check: order 3 fails positive_amount.

  • A valid dataset verdict: on_fail: drop excludes the bad row from results without invalidating the whole dataset.

  • Different row counts: 3 of 4 rows pass for Acme; 2 of 4 pass for Globex. The CSV stays unchanged.

The row counts include both the supplier access rule and the positive-amount check.

To require every amount to pass, change on_fail: drop to on_fail: deny and rerun the check. The verdict becomes invalid and the command exits unsuccessfully. Restore drop before continuing.

Compile it#

parcel compile orders.yaml --schema orders.csv -o orders.parcel

--schema orders.csv supplies the column names and types. Compilation checks the rules against them and writes orders.parcel. Checking the data values is the job of parcel check.

For the contract fields and more examples, see Writing contracts. Command options and output are covered in Checking contracts and Compiling contracts.