Spaces:
Sleeping
Sleeping
File size: 9,372 Bytes
e28ed64 543a85f e28ed64 543a85f e28ed64 543a85f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | ---
title: Privilege Desk
emoji: π’
colorFrom: blue
colorTo: indigo
sdk: docker
pinned: false
app_port: 8000
base_path: /web
---
# PrivilegeDesk
**Zero-Standing-Privilege Ops Environment for Training AI Agents**
A simulated enterprise access-control environment built on [OpenEnv](https://github.com/meta-pytorch/OpenEnv).
An AI agent is dropped into a synthetic corporate IAM system and must handle real-world privilege management tasks β from reviewing a single access request to conducting a full entitlement audit.
---
## Environment Overview
| Property | Value |
|----------|-------|
| **Domain** | Identity & Access Management (IAM) |
| **Tasks** | 3 (easy β medium β hard) |
| **Tools** | 19 structured tool calls |
| **Reward** | Partial credit, 0.0β1.0, deterministic grading |
| **Generation** | Fully procedural β unique episode per seed |
| **API** | OpenEnv-compliant (reset / step / state / grader / tasks / baseline) |
---
## The 3 Tasks
### Task 1 β Access Decision (`access_decision`) Β· Easy
> "A new access request has arrived. Review the request, inspect the applicable policy, and decide whether to approve or deny it. If approving, select the correct role and TTL."
- **Steps**: 1β5
- **Grading**: correct decision (40%) + correct role (25%) + correct TTL (20%) + justification category (15%)
- **Baseline difficulty**: ~0.7β0.9 with a well-prompted LLM
### Task 2 β JIT Escalation (`jit_escalation`) Β· Medium
> "Process an urgent just-in-time privilege escalation: find the correct approval chain, route the request in order, attach the incident ticket, set the TTL, and activate the grant."
- **Steps**: 3β15
- **Grading**: correct approvers (20%) + routing order (15%) + ticket attached (15%) + role (15%) + TTL (15%) + final decision (20%)
- **Baseline difficulty**: ~0.4β0.6 with a well-prompted LLM
### Task 3 β Access Review (`access_review`) Β· Hard
> "Conduct an access review for a user. Identify risky, stale, or over-privileged entitlements and revoke the minimum set β without breaking active workflows."
- **Steps**: 5β25
- **Grading**: precision (30%) + recall (30%) + workflow preservation (20%) + policy compliance (10%) + submission (10%)
- **Baseline difficulty**: ~0.2β0.4 with a well-prompted LLM
---
## The World Model
Each episode procedurally generates a complete synthetic enterprise from a seed:
| Entity | Description |
|--------|-------------|
| **Users** | Employees with name, email, department, manager |
| **Resources** | Databases, repos, cloud projects, admin consoles |
| **Policies** | Rules: max role + max TTL + required approvers per resource |
| **Entitlements** | Current userβroleβresource assignments |
| **Groups** | Team groups for inherited permissions (Task 3) |
| **Approval Chains** | Ordered approver lists per request (Task 2) |
| **Workflows** | Active pipelines that depend on entitlements (Task 3) |
| **Audit DB** | Historical access events queryable via `audit.query` |
| **Hidden State** | Ground truth β generated at reset, used by grader |
---
## API Reference
### Standard OpenEnv Endpoints
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/reset` | POST | Start a new episode. Pass `task_id` and optional `seed`. |
| `/step` | POST | Execute a tool call. Returns observation + reward + done. |
| `/state` | GET | Current episode metadata (episode_id, step_count). |
| `/schema` | GET | JSON schemas for Action and Observation. |
| `/health` | GET | Health check. |
### Hackathon-Required Endpoints
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/tasks` | GET | Lists all 3 tasks with schemas and grading weights. |
| `/grader` | POST | Returns 0.0β1.0 episode score with full breakdown. |
| `/baseline` | POST | Runs naive baseline agent on all 3 tasks. |
### Reset Parameters
```json
{
"task_id": "access_decision", // "access_decision" | "jit_escalation" | "access_review"
"seed": 42, // optional β omit for random episode
"difficulty_level": 1 // 1-3 (scales entity counts)
}
```
### Step Action Format
```json
{
"action": {
"tool_name": "access.decide",
"arguments": {
"request_id": "req_000",
"decision": "approve",
"role": "viewer",
"ttl_hours": 4,
"justification_category": "operational"
}
}
}
```
---
## Available Tools (19 total)
| Tool | Arguments | Used In |
|------|-----------|---------|
| `policy.lookup` | `resource_id` | T1, T2 |
| `policy.list` | β | T1, T2, T3 |
| `org.get_user` | `user_id` | T1, T2, T3 |
| `org.get_manager` | `user_id` | T2 |
| `org.list_users` | `department?` | T2, T3 |
| `request.view` | `request_id?` | T1, T2 |
| `request.list` | β | T2 |
| `approval.route` | `request_id`, `approver_id` | T2 |
| `approval.check_status` | `request_id` | T2 |
| `access.decide` | `request_id`, `decision`, `role`, `ttl_hours`, `justification_category?` | T1 |
| `access.grant` | `request_id` | T2 |
| `access.set_ttl` | `request_id`, `ttl_hours` | T2 |
| `entitlement.list` | `user_id?` | T1, T3 |
| `entitlement.inspect` | `entitlement_id` | T3 |
| `entitlement.revoke` | `entitlement_id`, `reason?` | T3 |
| `audit.query` | `user_id?`, `resource_id?`, `days?` | T3 |
| `group.resolve` | `group_id?` or `user_id?` | T3 |
| `workflow.check_active` | `user_id?`, `entitlement_id?` | T3 |
| `review.submit` | `summary?` | T3 |
---
## Reward Design
### Per-Step Rewards (returned on every `/step`)
- `+0.02β0.05` for discovering new information (policies, entitlements, audit logs)
- `+0.05β0.08` for correctly identifying or revoking a risky entitlement
- `-0.02` for tool errors
- `-0.01` for redundant (repeated) tool calls
- `-0.03` for routing to the wrong approver
- `-0.10` for revoking a workflow-critical entitlement
### Episode Score (returned when `done=True`, accessible via `/grader`)
All task graders return a weighted 0.0β1.0 score with **partial credit**. Binary 0/1 is never used β every field is independently gradable.
---
## Local Development
```bash
# Install dependencies
cd privilege_desk
uv sync
# Run server (hot-reload)
uv run server
# OR
uvicorn server.app:app --host 0.0.0.0 --port 8000 --reload
# Test episode generation
uv run python -c "
import sys; sys.path.insert(0, '.')
from pipeline.episode_generator import generate_episode
ws = generate_episode(task_id='access_decision', seed=42)
print('Users:', len(ws['users']), 'Policies:', len(ws['policies']))
"
# Run baseline inference (requires API key)
export API_BASE_URL=https://router.huggingface.co/v1
export HF_TOKEN=hf_...
export MODEL_NAME=meta-llama/Llama-3.3-70B-Instruct
uv run python inference.py
# Validate submission
openenv validate
```
## Docker
```bash
# Build
docker build -t privilege-desk:latest -f server/Dockerfile .
# Run
docker run -p 8000:8000 privilege-desk:latest
# Health check
curl http://localhost:8000/health
```
---
## Architecture
```
privilege_desk/
βββ models.py # Pydantic Action + Observation
βββ pipeline/
β βββ episode_generator.py # Procedural world generation
β βββ task_templates.py # 3 task definitions
βββ env/
β βββ world_state.py # Episode lifecycle (reset/step/grade)
β βββ action_router.py # Tool dispatch + audit log
β βββ tools.py # All 19 tool implementations
βββ reward/
β βββ grader.py # Per-task graders (0.0β1.0)
β βββ aggregator.py # Step reward + episode score
βββ server/
β βββ app.py # FastAPI app (standard + custom endpoints)
β βββ privilege_desk_environment.py # OpenEnv Environment subclass
βββ inference.py # Baseline LLM agent
βββ openenv.yaml # OpenEnv spec declaration
βββ Dockerfile # HF Spaces deployment
```
---
## Grading Details
### Task 1: Access Decision
| Component | Weight | What's Checked |
|-----------|--------|----------------|
| Correct approve/deny | 40% | Matches policy: requested role β€ max_role |
| Correct role | 25% | Exact match to policy max_role (partial credit for lower roles) |
| Correct TTL | 20% | Within Β±2h of policy max_ttl |
| Justification category | 15% | Correct category label |
### Task 2: JIT Escalation
| Component | Weight | What's Checked |
|-----------|--------|----------------|
| Correct approvers | 20% | Set of routed approver IDs matches required chain |
| Routing order | 15% | Sequential order matches policy chain |
| Ticket attached | 15% | Non-empty ticket_id in request |
| Correct role | 15% | Requested role β€ policy max_role |
| Correct TTL | 15% | Within Β±2h of policy max_ttl |
| Final grant/deny | 20% | Correctly activated or denied |
### Task 3: Access Review
| Component | Weight | What's Checked |
|-----------|--------|----------------|
| Precision | 30% | Revoked entitlements that were genuinely risky |
| Recall | 30% | Risky entitlements that were caught |
| Workflow preservation | 20% | No active workflows broken |
| Policy compliance | 10% | Remaining entitlements pass policy check |
| Submission | 10% | `review.submit` was called |
---
## License
BSD-style β see LICENSE file.
|