Files
poimen-memory/docs/API.md
T
rock d9a143995a
Build and Push / Test (push) Successful in 4m39s
Build and Push / Build and push image (push) Successful in 5m57s
docs: API.md + RBAC.md with Authentik integration
Documentation:
- docs/API.md: Complete API reference with examples
  - All endpoints with curl examples
  - Python SDK example
  - Error responses and rate limits

- docs/RBAC.md: RBAC system documentation
  - Two-level access control explained
  - Built-in roles (admin, portfolio-agent, authenticated-user)
  - Authentik configuration guide
  - Scope mapping examples for roles/permissions
  - Troubleshooting guide

JWT Integration:
- Add 'roles' field to JwtClaims struct
- Wire roles from Authentik JWT to RBAC Claims
- API key users get 'admin' role by default

Tests:
- Add test_to_rbac_claims_with_roles
- Verify roles extraction from JWT
- 670 tests passing
2026-09-01 09:44:52 -07:00

415 lines
8.0 KiB
Markdown

# Memory API Reference
## Authentication
All endpoints require authentication via JWT token (from Authentik) or API key fallback.
### JWT Authentication (Recommended)
```bash
# Get token from Authentik
TOKEN=$(curl -s -X POST https://authentik.riotpiao.com/application/o/token/ \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" | jq -r '.access_token')
# Use token in requests
curl -H "Authorization: Bearer $TOKEN" \
http://memory.riotpiao.com/memory/query?project=homelab&query=kubernetes
```
### API Key Authentication (Fallback)
```bash
curl -H "apikey: YOUR_API_KEY" \
http://memory.riotpiao.com/memory/query?project=homelab&query=kubernetes
```
---
## Endpoints
### Health Check
```http
GET /health
```
**Response:**
```json
{
"status": "ok",
"uptime_secs": 3600
}
```
---
### Query Memory
Search learned knowledge using semantic + hybrid search.
```http
GET /memory/query?project={project}&query={query}&limit={limit}&method={method}
```
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| project | string | Yes | Project to search in |
| query | string | Yes | Search query |
| limit | int | No | Max results (default: 10) |
| method | string | No | `semantic` or `hybrid` (default: hybrid) |
**Example:**
```bash
curl -H "Authorization: Bearer $TOKEN" \
"http://memory.riotpiao.com/memory/query?project=homelab&query=fix%20kubernetes%20port%20conflict&limit=5"
```
**Response:**
```json
{
"query": "fix kubernetes port conflict",
"project": "homelab",
"method": "hybrid",
"results": [
{
"level": "L1",
"score": 0.92,
"text": "To fix port conflicts in Kubernetes...",
"source": "troubleshooting/ports.md",
"provenance": ["session-123"]
}
]
}
```
**RBAC:** Requires `memory:read` permission. Results filtered by user's project/visibility access.
---
### Context Lookup (Three-Tier RAG)
Get contextual knowledge for tool/task with failure diagnosis.
```http
POST /memory/context
Content-Type: application/json
```
**Body:**
```json
{
"project": "homelab",
"tool": "kubectl",
"task": "debug-pod",
"scope": "tool_context",
"budget": 8192,
"failure_log": "CrashLoopBackOff: container exited with code 1"
}
```
**Example:**
```bash
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"project":"homelab","tool":"kubectl","task":"debug-pod","budget":4096}' \
http://memory.riotpiao.com/memory/context
```
**Response:**
```json
{
"tier": 1,
"lessons": [
{
"tier": 1,
"level": "L1",
"score": 1.0,
"text": "CrashLoopBackOff usually means...",
"matched_kind": "symptom",
"seen_count": 15
}
],
"skills": [
{
"name": "diagnose-pod-failure",
"score": 0.95,
"description": "Debug Kubernetes pod crashes"
}
],
"budget": {
"limit": 4096,
"used": 2048,
"dropped": []
}
}
```
**RBAC:** Requires `memory:read` permission + project access.
---
### Ingest Records
Add new knowledge to memory.
```http
POST /memory/ingest
Content-Type: application/json
```
**Body:**
```json
{
"project": "homelab",
"ingest_id": "session-2024-01-15-001",
"source": "conversation://claude/session-123",
"records": [
{"text": "Kubernetes uses port 6443 for API server..."},
{"text": "To change the port, edit /etc/kubernetes/manifests/kube-apiserver.yaml"}
]
}
```
**Example:**
```bash
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"project":"homelab","ingest_id":"test-001","source":"manual","records":[{"text":"Test fact"}]}' \
http://memory.riotpiao.com/memory/ingest
```
**Response:**
```json
{
"status": "accepted",
"ingest_id": "test-001",
"records_queued": 1
}
```
**RBAC:** Requires `memory:write` permission + project write access.
---
### Learn from Text
Process and learn from a block of text (chunking + embedding + synthesis).
```http
POST /memory/learn
Content-Type: application/json
```
**Body:**
```json
{
"project": "homelab",
"text": "# Kubernetes Networking\n\nKubernetes uses CNI plugins...",
"query": "What are the key networking concepts?",
"chunk_size": 2000,
"memory_budget": 4096
}
```
**Example:**
```bash
curl -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"project":"homelab","text":"# Guide\nSome content...","query":"Summarize this"}' \
http://memory.riotpiao.com/memory/learn
```
**RBAC:** Requires `memory:write` permission + project write access.
---
### List Projects
Get all accessible projects.
```http
GET /memory/projects
```
**Example:**
```bash
curl -H "Authorization: Bearer $TOKEN" \
http://memory.riotpiao.com/memory/projects
```
**Response:**
```json
{
"projects": ["homelab", "portfolio"],
"count": 2
}
```
**RBAC:** Returns only projects user has read access to.
---
### List Skills
Get extracted skills.
```http
GET /memory/skills
```
**Response:**
```json
{
"skills": [
{
"name": "diagnose-pod-failure",
"description": "Debug Kubernetes pod issues",
"when_to_use": "Pod in CrashLoopBackOff or Error state"
}
],
"count": 1
}
```
**RBAC:** Requires `memory:read` permission.
---
### Ingest Status
Check status of an ingest job.
```http
GET /memory/ingest/{ingest_id}
```
**Example:**
```bash
curl -H "Authorization: Bearer $TOKEN" \
http://memory.riotpiao.com/memory/ingest/session-2024-01-15-001
```
**Response:**
```json
{
"ingest_id": "session-2024-01-15-001",
"status": "completed",
"records_processed": 5,
"created_at": "2024-01-15T10:30:00Z",
"completed_at": "2024-01-15T10:30:05Z"
}
```
---
## Error Responses
### 401 Unauthorized
```json
{
"error": "unauthorized",
"reason": "missing Authorization header"
}
```
### 403 Forbidden
```json
{
"error": "forbidden",
"reason": "missing capability: memory:write"
}
```
Or with RBAC:
```json
{
"error": "forbidden",
"reason": "access denied to project 'secret-project'"
}
```
### 429 Too Many Requests
```json
{
"error": "rate_limited",
"reason": "exceeded 1000 requests/hour for /memory/query"
}
```
---
## Rate Limits
| Endpoint | Limit |
|----------|-------|
| `/memory/ingest` | 100/hour |
| `/memory/query` | 1000/hour |
| `/memory/context` | 100/hour |
| `/memory/learn` | 100/hour |
Rate limits are per-user (based on JWT `sub` claim).
---
## SDK Examples
### Python
```python
import requests
class MemoryClient:
def __init__(self, base_url, token):
self.base_url = base_url
self.headers = {"Authorization": f"Bearer {token}"}
def query(self, project, query, limit=10):
resp = requests.get(
f"{self.base_url}/memory/query",
params={"project": project, "query": query, "limit": limit},
headers=self.headers
)
resp.raise_for_status()
return resp.json()
def ingest(self, project, records, source="api"):
import uuid
resp = requests.post(
f"{self.base_url}/memory/ingest",
json={
"project": project,
"ingest_id": str(uuid.uuid4()),
"source": source,
"records": [{"text": r} for r in records]
},
headers=self.headers
)
resp.raise_for_status()
return resp.json()
# Usage
client = MemoryClient("http://memory.riotpiao.com", TOKEN)
results = client.query("homelab", "kubernetes networking")
```
### curl One-Liners
```bash
# Query
curl -H "Authorization: Bearer $TOKEN" \
"http://memory.riotpiao.com/memory/query?project=homelab&query=kubernetes"
# Ingest
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"project":"homelab","ingest_id":"'$(uuidgen)'","source":"cli","records":[{"text":"New fact"}]}' \
http://memory.riotpiao.com/memory/ingest
# Context
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"project":"homelab","tool":"kubectl","task":"debug"}' \
http://memory.riotpiao.com/memory/context
```