Docs/Migration Guide

Migration Guide

Step-by-step migration paths from common authorization systems to PermitNetworks. Each section covers conceptual mapping and practical code changes.

From Homegrown Authorization

Most teams start with if/else checks scattered across their codebase. These checks have no audit trail, no rate limiting, and no way to change rules without a code deploy. PermitNetworks centralizes them.

Step 1 — Replace inline checks with authorize()

Before
// Scattered across codebase
async function purchaseItem(agent, item) {
  // Hardcoded, hard to audit
  if (agent.role === "buyer") {
    if (item.price < 10000) {
      if (approvedVendors.includes(item.vendor)) {
        await executePurchase(item);
      }
    }
  }
  // No audit trail
  // No rate limiting
  // Rule change = code deploy
}
After
// Centralized, auditable
import { PermitClient } from "@permitnetworks/sdk";

const permit = new PermitClient({
  apiKey: process.env.PERMIT_API_KEY!,
  agentId: "purchase-bot",
});

async function purchaseItem(item) {
  const decision = await permit.authorize({
    action: "payment.create",
    context: {
      amount: item.price,
      vendor: item.vendor,
    },
  });

  if (decision.effect === "allow") {
    await executePurchase(item);
    await permit.confirm(decision.id);
  }
}

Step 2 — Translate rules to policies

For each condition block in your code, create a matching policy rule:

Policy JSON (replaces all the if/else logic)
{
  "name": "purchase-bot-limits",
  "agents": ["purchase-bot"],
  "rules": [
    {
      "action": "payment.create",
      "effect": "allow",
      "conditions": {
        "context.amount": { "$lt": 10000 },
        "context.vendor": { "$in": ["vendor-a", "vendor-b", "vendor-c"] }
      }
    },
    {
      "action": "payment.create",
      "effect": "deny"
    }
  ],
  "budget": {
    "limit": 50000,
    "unit": "USD",
    "period": "monthly"
  }
}

Migration checklist

  • 1Install @permitnetworks/sdk and configure API key
  • 2Identify all authorization check locations in your codebase
  • 3Replace each check with permit.authorize()
  • 4Translate each condition block to a policy rule
  • 5Add permit.confirm() after successful operations
  • 6Verify decisions in the dashboard audit log
  • 7Remove old if/else authorization code

From Open Policy Agent (OPA)

OPA is a general-purpose policy engine using the Rego language. PermitNetworks uses a simpler JSON policy format purpose-built for AI agent authorization, with built-in budget tracking and audit infrastructure.

Concept mapping

OPA conceptPermitNetworks equivalent
Rego policy modulePolicy JSON document
input documentcontext object in authorize()
data documentPolicy conditions + context fields
OPA decision (true/false)Decision (allow/deny/review/log)
OPA server /v1/data/POST /v1/decisions
OPA bundleNot applicable — policies managed via API/dashboard
Partial evaluationNot yet supported (coming soon)

Code comparison

OPA — Rego policy
package authz

default allow := false

allow if {
    input.action == "payment.create"
    input.context.amount <= 5000
    input.context.currency in {"USD", "EUR"}
}
PermitNetworks — Policy JSON
{
  "name": "payment-limits",
  "rules": [{
    "action": "payment.create",
    "effect": "allow",
    "conditions": {
      "context.amount": { "$lte": 5000 },
      "context.currency": { "$in": ["USD", "EUR"] }
    }
  }]
}
OPA — HTTP query
curl -X POST http://opa:8181/v1/data/authz/allow \
  -d '{ "input": { "action": "payment.create", "context": { "amount": 500 } } }'
PermitNetworks — HTTP query
curl -X POST https://api.permitnetworks.com/v1/decisions \
  -H "Authorization: Bearer pn_live_sk_..." \
  -d '{ "agent_id": "billing-bot", "action": "payment.create", "context": { "amount": 500 } }'

From Permit.io

Permit.io focuses on human RBAC/ABAC authorization. PermitNetworks is purpose-built for AI agent authorization — with budget tracking, decision lifecycle, and cryptographic audit trails. The SDK interface is similar but the data model differs.

Permit.io conceptPermitNetworks equivalent
UserAgent
RolePolicy (more expressive than roles)
Resource instanceresource string in authorize()
permit.check(user, action, resource)permit.authorize({ action, resource })
TenantNot applicable (single-tenant per account)
PDP sidecarManaged PDP — no sidecar needed
Permit.io
const { Permit } = require("permitio");

const permit = new Permit({
  token: process.env.PERMIT_TOKEN,
  pdp: "http://localhost:7766",
});

const allowed = await permit.check(
  user.id,
  "create",
  "document"
);
PermitNetworks
import { PermitClient } from "@permitnetworks/sdk";

const permit = new PermitClient({
  apiKey: process.env.PERMIT_API_KEY,
  agentId: agent.id,
});

const decision = await permit.authorize({
  action: "document.create",
  context: { user_id: user.id },
});
// decision.effect === "allow" | "deny"

From Auth0 FGA (OpenFGA)

Auth0 FGA is a relationship-based access control (ReBAC) system using a tuple model. PermitNetworks uses a policy/rule model better suited for AI agent authorization where the key questions are about what actions an agent can take, not about graph relationships.

OpenFGA conceptPermitNetworks equivalent
Authorization Model (DSL)Policy JSON document
Tuple (user, relation, object)Rule (agent, action, resource)
Check APIPOST /v1/decisions
Relationship tuplesPolicy conditions (no tuple store needed)
Expand APINot applicable

If your FGA model uses simple role → permission relationships (no deep graph traversal), migration is straightforward: each permitted (role, action, object-type) tuple becomes a policy rule. Complex relationship chains are not currently supported in PermitNetworks — contact us if this is a requirement.

OpenFGA check
const response = await fgaClient.check({
  user: "user:agent-123",
  relation: "can_create",
  object: "payment:acct_9kx2m",
});
// response.allowed: true | false
PermitNetworks
const decision = await permit.authorize({
  action: "payment.create",
  resource: "account:acct_9kx2m",
});
// decision.effect: "allow" | "deny"
// + audit trail, budget tracking,
// + webhooks, permits

General Migration Notes

  • Run PermitNetworks in parallel with your existing system during migration. Use the "log" effect to audit without blocking, then switch to "allow"/"deny" once confident.
  • PermitNetworks always defaults to deny if no policy matches. Start by creating allow policies, not deny policies.
  • The decision confirm/reject lifecycle is unique to PermitNetworks and has no equivalent in most other systems — it is optional but enables accurate budget tracking.
  • Permit tokens can be used to verify authorization in downstream services without an extra API call — similar to JWT bearer tokens but with a cryptographic audit trail.

Need help with a migration not covered here? Contact us and we will help you map your existing system to PermitNetworks.