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)

Download and run the Oso Dev Server binary directly:
# Single policy
./oso-dev-server migrate-ui policy.polar

# Multiple policies 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'

Verify installation

Access the migration interface: http://localhost:8080

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() anywhere in the request flow.

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 --local-authorization-config config.yaml --connection-string postgresql://localhost:5432/mydb
Supported databases: PostgreSQL onlyWhat you get:
  • Complete data snapshots from your database
  • Centralized view of authorization data
  • No need to actually centralize your data
Configure Oso Migrate with PostgreSQL running in Docker containers.macOS/Linux (binary):
# 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://localhost:5432/postgres
Windows (Docker):
# Create shared network
docker network create my-app

# Start PostgreSQL
docker run -p 5432:5432 \
  -e POSTGRES_PASSWORD=password \
  --volume /tmp:/tmp \
  --network my-app \
  --name postgres \
  -d postgres:latest

# Start Oso Migrate
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
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