From Tour of Go to Tour of Polar: Teaching Authz with Code
Authorization is one of those things that sounds simple—until you actually have to build it.
As a developer, you’ve probably written if user.isAdmin
more times than you can count. When you first start building an app, authorization (whether a user has permission to do what they’re trying to do) is usually easy. But then use cases start piling up: role inheritance, resource hierarchies, dynamic permissions - things start to get messy.
Oso provides authorization as a service. Authorization rules (what Oso calls a policy) are defined using Oso’s custom DSL for authorization, called Polar.

To help developers learn Polar, we built A Tour of Polar — a developer-focused, interactive learning experience inspired by the classic Tour of Go. It’s a point-and-click playground for exploring how authorization policies work.
And like any good playground, it’s meant to be tinkered with.
Inheriting Roles: Our Favorite Example
One of the examples that really crystallizes the power of Polar for me is the Inheriting Roles lesson.
Here’s the idea: you grant someone access at the top level (say, a repository), and they automatically inherit access down to folders and files.
In Polar:
actor User {}
resource Repository {
roles = ["reader", "maintainer"];
}
resource Folder {
roles = ["reader", "writer"];
relations = {
repository: Repository,
folder: Folder,
};
"reader" if "reader" on "repository";
"writer" if "maintainer" on "repository";
role if role on "folder";
}
resource File {
permissions = ["read", "write"];
roles = ["reader", "writer"];
relations = {
folder: Folder,
};
role if role on "folder";
"read" if "reader";
"write" if "writer";
}
This short snippet encodes logic that would be dozens of lines in app code—and nearly impossible to test well.
The App Structure (and How We Built It)
A Tour of Polar’s source code is available on GitHub. The frontend is built with vanilla HTML, a touch of Tailwind, and a lot of dynamic behavior stitched together by vanilla JavaScript. We didn’t use a framework for this one because we wanted to keep the code concise and limited to 1 file for ease of AI edits.
The frontend is a Tailwind based layout with the following elements:
The left panel holds step-by-step lessons.
The top-right is a live-editable Polar policy and a place to input Facts (authorization data, like what roles a particular user has).
The bottom-right is a query input + result display.
On the backend, we use Vercel + Next.js with a minimal API endpoint (exec.js
) that initializes an Oso instance, loads the user’s policy, and evaluates the authorize()
call with the query + facts.
This gives developers instant feedback when they ask: “Can this user do this thing?”
The key trick is initializing an Oso dev server - which is a non-open-source binary written in Rust.
Using Vercel to Run Executables
The major a-ha moment that made Tour of Polar possible was realizing that you can download and run executables in Vercel’s serverless runtime.
Normally, serverless environments are designed around lightweight API endpoints. You think in terms of JavaScript functions, not binaries. But Oso’s core policy engine is written in Rust and compiled to a native executable. If we wanted developers to write and evaluate Polar policies dynamically in the browser, we needed a way to run the engine on demand.
Instead of trying to run an Oso dev server on a separate server or try to replicate Oso’s authorization logic, we tried the simplest thing that could possibly work:
Use @osohq/dev-server, which downloads the correct Oso dev server distribution for your OS and runs it
When a request comes in, run an Oso dev server if one isn’t already running.
Store a reference to the dev server in global scope to allow reusing the same dev server if Vercel does a warm start
Add some basic in-memory queuing to prevent multiple operations from overwriting each other’s data in the dev server
Execute some API requests against the dev server and return the result to the frontend
To our delight, it worked great! Vercel’s serverless functions allow temporary file storage, so osohq/dev-server can download and run the executable on demand.
It’s a bit of a hack (we haven’t been able to find any Vercel docs which indicate this pattern is officially supported), but it’s also incredibly powerful. We essentially turned Vercel into a temporary playground for an embedded policy engine, where each function invocation becomes its own ephemeral policy evaluator.
Content Refactoring Using AI
The source code for the actual user experience of Tour of Polar is relatively concise. In fact, the largest single chunk of code is the actual content: the copy on the left, the code samples, and the sample fact lists.
Multiply that by 19 explorations and you’ve got a surprisingly dense content surface area. Each lesson has to be:
Technically accurate
Conceptually clear
Visually readable in limited space
And meaningful when executed, not just read
When we finished our first draft of this app, we realized that we really needed a “Facts” input. The first version used Oso’s policy testing framework in lieu of facts, which was a poor representation of how you would work with Oso in practice. So we built the “Facts” input.
But the hardest part of building the Facts input was actually modifying the content to reflect the new Facts input - adding sample facts and updating the copy to describe the sample facts. Without AI, updating all 19 explorations would be a tedious and draining copy/paste exercise.
On the other hand, with some well-structured prompts, Claude 3.7 and Zed handled much of the tedious work. We asked it to update the explorations one at a time—then we tested, proofread, and cleaned up the results. There was still human effort involved: the examples weren’t always accurate, and the generated copy was occasionally awkward or repetitive. But overall, the end result was much better because the AI took care of the tedious and repetitive work almost instantaneously, leaving us with the time and energy to put on the finishing touches.
Try It
A Tour of Polar is live. Whether you’re new to Oso or just curious about what real-world authorization looks like in code, I’d love for you to take it for a spin.
If you have thoughts, questions, or ideas for new lessons, reply to this post or join us in the Oso Community Slack.