> ## Documentation Index
> Fetch the complete documentation index at: https://www.osohq.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Local Authorization

> Perform authorization checks directly against your database for better performance.

Local authorization allows you to generate SQL queries that can be executed directly against your database, providing better performance for authorization checks by avoiding round trips to Oso Cloud.

## List Local

Generate SQL conditions to filter resources that an actor can access, perfect for implementing authorization in database queries.

**Node.js**

```javascript theme={null}
// Generate SQL condition for authorized resources
const sqlCondition = await oso.listLocal(alice, "read", "Issue", "id");

// Use with database query (example with Kysely)
const authorized_issues = await db
  .selectFrom("issues")
  .where(sql.raw<boolean>(sqlCondition))
  .selectAll()
  .execute();

// With context facts
const sqlCondition = await oso.listLocal(
  alice, 
  "read", 
  "Issue", 
  "id",
  [["has_role", alice, "admin", repository]]  // Context facts
);

console.log("Authorized issues:", authorized_issues.length);
```

**Signature:** `oso.listLocal(actor, action, resource_type, column, contextFacts?)`

```python theme={null}
# Generate SQL condition for authorized resources
sql_condition = oso.list_local(alice, "read", "Issue", "id")

# Use with SQLAlchemy
from sqlalchemy import select, text

authorized_issues = session.scalars(
    select(Issues).filter(text(sql_condition))
).all()

# With context facts
sql_condition = oso.list_local(
    alice, 
    "read", 
    "Issue", 
    "id",
    context_facts=[("has_role", alice, "admin", repository)]
)

print(f"Found {len(authorized_issues)} authorized issues")
```

**Signature:** `oso.list_local(actor, action, resource_type, column, context_facts=None)`

```go theme={null}
// Generate SQL condition for authorized resources
sqlCondition, err := osoClient.ListLocal(user, "read", "Issue", "id")
if err != nil {
    log.Fatal(err)
}

// Use with GORM
var issues []Issue
db.Find(&issues, sqlCondition)

// With context facts
contextFacts := []oso.Fact{
    oso.NewFact("has_role", user, oso.String("admin"), repository),
}
sqlCondition, err = osoClient.ListLocalWithContext(user, "read", "Issue", "id", contextFacts)
if err != nil {
    log.Fatal(err)
}

var contextIssues []Issue
db.Find(&contextIssues, sqlCondition)

fmt.Printf("Found %d authorized issues\n", len(issues))
```

**Signature:** `osoClient.ListLocal(actor, action, resourceType, column)` | `osoClient.ListLocalWithContext(actor, action, resourceType, column, contextFacts)`

```java theme={null}
// Generate SQL condition for authorized resources
String filterSql = oso.listLocal(alice, "read", "Issue", "id");

// Use with JPA
List<Issue> authorizedIssues = entityManager
    .createNativeQuery("SELECT * FROM issues WHERE " + filterSql, Issue.class)
    .getResultList();

// With context facts
List<Fact> contextFacts = Arrays.asList(
    new Fact("has_role", Arrays.asList(alice, new Value("admin"), repository))
);
String contextFilterSql = oso.listLocal(alice, "read", "Issue", "id", contextFacts);

List<Issue> contextAuthorizedIssues = entityManager
    .createNativeQuery("SELECT * FROM issues WHERE " + contextFilterSql, Issue.class)
    .getResultList();

System.out.println("Found " + authorizedIssues.size() + " authorized issues");
```

**Signature:** `oso.listLocal(actor, action, resourceType, column, contextFacts?)`

```ruby theme={null}
# Generate SQL condition for authorized resources
sql_condition = oso.list_local(alice, "read", "Issue", "id")

# Use with ActiveRecord
authorized_issues = Issue.where(sql_condition)

# With context facts
sql_condition_with_context = oso.list_local(
  bob, 
  "read", 
  "Issue", 
  "id", 
  context_facts: [["has_role", bob, "admin", anvils_repository]]
)

context_authorized_issues = Issue.where(sql_condition_with_context)

puts "Found #{authorized_issues.count} authorized issues"
```

**Signature:** `oso.list_local(actor, action, resource_type, column, context_facts=nil)`

```csharp theme={null}
// Generate SQL condition for authorized resources
var filterResult = await oso.ListLocal(alice, "read", "Issue", "id");
var filterSql = filterResult.Sql;

// Use with Entity Framework
var authorizedIssues = db.Issues
    .FromSqlRaw($"SELECT * FROM issue WHERE {filterSql}")
    .ToList();

// With context facts
var contextFacts = new List<Fact> { 
    new Fact("has_role", new List<Value> { alice, new Value("String", "admin"), repository })
};
var contextFilterResult = await oso.ListLocal(alice, "read", "Issue", "id", contextFacts);
var contextFilterSql = contextFilterResult.Sql;

Console.WriteLine($"Found {authorizedIssues.Count} authorized issues");
```

**Signature:** `oso.ListLocal(actor, action, resource_type, column, contextFacts?)`

**CLI**

```bash theme={null}
# Generate SQL condition for local authorization
oso-cloud list-local \
  --data-bindings path/to/local_authorization_config.yaml \
  User:alice read Issue id

# This outputs SQL that can be used in your database queries
```

**Signature:** `oso-cloud list-local --data-bindings <config-file> <actor> <action> <resource-type> <column>`

## Authorize Local

Generate SQL queries to check if an actor is authorized to perform an action on a specific resource.

**Node.js**

```javascript theme={null}
// Generate authorization check SQL
const query = await oso.authorizeLocal(alice, "read", swage_issue);

// Execute with database (example with raw SQL)
const result = await sql.raw<AuthorizeResult>(query).execute(db);
const { allowed } = result.rows[0];

if (!allowed) {
  throw new Error("Access denied");
}

// With context facts
const contextQuery = await oso.authorizeLocal(
  alice, 
  "read", 
  swage_issue,
  [["has_role", alice, "admin", repository]]
);

console.log(`Access ${allowed ? 'granted' : 'denied'}`);
```

**Signature:** `oso.authorizeLocal(actor, action, resource, contextFacts?)`

```python theme={null}
# Generate authorization check SQL
query = oso.authorize_local(alice, "read", swage_issue)

# Execute with SQLAlchemy
from sqlalchemy import text

authorized = session.execute(text(query)).scalar()

if not authorized:
    raise Exception("Access denied")

# With context facts
context_query = oso.authorize_local(
    alice, 
    "read", 
    swage_issue,
    context_facts=[("has_role", alice, "admin", repository)]
)

context_authorized = session.execute(text(context_query)).scalar()
print(f"Access {'granted' if authorized else 'denied'}")
```

**Signature:** `oso.authorize_local(actor, action, resource, context_facts=None)`

```go theme={null}
// Generate authorization check SQL
query, err := osoClient.AuthorizeLocal(alice, "read", swageIssue)
if err != nil {
    log.Fatal(err)
}

// Execute with GORM
var authorizeResult AuthorizeResult
db.Raw(query).Scan(&authorizeResult)

if !authorizeResult.Allowed {
    return fmt.Errorf("access denied")
}

// With context facts
contextFacts := []oso.Fact{
    oso.NewFact("has_role", alice, oso.String("admin"), repository),
}
contextQuery, err := osoClient.AuthorizeLocalWithContext(alice, "read", swageIssue, contextFacts)
if err != nil {
    log.Fatal(err)
}

var contextAuthorizeResult AuthorizeResult
db.Raw(contextQuery).Scan(&contextAuthorizeResult)

fmt.Printf("Access %s\n", map[bool]string{true: "granted", false: "denied"}[authorizeResult.Allowed])
```

**Signature:** `osoClient.AuthorizeLocal(actor, action, resource)` | `osoClient.AuthorizeLocalWithContext(actor, action, resource, contextFacts)`

```java theme={null}
// Generate authorization check SQL
String sqlQuery = oso.authorizeLocal(alice, "read", swageIssue);

// Execute with JPA
boolean allowed = (Boolean) entityManager
    .createNativeQuery(sqlQuery)
    .getSingleResult();

if (!allowed) {
    throw new SecurityException("Access denied");
}

// With context facts
List<Fact> contextFacts = Arrays.asList(
    new Fact("has_role", Arrays.asList(alice, new Value("admin"), repository))
);
String contextSqlQuery = oso.authorizeLocal(alice, "read", swageIssue, contextFacts);

boolean contextAllowed = (Boolean) entityManager
    .createNativeQuery(contextSqlQuery)
    .getSingleResult();

System.out.println("Access " + (allowed ? "granted" : "denied"));
```

**Signature:** `oso.authorizeLocal(actor, action, resource, contextFacts?)`

```ruby theme={null}
# Generate authorization check SQL
query = oso.authorize_local(alice, "read", swage_issue)

# Execute with ActiveRecord
allowed = Issue.connection.select_value(query)

raise "Access denied" unless allowed

# With context facts
context_query = oso.authorize_local(
  bob, 
  "read", 
  swage_issue, 
  context_facts: [["has_role", bob, "admin", anvils_repository]]
)

context_allowed = Issue.connection.select_value(context_query)
puts allowed ? "Access granted" : "Access denied"
```

**Signature:** `oso.authorize_local(actor, action, resource, context_facts=nil)`

```csharp theme={null}
// Generate authorization check SQL
var sqlResult = await oso.AuthorizeLocal(alice, "read", swage_issue);
var sql = sqlResult.Sql;

// Execute with Entity Framework
var result = db.AuthorizeResults
    .FromSqlRaw(sql)
    .Single();

if (!result.Allowed) {
    throw new UnauthorizedAccessException("Access denied");
}

// With context facts
var contextFacts = new List<Fact> { 
    new Fact("has_role", new List<Value> { alice, new Value("String", "admin"), repository })
};
var contextSqlResult = await oso.AuthorizeLocal(alice, "read", swage_issue, contextFacts);
var contextSql = contextSqlResult.Sql;

Console.WriteLine($"Access {(result.Allowed ? "granted" : "denied")}");
```

**Signature:** `oso.AuthorizeLocal(actor, action, resource, contextFacts?)`

**CLI**

```bash theme={null}
# Generate authorization check SQL
oso-cloud authorize-local \
  --data-bindings path/to/local_authorization_config.yaml \
  User:alice read Issue:swage

# This outputs SQL that returns a boolean result
```

**Signature:** `oso-cloud authorize-local --data-bindings <config-file> <actor> <action> <resource>`

## Actions Local

Generate SQL queries to get all actions an actor can perform on a specific resource.

**Node.js**

```javascript theme={null}
// Generate actions query SQL
const query = await oso.actionsLocal(alice, swage_issue);

// Execute with database
const result = await sql.raw<{ actions: string }>(query).execute(db);
const actions = result.rows.map(row => row.actions);

console.log("Available actions:", actions);

// With context facts
const contextQuery = await oso.actionsLocal(
  alice, 
  swage_issue,
  [["has_role", alice, "admin", repository]]
);

const contextResult = await sql.raw<{ actions: string }>(contextQuery).execute(db);
const contextActions = contextResult.rows.map(row => row.actions);
```

**Signature:** `oso.actionsLocal(actor, resource, contextFacts?)`

```python theme={null}
# Generate actions query SQL
query = oso.actions_local(alice, swage_issue)

# Execute with SQLAlchemy
from sqlalchemy import text

actions = list(session.execute(text(query)).scalars())

print(f"Available actions: {actions}")

# With context facts
context_query = oso.actions_local(
    alice, 
    swage_issue,
    context_facts=[("has_role", alice, "admin", repository)]
)

context_actions = list(session.execute(text(context_query)).scalars())
```

**Signature:** `oso.actions_local(actor, resource, context_facts=None)`

```go theme={null}
// Generate actions query SQL
query, err := osoClient.ActionsLocal(alice, swageIssue)
if err != nil {
    log.Fatal(err)
}

// Execute with GORM
var actions []string
db.Raw(query).Pluck("actions", &actions)

fmt.Printf("Available actions: %v\n", actions)

// With context facts
contextFacts := []oso.Fact{
    oso.NewFact("has_role", alice, oso.String("admin"), repository),
}
contextQuery, err := osoClient.ActionsLocalWithContext(alice, swageIssue, contextFacts)
if err != nil {
    log.Fatal(err)
}

var contextActions []string
db.Raw(contextQuery).Pluck("actions", &contextActions)
```

**Signature:** `osoClient.ActionsLocal(actor, resource)` | `osoClient.ActionsLocalWithContext(actor, resource, contextFacts)`

```java theme={null}
// Generate actions query SQL
String sqlQuery = oso.actionsLocal(alice, swageIssue);

// Execute with JPA
@SuppressWarnings("unchecked")
List<String> actions = entityManager
    .createNativeQuery(sqlQuery)
    .getResultList();

System.out.println("Available actions: " + actions);

// With context facts
List<Fact> contextFacts = Arrays.asList(
    new Fact("has_role", Arrays.asList(alice, new Value("admin"), repository))
);
String contextSqlQuery = oso.actionsLocal(alice, swageIssue, contextFacts);

@SuppressWarnings("unchecked")
List<String> contextActions = entityManager
    .createNativeQuery(contextSqlQuery)
    .getResultList();
```

**Signature:** `oso.actionsLocal(actor, resource, contextFacts?)`

```ruby theme={null}
# Generate actions query SQL
query = oso.actions_local(alice, swage_issue)

# Execute with ActiveRecord
actions = Issue.connection.select_all(query).pluck("actions")

puts "Available actions: #{actions}"

# With context facts
context_query = oso.actions_local(
  bob, 
  swage_issue, 
  context_facts: [["has_role", bob, "admin", anvils_repository]]
)

context_actions = Issue.connection.select_all(context_query).pluck("actions")
```

**Signature:** `oso.actions_local(actor, resource, context_facts=nil)`

```csharp theme={null}
// Generate actions query SQL
var sqlResult = await oso.ActionsLocal(bob, environmentAny);
var sql = sqlResult.Sql;

// Execute with Entity Framework
var result = db.ActionResults
    .FromSqlRaw(sql)
    .ToList();

var actions = result.Select(a => a.Actions).ToList();
Console.WriteLine($"Available actions: {string.Join(", ", actions)}");

// With context facts
var contextFacts = new List<Fact> { 
    new Fact("has_role", new List<Value> { bob, new Value("String", "admin"), repository })
};
var contextSqlResult = await oso.ActionsLocal(bob, environmentAny, contextFacts);
var contextSql = contextSqlResult.Sql;
```

**Signature:** `oso.ActionsLocal(actor, resource, contextFacts?)`

## Query Builder Local

Use the query builder to generate SQL for complex authorization queries with additional constraints.

**Node.js**

```javascript theme={null}
// Generate SQL for field-level authorization
const sqlQuery = await oso.buildQuery([
  "allow_field", 
  actor, 
  "read", 
  resource, 
  field
]).evaluateLocalSelect({ field_name: field });

// Execute field authorization query
const fieldResult = await sql.raw(sqlQuery).execute(db);

// Generate SQL filter for authorized users
const authorizedUserFragment = await oso.buildQuery([
  "allow", 
  actor_var, 
  "read", 
  resource
]).evaluateLocalFilter("id", actor_var);

// Use in WHERE clause
const filteredQuery = `SELECT * FROM users WHERE ${authorizedUserFragment}`;
```

**Methods:** `evaluateLocalSelect({field_name: field})` | `evaluateLocalFilter("column", variable)`

```python theme={null}
# Generate SQL for field-level authorization
sql_query = oso.build_query((
  "allow_field", 
  actor, 
  "read", 
  resource, 
  field
)).evaluate_local_select({"field_name": field})

# Execute field authorization query
field_result = session.execute(text(sql_query)).fetchall()

# Generate SQL filter for authorized users
authorized_user_fragment = oso.build_query((
  "allow", 
  actor_var, 
  "read", 
  resource
)).evaluate_local_filter("id", actor_var)

# Use in WHERE clause
filtered_query = f"SELECT * FROM users WHERE {authorized_user_fragment}"
```

**Methods:** `evaluate_local_select({"field_name": field})` | `evaluate_local_filter("column", variable)`

```go theme={null}
// Generate SQL for field-level authorization
sqlQuery, err := osoClient.BuildQuery(
  oso.NewQueryFact("allow_field", actor, oso.String("read"), resource, fieldVar),
).EvaluateLocalSelect(map[string]oso.Variable{"field_name": fieldVar})
if err != nil {
    log.Fatal(err)
}

// Execute field authorization query
var fieldResult []map[string]interface{}
db.Raw(sqlQuery).Scan(&fieldResult)

// Generate SQL filter for authorized users
authorizedUserFragment, err := osoClient.BuildQuery(
  oso.NewQueryFact("allow", actorVar, oso.String("read"), resource),
).EvaluateLocalFilter("id", actorVar)
if err != nil {
    log.Fatal(err)
}

// Use in WHERE clause
filteredQuery := fmt.Sprintf("SELECT * FROM users WHERE %s", authorizedUserFragment)
```

**Methods:** `EvaluateLocalSelect(map[string]Variable{"field_name": fieldVar})` | `EvaluateLocalFilter("column", variable)`

## Configuration Validation

Validate your local authorization configuration before using it in production.

**CLI**

```bash theme={null}
# Validate local authorization configuration
oso-cloud validate-local-authorization-config \
  path/to/local_authorization_config.yaml \
  -c postgres://localhost:5432/mydb \
  -p main.polar

# This checks that your configuration is valid and can connect to the database
```

**Signature:** `oso-cloud validate-local-authorization-config <config-file> -c <connection-string> -p <policy-file>`


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.