---
title: "Oso"
description: "Use Oso and its Polar policies for MainSDK access - setup, main.yaml, testing, limits and swapping."
section: "integrations"
canonical: "https://mainsdk.dev/docs/integrations/oso"
updated: "2026-10-28"
---

# Oso

> Use Oso and its Polar policies for MainSDK access - setup, main.yaml, testing, limits and swapping.

Canonical: https://mainsdk.dev/docs/integrations/oso · Updated: 2026-10-28

Oso is an authorization service that models roles, relationships and attributes in its Polar policy language. Behind [`access`](https://mainsdk.dev/docs/interfaces/access), your Oso policies decide and MainSDK adds typed checks, fail-closed behaviour and audit. Pick it when your team already models permissions in Oso.

## Interfaces it serves

### Permissions (`access`)

- Status: Building for 0.3 · ships as a stable API
- Driver: `oso` (Oso)
- Docs: https://mainsdk.dev/docs/interfaces/access.md

```yaml
access:
  driver: oso
```

Swap to another provider: `cedar`, `opa`, `openfga`, `spicedb`, `cerbos`, `permit`, `avp`.

## Before you start

1. **Set up Oso** for your app and write your policy.
2. **Create an API key** for each environment and keep it in your secrets manager.

## Configure

```yaml title="main.yaml"
access:
  driver: oso
  models: [rbac, rebac]
  unreachable: { deny: true, cache: 30s }
  # [TBD] connection keys; suggested secret: OSO_API_KEY
```

## Use it

```ts title="lib/repos.ts"
import { access } from "mainsdk";

const decision = await access.check({ subject: user, action: "repos.write", resource: repo });
if (!decision.allow) throw new Error("forbidden");
```

## Local development and testing

Build on in-process Cedar with `mainsdk dev`. `createTestApp()` from `@mainsdk/testing` puts `access` on its fake, and `chaos.on("access", { outage: true })` shows checks denying with `MAIN-ACCESS-0007`.

## What MainSDK adds on top

- Deny by default, with no bypass path.
- Denies when Oso is unreachable, with only a short cache you set.
- Lists filtered at the database, not after fetching rows.
- Every decision written to the audit log with the policy version.

See [Permissions](https://mainsdk.dev/docs/interfaces/access).

## Limits and notes

- The `access` spec lists Oso as a driver that comes later in phases 1-2 through the driver kit, beyond its capability profile.
- Which models the driver supports is declared in its capability profile; `mainsdk check` names any gap with `MAIN-ACCESS-0004`.
- `access.raw()` returns the Oso client; `mainsdk check` lists every use.

## Swap to or from it

```yaml title="main.yaml"
access:
  driver: cedar   # was oso
```

> **Warning:** Your policy and any facts you sent to Oso live there. Swapping engines means porting both; run `mainsdk test access` on the new driver first.

## FAQ

**Do I rewrite my Polar policy?** Not to adopt the driver. Only if you later move to another engine.

## Next

- [Permissions](https://mainsdk.dev/docs/interfaces/access)
- [Cerbos](https://mainsdk.dev/docs/integrations/cerbos) and [Permit.io](https://mainsdk.dev/docs/integrations/permit-io)
- [Swap a driver](https://mainsdk.dev/docs/guides/swap-a-driver)
