Skip to main content
Prerequisites: Oso Dev Server v1.18.0+ and the development tools setup.

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:
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:
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:
./oso-dev-server migrate-ui policy.polar
Multiple policy files with auto-reload:
./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:
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:
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:
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:
▶  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:
▼  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

Enable data snapshots for Local Authorization with database connections.Basic setup:
./oso-dev-server migrate-ui *.polar\
  --local-authorization-config config.yaml \
  --connection-string postgresql://postgres:password@localhost:5432/postgres  
Supported databases: PostgreSQL onlyWhat you get:
  • Complete data snapshots from your database
  • Centralized view of authorization data
  • No need to actually centralize your data
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.
# 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.
# 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:
docker network create my-app
Start Postgres with a shared /tmp directory:
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:
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.
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:
# Disable telemetry
./oso-dev-server analytics off

# Or set environment variable
export OSO_DISABLE_TELEMETRY=1

Troubleshooting

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
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
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