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

# Oso Migrate (Beta)

> Develop on Oso Cloud with confidence using automated comparison and debugging tools.

> [!NOTE]
>
> **Prerequisites:** Oso Dev Server v1.18.0+ and the [development tools setup](https://www.osohq.com/docs/develop/local-dev/env-setup.md).

## Features

* **Parity checking**: Compare authorization decisions side-by-side between your legacy system and Oso Cloud.
* **Request replay**: Replay authorization requests after policy updates.
* **Authorization logging**: View full request history with timestamps, queries, results, and data snapshots.
* **Policy debugger**: Inspect query evaluation in an interactive tree view.
* **Test integration**: Export logged requests into tests with real data snapshots.

## Installation

### Binary (macOS/Linux)

You can download and run the Oso Dev Server binary directly, no additional tooling required.

#### Download the Binary

To download the latest macOS ARM64 build:

```bash theme={null}
curl --location https://oso-local-development-binary.s3.amazonaws.com/latest/oso-local-development-binary-macos-arm64.tar.gz | tar xz && chmod +x standalone && mv standalone oso-dev-server
```

This command fetches the latest tarball, extracts the binary, marks it executable, and renames it to `oso-dev-server`.

**Other Available Builds:**

Replace the platform suffix in the URL to download the appropriate binary for your system:

* `linux-arm64`
* `linux-x86_64`
* `macos-x86_64`

Example:

```bash theme={null}
curl --location https://oso-local-development-binary.s3.amazonaws.com/latest/oso-local-development-binary-linux-x86_64.tar.gz \
  | tar xz && chmod +x standalone && mv standalone oso-dev-server
```

#### Run the Dev Server

**Single policy file:**

```bash theme={null}
./oso-dev-server migrate-ui policy.polar
```

**Multiple policy files with auto-reload:**

```bash theme={null}
./oso-dev-server migrate-ui policy1.polar policy2.polar --watch-for-changes
```

### Docker (Windows/All Platforms)

Use Docker for cross-platform compatibility:

**Single policy file:**

```bash theme={null}
docker run -it -p 8080:8080 \
  --mount type=bind,src=./policy.polar,dst=/app/policy.polar \
  public.ecr.aws/osohq/dev-server:latest migrate-ui /app/policy.polar
```

**Multiple policy files:**

```bash theme={null}
docker run -it -p 8080:8080 \
  --mount type=bind,src=./policies,dst=/app/policies \
  --entrypoint sh \
  public.ecr.aws/osohq/dev-server:latest \
  -c './oso-dev-server migrate-ui /app/policies/*.polar'
```

## Implementation Example

Use `ParityHandle` to compare authorization decisions:

```typescript theme={null}
import { Oso, ParityHandle, Value } from "oso-cloud";

const oso = new Oso(
  "http://localhost:8080",
  "e_0123456789_12345_osotesttoken01xiIn"
);

async function authorizeWithParityCheck(
  userId: string,
  action: string,
  resource: Value
): Promise<boolean> {
  const parityHandle = new ParityHandle();
  const user = { type: "User", id: userId };

  // Run both systems in parallel
  const osoPromise = oso.authorize(user, action, resource, { parityHandle });
  const legacyPromise = legacyAuthorize(userId, action, resource);

  const [_, legacyResult] = await Promise.allSettled([
    osoPromise,
    legacyPromise
  ]);

  // Record expected result for comparison
  parityHandle.expect(legacyResult);

  // Continue using legacy result during migration
  return legacyResult;
}
```

**Flexible integration:** Call `parityHandle.expect()` at any point in the request flow to accommodate non-centralized authorization logic (one call per request).

## Policy Debugger Guide

Understand how the Policy Debugger visualizes authorization queries.

**Query tree structure:**
Each query appears as an expandable tree showing:

* Different ways the query could succeed (OR logic)
* Subconditions required for success (AND logic)
* Current evaluation path you're inspecting

**Reading the interface:**

```text theme={null}
▶  allow(User{"alice"}, "view", Content{"foo"})   ← ● ○ →
```

* **Arrow (▶/▼):** Expand/collapse query
* **Color:** Green = succeeded, Red = failed
* **Dots (● ○):** Different possible resolution paths
* **Solid dot:** Currently viewed path

**Detailed evaluation:**

```text theme={null}
▼  allow(User{"alice"}, "view", Content{"foo"})   ← ● ○ →
   ▼  has_permission(User{"alice"}, "view", Content{"foo"})   ← ○ ● ○ ○ →
      ▼  has_role(User{"alice"}, "CanView", Folder{"foo-folder"})   ●
         ♦ (fact)
      ▼  has_relation(Content{"foo"}, "folder", Folder{"foo-folder"})   ●
         ♦ (fact)
```

**Negation handling:**

* `not` nodes succeed only when all wrapped expressions fail
* Visual indicators show which expressions were true/false

## Advanced Configuration

> [accordion] Local Authorization setup
>
> Enable data snapshots for Local Authorization with database connections.
>
> **Basic setup:**
>
> ```bash theme={null}
> ./oso-dev-server migrate-ui *.polar\
>   --local-authorization-config config.yaml \
>   --connection-string postgresql://postgres:password@localhost:5432/postgres  
> ```
>
> **Supported databases:** PostgreSQL only
>
> **What you get:**
>
> * Complete data snapshots from your database
> * Centralized view of authorization data
> * No need to actually centralize your data

> [accordion] Local Authorization with Dockerized Postgres
>
> Some developers prefer running PostgreSQL in a Docker container, especially for local development or integration tests. If you’re using **local authorization snapshotting** with Oso Migrate against a Dockerized Postgres instance, additional setup is required.
>
> Under the hood, local authorization snapshotting works by having Postgres write a data dump to a temporary directory created by Oso Migrate. For this to work, **both Oso Migrate and the Postgres container must be able to read and write to the same temporary directory**. This requires mounting OS-specific temp paths into the Postgres container.
>
> > Not using local authorization? You can skip this entire section.
>
> **macOS/Linux (running Oso Migrate via binary):**
>
> The temporary directory path depends on your operating system.
>
> On macOS, temporary directories are created under `/var/folders`. You must mount this path into the Postgres container.
>
> ```bash theme={null}
> # Start PostgreSQL with volume mount
> docker run -p 5432:5432 \
>   -e POSTGRES_PASSWORD=password \
>   --volume /var/folders:/var/folders \
>   -d postgres:latest
>
> # Start Oso Migrate (connects to host PostgreSQL)
> ./oso-dev-server migrate-ui policy.polar \
>   --connection-string postgresql://postgres:password@localhost:5432/postgres \
>   --local-authorization-config config.yaml
> ```
>
> On Linux, temporary directories are created under `/tmp`. Mount `/tmp` into the Postgres container.
>
> ```bash theme={null}
> # Start PostgreSQL with volume mount
> docker run -p 5432:5432 \
>   -e POSTGRES_PASSWORD=password \
>   --volume /tmp:/tmp \
>   -d postgres:latest
>
> # Start Oso Migrate (connects to host PostgreSQL)
> ./oso-dev-server migrate-ui policy.polar \
>   --connection-string postgresql://postgres:password@localhost:5432/postgres \
>   --local-authorization-config config.yaml  
> ```
>
> **Windows (running Oso Migrate via Docker):**
>
> When running both Postgres and Oso Migrate in Docker (common on Windows), you must:
>
> * Create a shared Docker network
> * Mount `/tmp` into both containers
>
> This ensures the temporary snapshot directory is shared and the containers can communicate.
>
> Create a shared network:
>
> ```bash theme={null}
> docker network create my-app
> ```
>
> Start Postgres with a shared `/tmp` directory:
>
> ```bash theme={null}
> docker run -p 5432:5432 \
>   -e POSTGRES_PASSWORD=password \
>   --volume /tmp:/tmp \
>   --network my-app \
>   --name postgres \
>   -d postgres:latest
> ```
>
> Start Oso Migrate on the same network with the same `/tmp` volume:
>
> ```bash theme={null}
> docker run -it -p 8080:8080 \
>   --mount type=bind,src=./policy.polar,dst=/app/policy.polar \
>   --mount type=bind,src=./config.yaml,dst=/app/config.yaml \
>   --volume /tmp:/tmp \
>   --network my-app \
>   public.ecr.aws/osohq/dev-server:latest migrate-ui /app/policy.polar \
>   --connection-string postgresql://postgres:password@postgres:5432/postgres \
>   --local-authorization-config /app/config.yaml
> ```
>
> This configuration ensures that `/tmp` on the host, the Postgres container, and the Oso Migrate container all point to the same directory, allowing snapshotting to function correctly.

> [accordion] Telemetry and privacy
>
> Oso collects anonymous usage analytics to improve the product.
>
> **What we collect:**
>
> * Policy update events (with hashed policy content)
> * Usage patterns (anonymous)
>
> **Your privacy:**
>
> * We cannot identify you from the analytics
> * All data is anonymized
>
> **Opt out:**
>
> ```bash theme={null}
> # Disable telemetry
> ./oso-dev-server analytics off
>
> # Or set environment variable
> export OSO_DISABLE_TELEMETRY=1
> ```

## Troubleshooting

> [accordion] Migration interface issues
>
> **Can't access localhost:8080:**
>
> * Verify Oso Migrate is running: check terminal for startup messages
> * Check port conflicts: `lsof -i :8080`
> * Try different port: add `--port 9000` to startup command
>
> **Policy not loading:**
>
> * Verify file path is correct and accessible
> * Check for syntax errors in Polar policy files
> * Review startup logs for detailed error messages

> [accordion] Parity checking problems
>
> **Expected results not showing:**
>
> * Ensure `parityHandle.expect()` is called once per request
> * Verify legacy authorization function is returning correct values
> * Check timing - call `expect()` after both systems complete
>
> **Mismatches not appearing:**
>
> * Confirm both authorization calls are using the same parameters
> * Verify data consistency between systems
> * Check request context and timing

> [accordion] Database connection issues
>
> **PostgreSQL connection fails:**
>
> * Verify connection string format and credentials
> * Check database is accessible from Oso Migrate
> * For Docker: ensure network connectivity between containers
>
> **Snapshots not appearing:**
>
> * Confirm Local Authorization config file is valid
> * Check database permissions for dump operations
> * Verify temp directory mounting for Docker setups

## Migration resources

* [Set up local development](https://www.osohq.com/docs/develop/local-dev/oso-dev-server.md) with the Dev Server
* [Write authorization policies](https://www.osohq.com/docs/develop/policies/overview.md) using Polar
* [Model your data as facts](https://www.osohq.com/docs/develop/facts/overview.md) for authorization decisions
* [Implement authorization checks](https://www.osohq.com/docs/develop/enforce/authorize-requests.md) in your application


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.