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

# QueryContext

> Query permissions without applying the sandbox

`QueryContext` lets you check what operations would be permitted by a capability set without actually applying the sandbox. This is useful for validation, testing, and building permission-checking UIs.

## Constructor

```python theme={null}
QueryContext(caps: CapabilitySet)
```

Create a query context from a capability set.

**caps** `CapabilitySet` *required*

The capability set to query against.

```python theme={null}
from nono_py import CapabilitySet, AccessMode, QueryContext

caps = CapabilitySet()
caps.allow_path("/tmp", AccessMode.READ_WRITE)
caps.block_network()

ctx = QueryContext(caps)
```

> [!NOTE]
>
> The context captures a snapshot of the capabilities at creation time. Changes to the original `CapabilitySet` after creating the context are not reflected.

## Methods

### query\_path

```python theme={null}
query_path(path: str, mode: AccessMode) -> dict
```

Check if a path operation would be permitted.

**path** `str` *required*

Path to check.

**mode** `AccessMode` *required*

Requested access mode.

**Returns:** Dictionary with query result.

#### Allowed Result

When the operation would be permitted:

```python theme={null}
{
    "status": "allowed",
    "reason": "granted_path",
    "granted_path": "/private/tmp",
    "access": "read+write"
}
```

| Field | Description |
| - | - |
| `status` | Always `"allowed"` |
| `reason` | Always `"granted_path"` |
| `granted_path` | The capability that grants access |
| `access` | The access level of that capability |

#### Denied Results

When the operation would be blocked:

**Path not granted:**

```python theme={null}
{
    "status": "denied",
    "reason": "path_not_granted"
}
```

**Insufficient access level:**

```python theme={null}
{
    "status": "denied",
    "reason": "insufficient_access",
    "granted": "read",
    "requested": "write"
}
```

| Field | Description |
| - | - |
| `status` | Always `"denied"` |
| `reason` | `"path_not_granted"` or `"insufficient_access"` |
| `granted` | (Only for insufficient\_access) The granted access level |
| `requested` | (Only for insufficient\_access) The requested access level |

#### Example

```python theme={null}
from nono_py import CapabilitySet, AccessMode, QueryContext

caps = CapabilitySet()
caps.allow_path("/tmp", AccessMode.READ)

ctx = QueryContext(caps)

# Allowed: path is covered with sufficient access
result = ctx.query_path("/tmp/file.txt", AccessMode.READ)
print(result)
# {'status': 'allowed', 'reason': 'granted_path',
#  'granted_path': '/private/tmp', 'access': 'read'}

# Denied: insufficient access
result = ctx.query_path("/tmp/file.txt", AccessMode.WRITE)
print(result)
# {'status': 'denied', 'reason': 'insufficient_access',
#  'granted': 'read', 'requested': 'write'}

# Denied: path not granted
result = ctx.query_path("/etc/passwd", AccessMode.READ)
print(result)
# {'status': 'denied', 'reason': 'path_not_granted'}
```

***

### query\_network

```python theme={null}
query_network() -> dict
```

Check if network access would be permitted.

**Returns:** Dictionary with query result.

#### Allowed Result

```python theme={null}
{
    "status": "allowed",
    "reason": "network_allowed"
}
```

#### Denied Result

```python theme={null}
{
    "status": "denied",
    "reason": "network_blocked"
}
```

#### Example

```python theme={null}
from nono_py import CapabilitySet, QueryContext

# Network allowed by default
caps = CapabilitySet()
ctx = QueryContext(caps)

result = ctx.query_network()
print(result)  # {'status': 'allowed', 'reason': 'network_allowed'}

# Block network
caps.block_network()
ctx = QueryContext(caps)

result = ctx.query_network()
print(result)  # {'status': 'denied', 'reason': 'network_blocked'}
```

## Use Cases

### Configuration Validation

Validate a capability configuration before deployment:

```python theme={null}
def validate_config(caps: CapabilitySet, required_paths: list[tuple[str, AccessMode]]) -> bool:
    ctx = QueryContext(caps)

    for path, mode in required_paths:
        result = ctx.query_path(path, mode)
        if result["status"] == "denied":
            print(f"Missing permission: {path} ({mode})")
            return False

    return True

# Check that all required paths are covered
caps = CapabilitySet()
caps.allow_path("/data", AccessMode.READ_WRITE)

required = [
    ("/data/input", AccessMode.READ),
    ("/data/output", AccessMode.WRITE),
]

if validate_config(caps, required):
    apply(caps)
```

### Permission Checking UI

Build an interactive permission checker:

```python theme={null}
def check_operation(ctx: QueryContext, path: str, mode: AccessMode) -> str:
    result = ctx.query_path(path, mode)

    if result["status"] == "allowed":
        return f"ALLOWED via {result['granted_path']}"
    elif result["reason"] == "insufficient_access":
        return f"DENIED: have {result['granted']}, need {result['requested']}"
    else:
        return "DENIED: path not granted"
```

### Testing Capability Sets

Write tests for your sandbox configuration:

```python theme={null}
import pytest
from nono_py import CapabilitySet, AccessMode, QueryContext

def test_sandbox_config():
    caps = CapabilitySet()
    caps.allow_path("/tmp", AccessMode.READ_WRITE)
    caps.allow_path("/data", AccessMode.READ)
    caps.block_network()

    ctx = QueryContext(caps)

    # Verify expected permissions
    assert ctx.query_path("/tmp/file", AccessMode.WRITE)["status"] == "allowed"
    assert ctx.query_path("/data/input", AccessMode.READ)["status"] == "allowed"
    assert ctx.query_path("/data/input", AccessMode.WRITE)["status"] == "denied"
    assert ctx.query_network()["status"] == "denied"
```

## Related

* [CapabilitySet](https://nono.sh/docs/python/api/capability-set.md) - Build the capability set to query
* [AccessMode](https://nono.sh/docs/python/api/access-mode.md) - Access modes for queries


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