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

# Writing WASM Policies

> Learn how to write custom validation policies using WebAssembly with Go or JavaScript

<Warning>
  **Experimental Preview Feature - Alternative Policy Engine**

  The **WASM policy engine is NOT the default policy engine in Chainloop**. The default policy engine uses [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/) (Open Policy Agent).

  This WASM policy engine is currently in **experimental preview** for users who want to write policies in Go or JavaScript instead of Rego. APIs and features may change in future releases. We recommend testing thoroughly before using in production.

  **Currently supported languages for WASM policies:**

  * ✅ Go (via TinyGo)
  * ✅ JavaScript (via Extism JS)
  * 🚧 Additional languages coming soon

  **For most users, we recommend using the default Rego-based policy engine** documented in [Writing Custom Policies](/guides/custom-policies).
</Warning>

<Tip>
  We recommend getting familiar with the [Policy concept](/concepts/policies) before writing your first WASM policy.
</Tip>

## What are WASM Policies?

WASM (WebAssembly) policies are custom validation rules that run in a secure sandbox environment using Chainloop's **experimental WASM policy engine**. This is an alternative to Chainloop's default Rego-based policy engine.

Unlike Rego policies (the default), WASM policies let you write validation logic in familiar programming languages like Go or JavaScript, with full access to standard libraries and ecosystem tools.

**Key benefits of WASM policies:**

* Write policies in Go or JavaScript using high-level SDKs
* Access to language ecosystems (JSON parsing, HTTP clients, etc.)
* Type safety and IDE support
* Secure execution in WebAssembly sandbox
* Portable across platforms

## When to Use WASM vs Rego

| Feature            | WASM Policies (Experimental) | Rego Policies (Default)  |
| ------------------ | ---------------------------- | ------------------------ |
| **Status**         | Experimental preview         | Production-ready default |
| **Languages**      | Go, JavaScript, Rust, etc.   | Rego only                |
| **Learning Curve** | Use familiar languages       | Learn Rego syntax        |
| **Libraries**      | Full language ecosystem      | Limited built-ins        |
| **Type Safety**    | Full type checking           | Dynamic typing           |
| **Performance**    | Fast (native code)           | Fast (optimized)         |
| **Sandbox**        | WASM isolation               | OPA runtime              |

**Use WASM policies when:**

* You need complex logic with external libraries
* Your team prefers Go/JavaScript over Rego
* You need HTTP API integration
* You want strong type safety and IDE support
* You're willing to use experimental features

**Use Rego policies (recommended default) when:**

* You want production-ready, stable policy engine
* You need declarative policy syntax
* Your policies are simple queries and filters
* You're already familiar with OPA/Rego
* You prefer the standard, widely-adopted approach

## How WASM Policies Work

### Execution Architecture

WASM policies run in a **host/guest architecture** where:

* **Host (Chainloop)**: The policy engine that loads and executes WASM modules
* **Guest (Policy)**: Your WASM policy code running in an isolated sandbox

<img src="https://mintcdn.com/chainloop/QD1a_grgddUxmCO1/guides/img/wasm-policy-architecture.png?fit=max&auto=format&n=QD1a_grgddUxmCO1&q=85&s=afc9142ac204e0c89d7485deb00e4866" alt="WASM Policy Architecture" width="2816" height="1536" data-path="guides/img/wasm-policy-architecture.png" />

**Key characteristics:**

* **In-process execution**: Policies run embedded in the control plane process (not as sidecars)
* **Sandboxed environment**: WebAssembly isolation prevents filesystem access and unsafe operations
* **Single-threaded**: Each policy execution is single-threaded and deterministic
* **Bytes-in/bytes-out**: Material data flows through a simple byte interface
* **Host functions**: Controlled capabilities (HTTP, discovery) exposed by Chainloop

<Warning>
  **The Execute Function is Required**

  Every WASM policy **must** export an `Execute()` function as the entry point. This is how Chainloop invokes your policy:

  ```go theme={"dark"}
  //export Execute
  func Execute() int32 {
      return chainloop.Run(validate)
  }
  ```

  ```javascript theme={"dark"}
  function Execute() {
    return run(() => {
      // validation logic
    });
  }

  module.exports = { Execute };
  ```

  Without the `Execute` export, the policy will fail to load.
</Warning>

### Technology Stack

Chainloop WASM policies are powered by [Extism](https://extism.org/), a universal plugin system that allows policies written in different languages to run securely in WebAssembly sandboxes.

**Why Extism?**

* **Multi-language support**: Extensible architecture for multiple languages
* **Security**: WASM sandbox isolates policies from the host system
* **Performance**: Fast in-process execution with minimal overhead
* **Portability**: Same policy runs anywhere WASM is supported
* **Flexible serialization**: Supports JSON, Protocol Buffers, and other formats

**Chainloop SDKs wrap Extism PDKs:**

* **Go**: Built on [extism/go-pdk](https://github.com/extism/go-pdk) - Provides idiomatic Go APIs
* **JavaScript**: Built on [extism/js-pdk](https://github.com/extism/js-pdk) - Runs JS in QuickJS WASM runtime

<Note>
  While Extism supports additional languages (Rust, Python, C#, etc.), Chainloop currently provides official SDKs for **Go and JavaScript only**. Additional language support is planned for future releases.
</Note>

You don't need to interact with Extism directly - Chainloop's SDKs provide all the high-level functions you need for policy development.

## Quick Start

### 1. Choose Your Language

<CardGroup cols={2}>
  <Card title="Go SDK" icon="golang" href="/guides/wasm-policies/go-sdk">
    Write policies in Go with TinyGo
  </Card>

  <Card title="JavaScript SDK" icon="js" href="/guides/wasm-policies/javascript-sdk">
    Write policies in JavaScript/TypeScript
  </Card>
</CardGroup>

### 2. Create Your First Policy

Here's a minimal policy that validates a string message:

<CodeGroup>
  ```go Go theme={"dark"}
  package main

  import (
      "encoding/json"

      chainloop "github.com/chainloop-dev/chainloop/labs/wasm-policy-sdk/go"
      "github.com/extism/go-pdk"
  )

  //export Execute
  func Execute() int32 {
      return chainloop.Run(validate)
  }

  func validate() error {
      // Get the material to validate
      var input struct {
          Message string `json:"message"`
      }

      if err := chainloop.GetMaterialJSON(&input); err != nil {
          return chainloop.Skip("Material is not valid JSON")
      }

      // Validate the message
      result := chainloop.Success()

      if input.Message == "" {
          result.AddViolation("message cannot be empty")
      }

      return chainloop.OutputResult(result)
  }

  func main() {}
  ```

  ```javascript JavaScript theme={"dark"}
  const {
    getMaterialJSON,
    success,
    skip,
    outputResult,
    run
  } = require('@chainloop-dev/policy-sdk');

  function Execute() {
    return run(() => {
      // Get the material to validate
      const input = getMaterialJSON();

      // Check if material has the required field
      if (!input.message) {
        outputResult(skip("Material missing 'message' field"));
        return;
      }

      // Validate the message
      const result = success();

      if (input.message === "") {
        result.addViolation("message cannot be empty");
      }

      outputResult(result);
    });
  }

  module.exports = { Execute };
  ```
</CodeGroup>

### 3. Build the Policy

<CodeGroup>
  ```bash Go theme={"dark"}
  # Install TinyGo first
  brew install tinygo  # macOS
  # or download from https://tinygo.org/

  # Build to WASM
  tinygo build -target=wasi -o policy.wasm policy.go
  ```

  ```bash JavaScript theme={"dark"}
  # Install extism-js compiler
  npm install -g @extism/js-pdk

  # Install dependencies
  npm install @chainloop-dev/policy-sdk esbuild

  # Build to WASM
  npm run build  # Uses esbuild + extism-js
  ```
</CodeGroup>

### 4. Create Policy Configuration

Create a `policy.yaml` file:

```yaml theme={"dark"}
apiVersion: workflowcontract.chainloop.dev/v1
kind: Policy
metadata:
  name: my-first-policy
  description: Validates message field in materials
spec:
  policies:
    - kind: EVIDENCE  # Material type to validate
      path: policy.wasm
```

### 5. Test Locally

Create test data (`test.json`):

```json theme={"dark"}
{
  "message": "hello world"
}
```

Test the policy:

```bash theme={"dark"}
chainloop policy devel eval \
  --policy policy.yaml \
  --material test.json \
  --kind EVIDENCE
```

**Expected output:**

```json theme={"dark"}
{
  "result": {
    "violations": [],
    "skip_reasons": [],
    "skipped": false
  }
}
```

## Policy Result States

Every policy execution returns one of three states:

### Success

Material passes all validation rules.

```go theme={"dark"}
result := chainloop.Success()
return chainloop.OutputResult(result)
```

### Fail

Material violates one or more rules. Include specific violation messages.

```go theme={"dark"}
result := chainloop.Success()
result.AddViolation("license GPL-3.0 not approved")
result.AddViolation("missing required field 'version'")
return chainloop.OutputResult(result)
```

### Skip

Policy doesn't apply to this material (wrong format, missing fields, etc.).

```go theme={"dark"}
return chainloop.Skip("Material is not a CycloneDX SBOM")
```

<Warning>
  **Important**: Use `Skip` when the material isn't applicable to your policy. Don't fail policies for materials they weren't designed to validate.
</Warning>

## Testing Workflow

1. **Write the policy** in Go or JavaScript
2. **Build to WASM** using TinyGo or extism-js
3. **Test locally** with `chainloop policy devel eval`
4. **Iterate** based on test results
5. **Deploy** to Chainloop once validated

See the [Policies concept](/concepts/policies) for details on policy management.

## Next Steps

<CardGroup cols={2}>
  <Card title="Go SDK Guide" icon="golang" href="/guides/wasm-policies/go-sdk">
    Learn the Go SDK and build your first Go policy
  </Card>

  <Card title="JavaScript SDK Guide" icon="js" href="/guides/wasm-policies/javascript-sdk">
    Learn the JavaScript SDK and build your first JS policy
  </Card>

  <Card title="Examples" icon="code" href="/guides/wasm-policies/examples">
    Explore complete policy examples and common patterns
  </Card>
</CardGroup>
