- Add migration 013_city_map_coordinates.sql with map coordinates, zones, and agents table - Add /city/map API endpoint in city-service - Add /city/agents and /city/agents/online endpoints - Extend presence aggregator to include agents[] in snapshot - Add AgentsSource for fetching agent data from DB - Create CityMap component with interactive room tiles - Add useCityMap hook for fetching map data - Update useGlobalPresence to include agents - Add map/list view toggle on /city page - Add agent badges to room cards and map tiles
353 lines
6.3 KiB
Markdown
353 lines
6.3 KiB
Markdown
# PDP Service (Policy Decision Point)
|
|
|
|
**Port:** 7012
|
|
**Purpose:** Centralized access control for DAARION
|
|
|
|
## Features
|
|
|
|
✅ **Policy Evaluation:**
|
|
- MicroDAO access (owner/admin/member)
|
|
- Channel access (SEND_MESSAGE, READ, MANAGE)
|
|
- Tool execution (allowed_agents + roles)
|
|
- Agent management
|
|
- Usage viewing
|
|
|
|
✅ **Policy Storage:**
|
|
- Config-based (Phase 4)
|
|
- Database-backed (Phase 5)
|
|
|
|
✅ **Audit Logging:**
|
|
- Every decision logged to security_audit
|
|
- Integration with audit service
|
|
|
|
## Policy Model
|
|
|
|
### Actor Identity
|
|
```json
|
|
{
|
|
"actor_id": "user:93",
|
|
"actor_type": "human",
|
|
"microdao_ids": ["microdao:7"],
|
|
"roles": ["member", "admin"]
|
|
}
|
|
```
|
|
|
|
### Policy Request
|
|
```json
|
|
{
|
|
"actor": {...ActorIdentity...},
|
|
"action": "send_message",
|
|
"resource": {
|
|
"type": "channel",
|
|
"id": "channel-uuid"
|
|
},
|
|
"context": {}
|
|
}
|
|
```
|
|
|
|
### Policy Decision
|
|
```json
|
|
{
|
|
"effect": "permit",
|
|
"reason": "channel_member",
|
|
"obligations": {}
|
|
}
|
|
```
|
|
|
|
## API
|
|
|
|
### POST /internal/pdp/evaluate
|
|
|
|
Evaluate access control policy:
|
|
|
|
```bash
|
|
curl -X POST http://localhost:7012/internal/pdp/evaluate \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"actor": {
|
|
"actor_id": "user:93",
|
|
"actor_type": "human",
|
|
"microdao_ids": ["microdao:7"],
|
|
"roles": ["member"]
|
|
},
|
|
"action": "send_message",
|
|
"resource": {
|
|
"type": "channel",
|
|
"id": "channel-general"
|
|
}
|
|
}'
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"effect": "permit",
|
|
"reason": "channel_member"
|
|
}
|
|
```
|
|
|
|
### GET /internal/pdp/policies
|
|
|
|
List loaded policies:
|
|
```bash
|
|
curl http://localhost:7012/internal/pdp/policies
|
|
```
|
|
|
|
## Policy Configuration
|
|
|
|
Edit `config.yaml`:
|
|
|
|
### MicroDAO Policies
|
|
```yaml
|
|
microdao_policies:
|
|
- microdao_id: "microdao:daarion"
|
|
owners: ["user:1"]
|
|
admins: ["user:1", "user:93"]
|
|
members: [] # All members
|
|
```
|
|
|
|
### Channel Policies
|
|
```yaml
|
|
channel_policies:
|
|
- channel_id: "channel-general"
|
|
microdao_id: "microdao:daarion"
|
|
allowed_roles: ["member", "admin", "owner"]
|
|
blocked_users: []
|
|
```
|
|
|
|
### Tool Policies
|
|
```yaml
|
|
tool_policies:
|
|
- tool_id: "projects.list"
|
|
enabled: true
|
|
allowed_agents: ["agent:sofia"]
|
|
allowed_user_roles: ["admin"]
|
|
```
|
|
|
|
### Agent Policies
|
|
```yaml
|
|
agent_policies:
|
|
- agent_id: "agent:sofia"
|
|
owner_id: "user:1"
|
|
microdao_id: "microdao:daarion"
|
|
```
|
|
|
|
## Policy Rules
|
|
|
|
### MicroDAO Access
|
|
- **Owners:** Full access (all actions)
|
|
- **Admins:** READ, WRITE, INVITE
|
|
- **Members:** READ only
|
|
|
|
### Channel Access
|
|
1. Must be microDAO member
|
|
2. Must not be blocked
|
|
3. Must have required role
|
|
4. SEND_MESSAGE: Additional rate limit checks
|
|
5. MANAGE: Admin+ only
|
|
|
|
### Tool Execution
|
|
1. Tool must be enabled
|
|
2. Actor in allowed_agents list
|
|
3. OR actor has required role
|
|
|
|
### Agent Management
|
|
- Agent owner: Full access
|
|
- MicroDAO admin: Full access
|
|
- Same microDAO: READ only
|
|
|
|
### Usage Viewing
|
|
- Own usage: Always allowed
|
|
- MicroDAO usage: Admin only
|
|
- All usage: System admin only
|
|
|
|
## Evaluation Flow
|
|
|
|
```
|
|
Request → PDP Service
|
|
↓
|
|
1. System Admin Check (bypass)
|
|
↓
|
|
2. Service-to-Service Check (trust)
|
|
↓
|
|
3. Resource-Specific Rules
|
|
├─ MicroDAO → Owner/Admin/Member
|
|
├─ Channel → Membership + Role
|
|
├─ Tool → Allowlist + Role
|
|
├─ Agent → Ownership
|
|
└─ Usage → Self + Admin
|
|
↓
|
|
4. Default Deny
|
|
↓
|
|
Decision (permit/deny + reason)
|
|
↓
|
|
Audit Log (security_audit table)
|
|
```
|
|
|
|
## Integration
|
|
|
|
### From Other Services
|
|
|
|
```python
|
|
import httpx
|
|
|
|
async def check_permission(actor, action, resource):
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.post(
|
|
"http://pdp-service:7012/internal/pdp/evaluate",
|
|
json={
|
|
"actor": actor.dict(),
|
|
"action": action,
|
|
"resource": resource.dict()
|
|
}
|
|
)
|
|
decision = response.json()
|
|
return decision["effect"] == "permit"
|
|
```
|
|
|
|
### Example: messaging-service
|
|
|
|
```python
|
|
# Before sending message
|
|
permitted = await check_permission(
|
|
actor=current_actor,
|
|
action="send_message",
|
|
resource={"type": "channel", "id": channel_id}
|
|
)
|
|
|
|
if not permitted:
|
|
raise HTTPException(403, "Access denied")
|
|
```
|
|
|
|
## Setup
|
|
|
|
### Local Development
|
|
```bash
|
|
cd services/pdp-service
|
|
pip install -r requirements.txt
|
|
export DATABASE_URL="postgresql://..."
|
|
python main.py
|
|
```
|
|
|
|
### Docker
|
|
```bash
|
|
docker build -t pdp-service .
|
|
docker run -p 7012:7012 \
|
|
-e DATABASE_URL="postgresql://..." \
|
|
-v $(pwd)/config.yaml:/app/config.yaml \
|
|
pdp-service
|
|
```
|
|
|
|
## Testing
|
|
|
|
### Unit Tests
|
|
```python
|
|
from engine import evaluate
|
|
from policy_store import PolicyStore
|
|
from models import *
|
|
|
|
store = PolicyStore()
|
|
|
|
# Test: Owner can manage microDAO
|
|
request = PolicyRequest(
|
|
actor=ActorIdentity(
|
|
actor_id="user:1",
|
|
actor_type="human",
|
|
roles=[]
|
|
),
|
|
action="manage",
|
|
resource=ResourceRef(
|
|
type="microdao",
|
|
id="microdao:daarion"
|
|
)
|
|
)
|
|
|
|
decision = evaluate(request, store)
|
|
assert decision.effect == "permit"
|
|
assert decision.reason == "microdao_owner"
|
|
```
|
|
|
|
### Integration Tests
|
|
```bash
|
|
# Start service
|
|
python main.py &
|
|
|
|
# Test evaluation
|
|
curl -X POST http://localhost:7012/internal/pdp/evaluate \
|
|
-d '{...}'
|
|
|
|
# Check policies
|
|
curl http://localhost:7012/internal/pdp/policies
|
|
```
|
|
|
|
## Audit Logging
|
|
|
|
Every policy decision is logged to `security_audit` table:
|
|
|
|
```sql
|
|
SELECT * FROM security_audit
|
|
WHERE actor_id = 'user:93'
|
|
ORDER BY timestamp DESC
|
|
LIMIT 10;
|
|
```
|
|
|
|
**Fields:**
|
|
- `actor_id`, `actor_type`
|
|
- `action`, `resource_type`, `resource_id`
|
|
- `decision` (permit/deny)
|
|
- `reason`
|
|
- `context` (JSONB)
|
|
- `timestamp`
|
|
|
|
## Roadmap
|
|
|
|
### Phase 4 (Current):
|
|
- ✅ Config-based policies
|
|
- ✅ 5+ policy types
|
|
- ✅ Audit logging
|
|
- ✅ Internal API
|
|
|
|
### Phase 5:
|
|
- 🔜 Database-backed policies
|
|
- 🔜 Dynamic policy updates
|
|
- 🔜 Policy versioning
|
|
- 🔜 ABAC (Attribute-Based Access Control)
|
|
- 🔜 Policy testing UI
|
|
- 🔜 Redis caching
|
|
|
|
## Troubleshooting
|
|
|
|
**Policies not loading?**
|
|
```bash
|
|
# Check config.yaml
|
|
cat config.yaml
|
|
|
|
# Check logs
|
|
docker logs pdp-service | grep "Loaded"
|
|
```
|
|
|
|
**Always deny?**
|
|
```bash
|
|
# Check actor has correct microDAO membership
|
|
# Check resource ID matches config
|
|
# Check audit log for reason
|
|
```
|
|
|
|
**Audit logging fails?**
|
|
```bash
|
|
# Check security_audit table exists
|
|
docker exec postgres psql -U postgres -d daarion \
|
|
-c "SELECT * FROM security_audit LIMIT 1;"
|
|
```
|
|
|
|
---
|
|
|
|
**Status:** ✅ Phase 4 Ready
|
|
**Version:** 1.0.0
|
|
**Last Updated:** 2025-11-24
|
|
|
|
|
|
|
|
|
|
|