> ## Documentation Index
> Fetch the complete documentation index at: https://docs-attestly.code4source.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Visual builder

> Author rulesets visually on the playground — drag nodes, connect them, run them on a map.

The **playground** is a visual environment where you can author and
test rulesets without writing JSON by hand. It pairs a map with a
graph-based **builder**, so you can draw a polygon, drop nodes onto a
canvas, connect them, and see the verdict on the same screen.

## At a glance

The playground splits the screen into three areas:

<Frame>
  <img className="block dark:hidden" src="https://mintcdn.com/code4source/xWaIkEoznkZrpr3A/images/builder/overview-light.png?fit=max&auto=format&n=xWaIkEoznkZrpr3A&q=85&s=eb7c85222168f8f3a6f1add07d4ef223" alt="Playground layout: map on the left, builder canvas in the center, results panel on the right" width="2880" height="1800" data-path="images/builder/overview-light.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/code4source/xWaIkEoznkZrpr3A/images/builder/overview-dark.png?fit=max&auto=format&n=xWaIkEoznkZrpr3A&q=85&s=ff294e5f7c5ca2ca3393bf5dcfe7b365" alt="Playground layout: map on the left, builder canvas in the center, results panel on the right" width="2880" height="1800" data-path="images/builder/overview-dark.png" />
</Frame>

1. **Map** — draw or paste a geometry. It becomes the `$input` to
   every set anchored on it.
2. **Builder canvas** — the visual ruleset. Each node is a `set`,
   `projection`, `check`, or `verdict`; edges represent references
   (e.g. a check pointing at a set).
3. **Panel** — the live `Run` button, the JSON view, the verdict and
   evidence after each run.

## Authoring loop

The typical authoring loop:

1. Draw a polygon on the map (or paste GeoJSON).
2. Pick a starting point — either an empty canvas or a
   [template](#templates).
3. Add nodes from the palette and connect them.
4. Click **Run** to evaluate against the polygon.
5. Inspect the verdict and per-check evidence.
6. Iterate.

## The palette

The sidebar palette holds the node kinds you can drop onto the
canvas:

<Frame>
  <img className="block dark:hidden" src="https://mintcdn.com/code4source/xWaIkEoznkZrpr3A/images/builder/palette-light.png?fit=max&auto=format&n=xWaIkEoznkZrpr3A&q=85&s=29c7ab1b58fa1211b2370e81526cd026" alt="Builder palette with the five node kinds" width="2880" height="1800" data-path="images/builder/palette-light.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/code4source/xWaIkEoznkZrpr3A/images/builder/palette-dark.png?fit=max&auto=format&n=xWaIkEoznkZrpr3A&q=85&s=db525815d80a6a1668b5ea5e164d70eb" alt="Builder palette with the five node kinds" width="2880" height="1800" data-path="images/builder/palette-dark.png" />
</Frame>

| Node          | What it produces                                                                 |
| ------------- | -------------------------------------------------------------------------------- |
| `source_set`  | A set anchored on a spatial source (e.g. `icmbio_ucs_federais`).                 |
| `subject_set` | A set anchored on a subject register (e.g. `ofac_sdn`).                          |
| `setop_set`   | A set built from `union` / `intersection` / `difference` of other sets.          |
| `projection`  | A scalar or geometric value computed over a set (`count`, `total_area_m2`, ...). |
| `check`       | A boolean predicate with a severity. Feeds the verdict.                          |

Drop a node, then click it to open its **editor** in the right
sidebar.

## Editors

Every node has a typed editor. The editor enforces the same rules
that the API enforces — invalid configurations are flagged before
you run.

<Frame>
  <img className="block dark:hidden" src="https://mintcdn.com/code4source/xWaIkEoznkZrpr3A/images/builder/source-set-editor-light.png?fit=max&auto=format&n=xWaIkEoznkZrpr3A&q=85&s=4f017459e29d166a47b953fdcc430cc2" alt="Source set editor: source picker, join op, target, optional filter" width="2880" height="1800" data-path="images/builder/source-set-editor-light.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/code4source/xWaIkEoznkZrpr3A/images/builder/source-set-editor-dark.png?fit=max&auto=format&n=xWaIkEoznkZrpr3A&q=85&s=e902fb10a6408484136672bace77a8fa" alt="Source set editor: source picker, join op, target, optional filter" width="2880" height="1800" data-path="images/builder/source-set-editor-dark.png" />
</Frame>

For a `source_set`, you pick:

* The **source** from the catalog (auto-suggested via
  `GET /v1/sources`).
* The **join** — `intersects`, `contains`, `within`, `covers`,
  `covered_by`, `overlaps`, `touches`, `crosses`, `disjoint`,
  `equals`, `dwithin`, `beyond` for spatial sets; `equals` / `ilike`
  when the set is anchored on a subject register.
* The **target** — `$input` or another set in the graph.
* An optional **filter** (e.g. temporal, property-equals).

For a `check`, you pick:

* The **severity** — `critical`, `high`, `medium`, `low`, `info`.
* The **predicate** — `exists` (set non-empty) or `threshold`
  (referenced projection passes a comparison).

## Connecting nodes

Drag from a node's output handle to another node's input. The
builder rejects connections that would create cycles or that
mismatch types.

<Frame>
  <img className="block dark:hidden" src="https://mintcdn.com/code4source/xWaIkEoznkZrpr3A/images/builder/connections-light.png?fit=max&auto=format&n=xWaIkEoznkZrpr3A&q=85&s=7c3166e42fecab0c0b0335db07e3d198" alt="Two source sets feeding into a setop set, which feeds into a check" width="2880" height="1800" data-path="images/builder/connections-light.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/code4source/xWaIkEoznkZrpr3A/images/builder/connections-dark.png?fit=max&auto=format&n=xWaIkEoznkZrpr3A&q=85&s=7f35db95383a4fdeb7b39fe1f2542b06" alt="Two source sets feeding into a setop set, which feeds into a check" width="2880" height="1800" data-path="images/builder/connections-dark.png" />
</Frame>

## Run and inspect

Click **Run** in the topbar to evaluate the canvas against the
current map geometry. The panel updates with:

* The top-level `status` (`ok` / `degraded`) and `outcome`
  (`compliant`, `warning`, `non_compliant`, `degraded`).
* Each check: `triggered`, `severity`, evidence list.
* Each projection: computed value.

<Frame>
  <img className="block dark:hidden" src="https://mintcdn.com/code4source/xWaIkEoznkZrpr3A/images/builder/run-result-light.png?fit=max&auto=format&n=xWaIkEoznkZrpr3A&q=85&s=48bd6b04f98557410a24e8d527ffa039" alt="Result panel showing a non_compliant outcome with evidence highlighted on the map" width="2880" height="1800" data-path="images/builder/run-result-light.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/code4source/xWaIkEoznkZrpr3A/images/builder/run-result-dark.png?fit=max&auto=format&n=xWaIkEoznkZrpr3A&q=85&s=0bcad10d7d57fb2977c9011e9a23514f" alt="Result panel showing a non_compliant outcome with evidence highlighted on the map" width="2880" height="1800" data-path="images/builder/run-result-dark.png" />
</Frame>

Evidence features are highlighted on the map so you can see exactly
which polygons drove the verdict.

## JSON view

Every visual edit syncs both ways with a JSON document. Click
**Show JSON** to open the modal — copy the body to use directly with
`POST /v1/evaluate`, or paste in a ruleset to load it into the
canvas.

<Frame>
  <img className="block dark:hidden" src="https://mintcdn.com/code4source/xWaIkEoznkZrpr3A/images/builder/json-view-light.png?fit=max&auto=format&n=xWaIkEoznkZrpr3A&q=85&s=3b1d260797f91fa004456f9a39b43942" alt="JSON modal showing the canonical ruleset body" width="2880" height="1800" data-path="images/builder/json-view-light.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/code4source/xWaIkEoznkZrpr3A/images/builder/json-view-dark.png?fit=max&auto=format&n=xWaIkEoznkZrpr3A&q=85&s=f106854c908a7436fca1ddee3e2090d7" alt="JSON modal showing the canonical ruleset body" width="2880" height="1800" data-path="images/builder/json-view-dark.png" />
</Frame>

## Templates

The sidebar offers ready-made starting points covering common
patterns:

| Template              | What it shows                                                       |
| --------------------- | ------------------------------------------------------------------- |
| `overlap_ratio_tiers` | Tiered checks on overlap ratios (majority vs partial overlap).      |
| `distance_tiers`      | Distance-based severity tiers (very close / close / far).           |
| `distance_band`       | Match features in a `[min, max]` distance band.                     |
| `chained_sets`        | One set joined against another set instead of `$input`.             |
| `dynamic_buffer_app`  | A buffer whose distance is read from a feature property.            |
| `merged_hazard_zone`  | `merge` projection unifying a set's geometries into a hazard layer. |
| `temporal_recency`    | Filter to features newer/older than a relative window.              |
| `multi_join`          | Multiple sources in a single ruleset.                               |

Templates load into the canvas; from there you adapt names,
sources, severities, and thresholds to your policy.

## When to use the builder vs raw JSON

* **Builder**: exploring policies, demoing to stakeholders,
  authoring a first version visually before reviewing.
* **Raw JSON**: editing a stored ruleset programmatically, code
  review on a PR, automated generation from a higher-level config.

The two are interchangeable — the JSON view is canonical and the
builder is just a renderer over it.
